(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.echarts = {}));
})(this, function (exports) {
  'use strict';
  /*! *****************************************************************************
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  this file except in compliance with the License. You may obtain a copy of the
  License at http://www.apache.org/licenses/LICENSE-2.0
    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  MERCHANTABLITY OR NON-INFRINGEMENT.
    See the Apache Version 2.0 License for specific language governing permissions
  and limitations under the License.
  ***************************************************************************** */

  /* global Reflect, Promise */

  var extendStatics = function (d, b) {
    extendStatics = Object.setPrototypeOf || {
      __proto__: []
    } instanceof Array && function (d, b) {
      d.__proto__ = b;
    } || function (d, b) {
      for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    };

    return extendStatics(d, b);
  };

  function __extends(d, b) {
    extendStatics(d, b);

    function __() {
      this.constructor = d;
    }

    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  }

  var __assign = function () {
    __assign = Object.assign || function __assign(t) {
      for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];

        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
      }

      return t;
    };

    return __assign.apply(this, arguments);
  };

  function __spreadArrays() {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;

    for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j];

    return r;
  }

  var Browser = function () {
    function Browser() {
      this.firefox = false;
      this.ie = false;
      this.edge = false;
      this.weChat = false;
    }

    return Browser;
  }();

  var Env = function () {
    function Env() {
      this.browser = new Browser();
      this.node = false;
      this.wxa = false;
      this.worker = false;
      this.canvasSupported = false;
      this.svgSupported = false;
      this.touchEventsSupported = false;
      this.pointerEventsSupported = false;
      this.domSupported = false;
    }

    return Env;
  }();

  var env = new Env();

  if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') {
    env.wxa = true;
    env.canvasSupported = true;
    env.touchEventsSupported = true;
  } else if (typeof document === 'undefined' && typeof self !== 'undefined') {
    env.worker = true;
    env.canvasSupported = true;
  } else if (typeof navigator === 'undefined') {
    env.node = true;
    env.canvasSupported = true;
    env.svgSupported = true;
  } else {
    detect(navigator.userAgent, env);
  }

  function detect(ua, env) {
    var browser = env.browser;
    var firefox = ua.match(/Firefox\/([\d.]+)/);
    var ie = ua.match(/MSIE\s([\d.]+)/) || ua.match(/Trident\/.+?rv:(([\d.]+))/);
    var edge = ua.match(/Edge\/([\d.]+)/);
    var weChat = /micromessenger/i.test(ua);

    if (firefox) {
      browser.firefox = true;
      browser.version = firefox[1];
    }

    if (ie) {
      browser.ie = true;
      browser.version = ie[1];
    }

    if (edge) {
      browser.edge = true;
      browser.version = edge[1];
    }

    if (weChat) {
      browser.weChat = true;
    }

    env.canvasSupported = !!document.createElement('canvas').getContext;
    env.svgSupported = typeof SVGRect !== 'undefined';
    env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge;
    env.pointerEventsSupported = 'onpointerdown' in window && (browser.edge || browser.ie && +browser.version >= 11);
    env.domSupported = typeof document !== 'undefined';
  }

  var BUILTIN_OBJECT = {
    '[object Function]': true,
    '[object RegExp]': true,
    '[object Date]': true,
    '[object Error]': true,
    '[object CanvasGradient]': true,
    '[object CanvasPattern]': true,
    '[object Image]': true,
    '[object Canvas]': true
  };
  var TYPED_ARRAY = {
    '[object Int8Array]': true,
    '[object Uint8Array]': true,
    '[object Uint8ClampedArray]': true,
    '[object Int16Array]': true,
    '[object Uint16Array]': true,
    '[object Int32Array]': true,
    '[object Uint32Array]': true,
    '[object Float32Array]': true,
    '[object Float64Array]': true
  };
  var objToString = Object.prototype.toString;
  var arrayProto = Array.prototype;
  var nativeForEach = arrayProto.forEach;
  var nativeFilter = arrayProto.filter;
  var nativeSlice = arrayProto.slice;
  var nativeMap = arrayProto.map;

  var ctorFunction = function () {}.constructor;

  var protoFunction = ctorFunction ? ctorFunction.prototype : null;
  var methods = {};

  function $override(name, fn) {
    methods[name] = fn;
  }

  var idStart = 0x0907;

  function guid() {
    return idStart++;
  }

  function logError() {
    var args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }

    if (typeof console !== 'undefined') {
      console.error.apply(console, args);
    }
  }

  function clone(source) {
    if (source == null || typeof source !== 'object') {
      return source;
    }

    var result = source;
    var typeStr = objToString.call(source);

    if (typeStr === '[object Array]') {
      if (!isPrimitive(source)) {
        result = [];

        for (var i = 0, len = source.length; i < len; i++) {
          result[i] = clone(source[i]);
        }
      }
    } else if (TYPED_ARRAY[typeStr]) {
      if (!isPrimitive(source)) {
        var Ctor = source.constructor;

        if (Ctor.from) {
          result = Ctor.from(source);
        } else {
          result = new Ctor(source.length);

          for (var i = 0, len = source.length; i < len; i++) {
            result[i] = clone(source[i]);
          }
        }
      }
    } else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
      result = {};

      for (var key in source) {
        if (source.hasOwnProperty(key)) {
          result[key] = clone(source[key]);
        }
      }
    }

    return result;
  }

  function merge(target, source, overwrite) {
    if (!isObject(source) || !isObject(target)) {
      return overwrite ? clone(source) : target;
    }

    for (var key in source) {
      if (source.hasOwnProperty(key)) {
        var targetProp = target[key];
        var sourceProp = source[key];

        if (isObject(sourceProp) && isObject(targetProp) && !isArray(sourceProp) && !isArray(targetProp) && !isDom(sourceProp) && !isDom(targetProp) && !isBuiltInObject(sourceProp) && !isBuiltInObject(targetProp) && !isPrimitive(sourceProp) && !isPrimitive(targetProp)) {
          merge(targetProp, sourceProp, overwrite);
        } else if (overwrite || !(key in target)) {
          target[key] = clone(source[key]);
        }
      }
    }

    return target;
  }

  function mergeAll(targetAndSources, overwrite) {
    var result = targetAndSources[0];

    for (var i = 1, len = targetAndSources.length; i < len; i++) {
      result = merge(result, targetAndSources[i], overwrite);
    }

    return result;
  }

  function extend(target, source) {
    if (Object.assign) {
      Object.assign(target, source);
    } else {
      for (var key in source) {
        if (source.hasOwnProperty(key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  }

  function defaults(target, source, overlay) {
    var keysArr = keys(source);

    for (var i = 0; i < keysArr.length; i++) {
      var key = keysArr[i];

      if (overlay ? source[key] != null : target[key] == null) {
        target[key] = source[key];
      }
    }

    return target;
  }

  var createCanvas = function () {
    return methods.createCanvas();
  };

  methods.createCanvas = function () {
    return document.createElement('canvas');
  };

  function indexOf(array, value) {
    if (array) {
      if (array.indexOf) {
        return array.indexOf(value);
      }

      for (var i = 0, len = array.length; i < len; i++) {
        if (array[i] === value) {
          return i;
        }
      }
    }

    return -1;
  }

  function inherits(clazz, baseClazz) {
    var clazzPrototype = clazz.prototype;

    function F() {}

    F.prototype = baseClazz.prototype;
    clazz.prototype = new F();

    for (var prop in clazzPrototype) {
      if (clazzPrototype.hasOwnProperty(prop)) {
        clazz.prototype[prop] = clazzPrototype[prop];
      }
    }

    clazz.prototype.constructor = clazz;
    clazz.superClass = baseClazz;
  }

  function mixin(target, source, override) {
    target = 'prototype' in target ? target.prototype : target;
    source = 'prototype' in source ? source.prototype : source;

    if (Object.getOwnPropertyNames) {
      var keyList = Object.getOwnPropertyNames(source);

      for (var i = 0; i < keyList.length; i++) {
        var key = keyList[i];

        if (key !== 'constructor') {
          if (override ? source[key] != null : target[key] == null) {
            target[key] = source[key];
          }
        }
      }
    } else {
      defaults(target, source, override);
    }
  }

  function isArrayLike(data) {
    if (!data) {
      return false;
    }

    if (typeof data === 'string') {
      return false;
    }

    return typeof data.length === 'number';
  }

  function each(arr, cb, context) {
    if (!(arr && cb)) {
      return;
    }

    if (arr.forEach && arr.forEach === nativeForEach) {
      arr.forEach(cb, context);
    } else if (arr.length === +arr.length) {
      for (var i = 0, len = arr.length; i < len; i++) {
        cb.call(context, arr[i], i, arr);
      }
    } else {
      for (var key in arr) {
        if (arr.hasOwnProperty(key)) {
          cb.call(context, arr[key], key, arr);
        }
      }
    }
  }

  function map(arr, cb, context) {
    if (!arr) {
      return [];
    }

    if (!cb) {
      return slice(arr);
    }

    if (arr.map && arr.map === nativeMap) {
      return arr.map(cb, context);
    } else {
      var result = [];

      for (var i = 0, len = arr.length; i < len; i++) {
        result.push(cb.call(context, arr[i], i, arr));
      }

      return result;
    }
  }

  function reduce(arr, cb, memo, context) {
    if (!(arr && cb)) {
      return;
    }

    for (var i = 0, len = arr.length; i < len; i++) {
      memo = cb.call(context, memo, arr[i], i, arr);
    }

    return memo;
  }

  function filter(arr, cb, context) {
    if (!arr) {
      return [];
    }

    if (!cb) {
      return slice(arr);
    }

    if (arr.filter && arr.filter === nativeFilter) {
      return arr.filter(cb, context);
    } else {
      var result = [];

      for (var i = 0, len = arr.length; i < len; i++) {
        if (cb.call(context, arr[i], i, arr)) {
          result.push(arr[i]);
        }
      }

      return result;
    }
  }

  function find(arr, cb, context) {
    if (!(arr && cb)) {
      return;
    }

    for (var i = 0, len = arr.length; i < len; i++) {
      if (cb.call(context, arr[i], i, arr)) {
        return arr[i];
      }
    }
  }

  function keys(obj) {
    if (!obj) {
      return [];
    }

    if (Object.keys) {
      return Object.keys(obj);
    }

    var keyList = [];

    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        keyList.push(key);
      }
    }

    return keyList;
  }

  function bindPolyfill(func, context) {
    var args = [];

    for (var _i = 2; _i < arguments.length; _i++) {
      args[_i - 2] = arguments[_i];
    }

    return function () {
      return func.apply(context, args.concat(nativeSlice.call(arguments)));
    };
  }

  var bind = protoFunction && isFunction(protoFunction.bind) ? protoFunction.call.bind(protoFunction.bind) : bindPolyfill;

  function curry(func) {
    var args = [];

    for (var _i = 1; _i < arguments.length; _i++) {
      args[_i - 1] = arguments[_i];
    }

    return function () {
      return func.apply(this, args.concat(nativeSlice.call(arguments)));
    };
  }

  function isArray(value) {
    if (Array.isArray) {
      return Array.isArray(value);
    }

    return objToString.call(value) === '[object Array]';
  }

  function isFunction(value) {
    return typeof value === 'function';
  }

  function isString(value) {
    return typeof value === 'string';
  }

  function isStringSafe(value) {
    return objToString.call(value) === '[object String]';
  }

  function isNumber(value) {
    return typeof value === 'number';
  }

  function isObject(value) {
    var type = typeof value;
    return type === 'function' || !!value && type === 'object';
  }

  function isBuiltInObject(value) {
    return !!BUILTIN_OBJECT[objToString.call(value)];
  }

  function isTypedArray(value) {
    return !!TYPED_ARRAY[objToString.call(value)];
  }

  function isDom(value) {
    return typeof value === 'object' && typeof value.nodeType === 'number' && typeof value.ownerDocument === 'object';
  }

  function isGradientObject(value) {
    return value.colorStops != null;
  }

  function isPatternObject(value) {
    return value.image != null;
  }

  function isRegExp(value) {
    return objToString.call(value) === '[object RegExp]';
  }

  function eqNaN(value) {
    return value !== value;
  }

  function retrieve() {
    var args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }

    for (var i = 0, len = args.length; i < len; i++) {
      if (args[i] != null) {
        return args[i];
      }
    }
  }

  function retrieve2(value0, value1) {
    return value0 != null ? value0 : value1;
  }

  function retrieve3(value0, value1, value2) {
    return value0 != null ? value0 : value1 != null ? value1 : value2;
  }

  function slice(arr) {
    var args = [];

    for (var _i = 1; _i < arguments.length; _i++) {
      args[_i - 1] = arguments[_i];
    }

    return nativeSlice.apply(arr, args);
  }

  function normalizeCssArray(val) {
    if (typeof val === 'number') {
      return [val, val, val, val];
    }

    var len = val.length;

    if (len === 2) {
      return [val[0], val[1], val[0], val[1]];
    } else if (len === 3) {
      return [val[0], val[1], val[2], val[1]];
    }

    return val;
  }

  function assert(condition, message) {
    if (!condition) {
      throw new Error(message);
    }
  }

  function trim(str) {
    if (str == null) {
      return null;
    } else if (typeof str.trim === 'function') {
      return str.trim();
    } else {
      return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    }
  }

  var primitiveKey = '__ec_primitive__';

  function setAsPrimitive(obj) {
    obj[primitiveKey] = true;
  }

  function isPrimitive(obj) {
    return obj[primitiveKey];
  }

  var HashMap = function () {
    function HashMap(obj) {
      this.data = {};
      var isArr = isArray(obj);
      this.data = {};
      var thisMap = this;
      obj instanceof HashMap ? obj.each(visit) : obj && each(obj, visit);

      function visit(value, key) {
        isArr ? thisMap.set(value, key) : thisMap.set(key, value);
      }
    }

    HashMap.prototype.get = function (key) {
      return this.data.hasOwnProperty(key) ? this.data[key] : null;
    };

    HashMap.prototype.set = function (key, value) {
      return this.data[key] = value;
    };

    HashMap.prototype.each = function (cb, context) {
      for (var key in this.data) {
        if (this.data.hasOwnProperty(key)) {
          cb.call(context, this.data[key], key);
        }
      }
    };

    HashMap.prototype.keys = function () {
      return keys(this.data);
    };

    HashMap.prototype.removeKey = function (key) {
      delete this.data[key];
    };

    return HashMap;
  }();

  function createHashMap(obj) {
    return new HashMap(obj);
  }

  function concatArray(a, b) {
    var newArray = new a.constructor(a.length + b.length);

    for (var i = 0; i < a.length; i++) {
      newArray[i] = a[i];
    }

    var offset = a.length;

    for (var i = 0; i < b.length; i++) {
      newArray[i + offset] = b[i];
    }

    return newArray;
  }

  function createObject(proto, properties) {
    var obj;

    if (Object.create) {
      obj = Object.create(proto);
    } else {
      var StyleCtor = function () {};

      StyleCtor.prototype = proto;
      obj = new StyleCtor();
    }

    if (properties) {
      extend(obj, properties);
    }

    return obj;
  }

  function hasOwn(own, prop) {
    return own.hasOwnProperty(prop);
  }

  function noop() {}

  var zrUtil = /*#__PURE__*/Object.freeze({
    __proto__: null,
    $override: $override,
    guid: guid,
    logError: logError,
    clone: clone,
    merge: merge,
    mergeAll: mergeAll,
    extend: extend,
    defaults: defaults,
    createCanvas: createCanvas,
    indexOf: indexOf,
    inherits: inherits,
    mixin: mixin,
    isArrayLike: isArrayLike,
    each: each,
    map: map,
    reduce: reduce,
    filter: filter,
    find: find,
    keys: keys,
    bind: bind,
    curry: curry,
    isArray: isArray,
    isFunction: isFunction,
    isString: isString,
    isStringSafe: isStringSafe,
    isNumber: isNumber,
    isObject: isObject,
    isBuiltInObject: isBuiltInObject,
    isTypedArray: isTypedArray,
    isDom: isDom,
    isGradientObject: isGradientObject,
    isPatternObject: isPatternObject,
    isRegExp: isRegExp,
    eqNaN: eqNaN,
    retrieve: retrieve,
    retrieve2: retrieve2,
    retrieve3: retrieve3,
    slice: slice,
    normalizeCssArray: normalizeCssArray,
    assert: assert,
    trim: trim,
    setAsPrimitive: setAsPrimitive,
    isPrimitive: isPrimitive,
    HashMap: HashMap,
    createHashMap: createHashMap,
    concatArray: concatArray,
    createObject: createObject,
    hasOwn: hasOwn,
    noop: noop
  });

  function create(x, y) {
    if (x == null) {
      x = 0;
    }

    if (y == null) {
      y = 0;
    }

    return [x, y];
  }

  function copy(out, v) {
    out[0] = v[0];
    out[1] = v[1];
    return out;
  }

  function clone$1(v) {
    return [v[0], v[1]];
  }

  function set(out, a, b) {
    out[0] = a;
    out[1] = b;
    return out;
  }

  function add(out, v1, v2) {
    out[0] = v1[0] + v2[0];
    out[1] = v1[1] + v2[1];
    return out;
  }

  function scaleAndAdd(out, v1, v2, a) {
    out[0] = v1[0] + v2[0] * a;
    out[1] = v1[1] + v2[1] * a;
    return out;
  }

  function sub(out, v1, v2) {
    out[0] = v1[0] - v2[0];
    out[1] = v1[1] - v2[1];
    return out;
  }

  function len(v) {
    return Math.sqrt(lenSquare(v));
  }

  var length = len;

  function lenSquare(v) {
    return v[0] * v[0] + v[1] * v[1];
  }

  var lengthSquare = lenSquare;

  function mul(out, v1, v2) {
    out[0] = v1[0] * v2[0];
    out[1] = v1[1] * v2[1];
    return out;
  }

  function div(out, v1, v2) {
    out[0] = v1[0] / v2[0];
    out[1] = v1[1] / v2[1];
    return out;
  }

  function dot(v1, v2) {
    return v1[0] * v2[0] + v1[1] * v2[1];
  }

  function scale(out, v, s) {
    out[0] = v[0] * s;
    out[1] = v[1] * s;
    return out;
  }

  function normalize(out, v) {
    var d = len(v);

    if (d === 0) {
      out[0] = 0;
      out[1] = 0;
    } else {
      out[0] = v[0] / d;
      out[1] = v[1] / d;
    }

    return out;
  }

  function distance(v1, v2) {
    return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]));
  }

  var dist = distance;

  function distanceSquare(v1, v2) {
    return (v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]);
  }

  var distSquare = distanceSquare;

  function negate(out, v) {
    out[0] = -v[0];
    out[1] = -v[1];
    return out;
  }

  function lerp(out, v1, v2, t) {
    out[0] = v1[0] + t * (v2[0] - v1[0]);
    out[1] = v1[1] + t * (v2[1] - v1[1]);
    return out;
  }

  function applyTransform(out, v, m) {
    var x = v[0];
    var y = v[1];
    out[0] = m[0] * x + m[2] * y + m[4];
    out[1] = m[1] * x + m[3] * y + m[5];
    return out;
  }

  function min(out, v1, v2) {
    out[0] = Math.min(v1[0], v2[0]);
    out[1] = Math.min(v1[1], v2[1]);
    return out;
  }

  function max(out, v1, v2) {
    out[0] = Math.max(v1[0], v2[0]);
    out[1] = Math.max(v1[1], v2[1]);
    return out;
  }

  var vector = /*#__PURE__*/Object.freeze({
    __proto__: null,
    create: create,
    copy: copy,
    clone: clone$1,
    set: set,
    add: add,
    scaleAndAdd: scaleAndAdd,
    sub: sub,
    len: len,
    length: length,
    lenSquare: lenSquare,
    lengthSquare: lengthSquare,
    mul: mul,
    div: div,
    dot: dot,
    scale: scale,
    normalize: normalize,
    distance: distance,
    dist: dist,
    distanceSquare: distanceSquare,
    distSquare: distSquare,
    negate: negate,
    lerp: lerp,
    applyTransform: applyTransform,
    min: min,
    max: max
  });

  var Param = function () {
    function Param(target, e) {
      this.target = target;
      this.topTarget = e && e.topTarget;
    }

    return Param;
  }();

  var Draggable = function () {
    function Draggable(handler) {
      this.handler = handler;
      handler.on('mousedown', this._dragStart, this);
      handler.on('mousemove', this._drag, this);
      handler.on('mouseup', this._dragEnd, this);
    }

    Draggable.prototype._dragStart = function (e) {
      var draggingTarget = e.target;

      while (draggingTarget && !draggingTarget.draggable) {
        draggingTarget = draggingTarget.parent;
      }

      if (draggingTarget) {
        this._draggingTarget = draggingTarget;
        draggingTarget.dragging = true;
        this._x = e.offsetX;
        this._y = e.offsetY;
        this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragstart', e.event);
      }
    };

    Draggable.prototype._drag = function (e) {
      var draggingTarget = this._draggingTarget;

      if (draggingTarget) {
        var x = e.offsetX;
        var y = e.offsetY;
        var dx = x - this._x;
        var dy = y - this._y;
        this._x = x;
        this._y = y;
        draggingTarget.drift(dx, dy, e);
        this.handler.dispatchToElement(new Param(draggingTarget, e), 'drag', e.event);
        var dropTarget = this.handler.findHover(x, y, draggingTarget).target;
        var lastDropTarget = this._dropTarget;
        this._dropTarget = dropTarget;

        if (draggingTarget !== dropTarget) {
          if (lastDropTarget && dropTarget !== lastDropTarget) {
            this.handler.dispatchToElement(new Param(lastDropTarget, e), 'dragleave', e.event);
          }

          if (dropTarget && dropTarget !== lastDropTarget) {
            this.handler.dispatchToElement(new Param(dropTarget, e), 'dragenter', e.event);
          }
        }
      }
    };

    Draggable.prototype._dragEnd = function (e) {
      var draggingTarget = this._draggingTarget;

      if (draggingTarget) {
        draggingTarget.dragging = false;
      }

      this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragend', e.event);

      if (this._dropTarget) {
        this.handler.dispatchToElement(new Param(this._dropTarget, e), 'drop', e.event);
      }

      this._draggingTarget = null;
      this._dropTarget = null;
    };

    return Draggable;
  }();

  var Eventful = function () {
    function Eventful(eventProcessors) {
      if (eventProcessors) {
        this._$eventProcessor = eventProcessors;
      }
    }

    Eventful.prototype.on = function (event, query, handler, context) {
      if (!this._$handlers) {
        this._$handlers = {};
      }

      var _h = this._$handlers;

      if (typeof query === 'function') {
        context = handler;
        handler = query;
        query = null;
      }

      if (!handler || !event) {
        return this;
      }

      var eventProcessor = this._$eventProcessor;

      if (query != null && eventProcessor && eventProcessor.normalizeQuery) {
        query = eventProcessor.normalizeQuery(query);
      }

      if (!_h[event]) {
        _h[event] = [];
      }

      for (var i = 0; i < _h[event].length; i++) {
        if (_h[event][i].h === handler) {
          return this;
        }
      }

      var wrap = {
        h: handler,
        query: query,
        ctx: context || this,
        callAtLast: handler.zrEventfulCallAtLast
      };
      var lastIndex = _h[event].length - 1;
      var lastWrap = _h[event][lastIndex];
      lastWrap && lastWrap.callAtLast ? _h[event].splice(lastIndex, 0, wrap) : _h[event].push(wrap);
      return this;
    };

    Eventful.prototype.isSilent = function (eventName) {
      var _h = this._$handlers;
      return !_h || !_h[eventName] || !_h[eventName].length;
    };

    Eventful.prototype.off = function (eventType, handler) {
      var _h = this._$handlers;

      if (!_h) {
        return this;
      }

      if (!eventType) {
        this._$handlers = {};
        return this;
      }

      if (handler) {
        if (_h[eventType]) {
          var newList = [];

          for (var i = 0, l = _h[eventType].length; i < l; i++) {
            if (_h[eventType][i].h !== handler) {
              newList.push(_h[eventType][i]);
            }
          }

          _h[eventType] = newList;
        }

        if (_h[eventType] && _h[eventType].length === 0) {
          delete _h[eventType];
        }
      } else {
        delete _h[eventType];
      }

      return this;
    };

    Eventful.prototype.trigger = function (eventType) {
      var args = [];

      for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
      }

      if (!this._$handlers) {
        return this;
      }

      var _h = this._$handlers[eventType];
      var eventProcessor = this._$eventProcessor;

      if (_h) {
        var argLen = args.length;
        var len = _h.length;

        for (var i = 0; i < len; i++) {
          var hItem = _h[i];

          if (eventProcessor && eventProcessor.filter && hItem.query != null && !eventProcessor.filter(eventType, hItem.query)) {
            continue;
          }

          switch (argLen) {
            case 0:
              hItem.h.call(hItem.ctx);
              break;

            case 1:
              hItem.h.call(hItem.ctx, args[0]);
              break;

            case 2:
              hItem.h.call(hItem.ctx, args[0], args[1]);
              break;

            default:
              hItem.h.apply(hItem.ctx, args);
              break;
          }
        }
      }

      eventProcessor && eventProcessor.afterTrigger && eventProcessor.afterTrigger(eventType);
      return this;
    };

    Eventful.prototype.triggerWithContext = function (type) {
      if (!this._$handlers) {
        return this;
      }

      var _h = this._$handlers[type];
      var eventProcessor = this._$eventProcessor;

      if (_h) {
        var args = arguments;
        var argLen = args.length;
        var ctx = args[argLen - 1];
        var len = _h.length;

        for (var i = 0; i < len; i++) {
          var hItem = _h[i];

          if (eventProcessor && eventProcessor.filter && hItem.query != null && !eventProcessor.filter(type, hItem.query)) {
            continue;
          }

          switch (argLen) {
            case 0:
              hItem.h.call(ctx);
              break;

            case 1:
              hItem.h.call(ctx, args[0]);
              break;

            case 2:
              hItem.h.call(ctx, args[0], args[1]);
              break;

            default:
              hItem.h.apply(ctx, args.slice(1, argLen - 1));
              break;
          }
        }
      }

      eventProcessor && eventProcessor.afterTrigger && eventProcessor.afterTrigger(type);
      return this;
    };

    return Eventful;
  }();

  var LN2 = Math.log(2);

  function determinant(rows, rank, rowStart, rowMask, colMask, detCache) {
    var cacheKey = rowMask + '-' + colMask;
    var fullRank = rows.length;

    if (detCache.hasOwnProperty(cacheKey)) {
      return detCache[cacheKey];
    }

    if (rank === 1) {
      var colStart = Math.round(Math.log((1 << fullRank) - 1 & ~colMask) / LN2);
      return rows[rowStart][colStart];
    }

    var subRowMask = rowMask | 1 << rowStart;
    var subRowStart = rowStart + 1;

    while (rowMask & 1 << subRowStart) {
      subRowStart++;
    }

    var sum = 0;

    for (var j = 0, colLocalIdx = 0; j < fullRank; j++) {
      var colTag = 1 << j;

      if (!(colTag & colMask)) {
        sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j] * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache);
        colLocalIdx++;
      }
    }

    detCache[cacheKey] = sum;
    return sum;
  }

  function buildTransformer(src, dest) {
    var mA = [[src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]], [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]], [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]], [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]], [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]], [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]], [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]], [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]]];
    var detCache = {};
    var det = determinant(mA, 8, 0, 0, 0, detCache);

    if (det === 0) {
      return;
    }

    var vh = [];

    for (var i = 0; i < 8; i++) {
      for (var j = 0; j < 8; j++) {
        vh[j] == null && (vh[j] = 0);
        vh[j] += ((i + j) % 2 ? -1 : 1) * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache) / det * dest[i];
      }
    }

    return function (out, srcPointX, srcPointY) {
      var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1;
      out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk;
      out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk;
    };
  }

  var EVENT_SAVED_PROP = '___zrEVENTSAVED';
  var _calcOut = [];

  function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
    return transformCoordWithViewport(_calcOut, elFrom, inX, inY, true) && transformCoordWithViewport(out, elTarget, _calcOut[0], _calcOut[1]);
  }

  function transformCoordWithViewport(out, el, inX, inY, inverse) {
    if (el.getBoundingClientRect && env.domSupported && !isCanvasEl(el)) {
      var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
      var markers = prepareCoordMarkers(el, saved);
      var transformer = preparePointerTransformer(markers, saved, inverse);

      if (transformer) {
        transformer(out, inX, inY);
        return true;
      }
    }

    return false;
  }

  function prepareCoordMarkers(el, saved) {
    var markers = saved.markers;

    if (markers) {
      return markers;
    }

    markers = saved.markers = [];
    var propLR = ['left', 'right'];
    var propTB = ['top', 'bottom'];

    for (var i = 0; i < 4; i++) {
      var marker = document.createElement('div');
      var stl = marker.style;
      var idxLR = i % 2;
      var idxTB = (i >> 1) % 2;
      stl.cssText = ['position: absolute', 'visibility: hidden', 'padding: 0', 'margin: 0', 'border-width: 0', 'user-select: none', 'width:0', 'height:0', propLR[idxLR] + ':0', propTB[idxTB] + ':0', propLR[1 - idxLR] + ':auto', propTB[1 - idxTB] + ':auto', ''].join('!important;');
      el.appendChild(marker);
      markers.push(marker);
    }

    return markers;
  }

  function preparePointerTransformer(markers, saved, inverse) {
    var transformerName = inverse ? 'invTrans' : 'trans';
    var transformer = saved[transformerName];
    var oldSrcCoords = saved.srcCoords;
    var srcCoords = [];
    var destCoords = [];
    var oldCoordTheSame = true;

    for (var i = 0; i < 4; i++) {
      var rect = markers[i].getBoundingClientRect();
      var ii = 2 * i;
      var x = rect.left;
      var y = rect.top;
      srcCoords.push(x, y);
      oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
      destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
    }

    return oldCoordTheSame && transformer ? transformer : (saved.srcCoords = srcCoords, saved[transformerName] = inverse ? buildTransformer(destCoords, srcCoords) : buildTransformer(srcCoords, destCoords));
  }

  function isCanvasEl(el) {
    return el.nodeName.toUpperCase() === 'CANVAS';
  }

  var isDomLevel2 = typeof window !== 'undefined' && !!window.addEventListener;
  var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
  var _calcOut$1 = [];

  function clientToLocal(el, e, out, calculate) {
    out = out || {};

    if (calculate || !env.canvasSupported) {
      calculateZrXY(el, e, out);
    } else if (env.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) {
      out.zrX = e.layerX;
      out.zrY = e.layerY;
    } else if (e.offsetX != null) {
      out.zrX = e.offsetX;
      out.zrY = e.offsetY;
    } else {
      calculateZrXY(el, e, out);
    }

    return out;
  }

  function calculateZrXY(el, e, out) {
    if (env.domSupported && el.getBoundingClientRect) {
      var ex = e.clientX;
      var ey = e.clientY;

      if (isCanvasEl(el)) {
        var box = el.getBoundingClientRect();
        out.zrX = ex - box.left;
        out.zrY = ey - box.top;
        return;
      } else {
        if (transformCoordWithViewport(_calcOut$1, el, ex, ey)) {
          out.zrX = _calcOut$1[0];
          out.zrY = _calcOut$1[1];
          return;
        }
      }
    }

    out.zrX = out.zrY = 0;
  }

  function getNativeEvent(e) {
    return e || window.event;
  }

  function normalizeEvent(el, e, calculate) {
    e = getNativeEvent(e);

    if (e.zrX != null) {
      return e;
    }

    var eventType = e.type;
    var isTouch = eventType && eventType.indexOf('touch') >= 0;

    if (!isTouch) {
      clientToLocal(el, e, e, calculate);
      var wheelDelta = getWheelDeltaMayPolyfill(e);
      e.zrDelta = wheelDelta ? wheelDelta / 120 : -(e.detail || 0) / 3;
    } else {
      var touch = eventType !== 'touchend' ? e.targetTouches[0] : e.changedTouches[0];
      touch && clientToLocal(el, touch, e, calculate);
    }

    var button = e.button;

    if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) {
      e.which = button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0;
    }

    return e;
  }

  function getWheelDeltaMayPolyfill(e) {
    var rawWheelDelta = e.wheelDelta;

    if (rawWheelDelta) {
      return rawWheelDelta;
    }

    var deltaX = e.deltaX;
    var deltaY = e.deltaY;

    if (deltaX == null || deltaY == null) {
      return rawWheelDelta;
    }

    var delta = deltaY !== 0 ? Math.abs(deltaY) : Math.abs(deltaX);
    var sign = deltaY > 0 ? -1 : deltaY < 0 ? 1 : deltaX > 0 ? -1 : 1;
    return 3 * delta * sign;
  }

  function addEventListener(el, name, handler, opt) {
    if (isDomLevel2) {
      el.addEventListener(name, handler, opt);
    } else {
      el.attachEvent('on' + name, handler);
    }
  }

  function removeEventListener(el, name, handler, opt) {
    if (isDomLevel2) {
      el.removeEventListener(name, handler, opt);
    } else {
      el.detachEvent('on' + name, handler);
    }
  }

  var stop = isDomLevel2 ? function (e) {
    e.preventDefault();
    e.stopPropagation();
    e.cancelBubble = true;
  } : function (e) {
    e.returnValue = false;
    e.cancelBubble = true;
  };

  function isMiddleOrRightButtonOnMouseUpDown(e) {
    return e.which === 2 || e.which === 3;
  }

  var GestureMgr = function () {
    function GestureMgr() {
      this._track = [];
    }

    GestureMgr.prototype.recognize = function (event, target, root) {
      this._doTrack(event, target, root);

      return this._recognize(event);
    };

    GestureMgr.prototype.clear = function () {
      this._track.length = 0;
      return this;
    };

    GestureMgr.prototype._doTrack = function (event, target, root) {
      var touches = event.touches;

      if (!touches) {
        return;
      }

      var trackItem = {
        points: [],
        touches: [],
        target: target,
        event: event
      };

      for (var i = 0, len = touches.length; i < len; i++) {
        var touch = touches[i];
        var pos = clientToLocal(root, touch, {});
        trackItem.points.push([pos.zrX, pos.zrY]);
        trackItem.touches.push(touch);
      }

      this._track.push(trackItem);
    };

    GestureMgr.prototype._recognize = function (event) {
      for (var eventName in recognizers) {
        if (recognizers.hasOwnProperty(eventName)) {
          var gestureInfo = recognizers[eventName](this._track, event);

          if (gestureInfo) {
            return gestureInfo;
          }
        }
      }
    };

    return GestureMgr;
  }();

  function dist$1(pointPair) {
    var dx = pointPair[1][0] - pointPair[0][0];
    var dy = pointPair[1][1] - pointPair[0][1];
    return Math.sqrt(dx * dx + dy * dy);
  }

  function center(pointPair) {
    return [(pointPair[0][0] + pointPair[1][0]) / 2, (pointPair[0][1] + pointPair[1][1]) / 2];
  }

  var recognizers = {
    pinch: function (tracks, event) {
      var trackLen = tracks.length;

      if (!trackLen) {
        return;
      }

      var pinchEnd = (tracks[trackLen - 1] || {}).points;
      var pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd;

      if (pinchPre && pinchPre.length > 1 && pinchEnd && pinchEnd.length > 1) {
        var pinchScale = dist$1(pinchEnd) / dist$1(pinchPre);
        !isFinite(pinchScale) && (pinchScale = 1);
        event.pinchScale = pinchScale;
        var pinchCenter = center(pinchEnd);
        event.pinchX = pinchCenter[0];
        event.pinchY = pinchCenter[1];
        return {
          type: 'pinch',
          target: tracks[0].target,
          event: event
        };
      }
    }
  };
  var SILENT = 'silent';

  function makeEventPacket(eveType, targetInfo, event) {
    return {
      type: eveType,
      event: event,
      target: targetInfo.target,
      topTarget: targetInfo.topTarget,
      cancelBubble: false,
      offsetX: event.zrX,
      offsetY: event.zrY,
      gestureEvent: event.gestureEvent,
      pinchX: event.pinchX,
      pinchY: event.pinchY,
      pinchScale: event.pinchScale,
      wheelDelta: event.zrDelta,
      zrByTouch: event.zrByTouch,
      which: event.which,
      stop: stopEvent
    };
  }

  function stopEvent() {
    stop(this.event);
  }

  var EmptyProxy = function (_super) {
    __extends(EmptyProxy, _super);

    function EmptyProxy() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.handler = null;
      return _this;
    }

    EmptyProxy.prototype.dispose = function () {};

    EmptyProxy.prototype.setCursor = function () {};

    return EmptyProxy;
  }(Eventful);

  var HoveredResult = function () {
    function HoveredResult(x, y) {
      this.x = x;
      this.y = y;
    }

    return HoveredResult;
  }();

  var handlerNames = ['click', 'dblclick', 'mousewheel', 'mouseout', 'mouseup', 'mousedown', 'mousemove', 'contextmenu'];

  var Handler = function (_super) {
    __extends(Handler, _super);

    function Handler(storage, painter, proxy, painterRoot) {
      var _this = _super.call(this) || this;

      _this._hovered = new HoveredResult(0, 0);
      _this.storage = storage;
      _this.painter = painter;
      _this.painterRoot = painterRoot;
      proxy = proxy || new EmptyProxy();
      _this.proxy = null;

      _this.setHandlerProxy(proxy);

      _this._draggingMgr = new Draggable(_this);
      return _this;
    }

    Handler.prototype.setHandlerProxy = function (proxy) {
      if (this.proxy) {
        this.proxy.dispose();
      }

      if (proxy) {
        each(handlerNames, function (name) {
          proxy.on && proxy.on(name, this[name], this);
        }, this);
        proxy.handler = this;
      }

      this.proxy = proxy;
    };

    Handler.prototype.mousemove = function (event) {
      var x = event.zrX;
      var y = event.zrY;
      var isOutside = isOutsideBoundary(this, x, y);
      var lastHovered = this._hovered;
      var lastHoveredTarget = lastHovered.target;

      if (lastHoveredTarget && !lastHoveredTarget.__zr) {
        lastHovered = this.findHover(lastHovered.x, lastHovered.y);
        lastHoveredTarget = lastHovered.target;
      }

      var hovered = this._hovered = isOutside ? new HoveredResult(x, y) : this.findHover(x, y);
      var hoveredTarget = hovered.target;
      var proxy = this.proxy;
      proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default');

      if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) {
        this.dispatchToElement(lastHovered, 'mouseout', event);
      }

      this.dispatchToElement(hovered, 'mousemove', event);

      if (hoveredTarget && hoveredTarget !== lastHoveredTarget) {
        this.dispatchToElement(hovered, 'mouseover', event);
      }
    };

    Handler.prototype.mouseout = function (event) {
      var eventControl = event.zrEventControl;
      var zrIsToLocalDOM = event.zrIsToLocalDOM;

      if (eventControl !== 'only_globalout') {
        this.dispatchToElement(this._hovered, 'mouseout', event);
      }

      if (eventControl !== 'no_globalout') {
        !zrIsToLocalDOM && this.trigger('globalout', {
          type: 'globalout',
          event: event
        });
      }
    };

    Handler.prototype.resize = function () {
      this._hovered = new HoveredResult(0, 0);
    };

    Handler.prototype.dispatch = function (eventName, eventArgs) {
      var handler = this[eventName];
      handler && handler.call(this, eventArgs);
    };

    Handler.prototype.dispose = function () {
      this.proxy.dispose();
      this.storage = null;
      this.proxy = null;
      this.painter = null;
    };

    Handler.prototype.setCursorStyle = function (cursorStyle) {
      var proxy = this.proxy;
      proxy.setCursor && proxy.setCursor(cursorStyle);
    };

    Handler.prototype.dispatchToElement = function (targetInfo, eventName, event) {
      targetInfo = targetInfo || {};
      var el = targetInfo.target;

      if (el && el.silent) {
        return;
      }

      var eventKey = 'on' + eventName;
      var eventPacket = makeEventPacket(eventName, targetInfo, event);

      while (el) {
        el[eventKey] && (eventPacket.cancelBubble = !!el[eventKey].call(el, eventPacket));
        el.trigger(eventName, eventPacket);
        el = el.__hostTarget ? el.__hostTarget : el.parent;

        if (eventPacket.cancelBubble) {
          break;
        }
      }

      if (!eventPacket.cancelBubble) {
        this.trigger(eventName, eventPacket);

        if (this.painter && this.painter.eachOtherLayer) {
          this.painter.eachOtherLayer(function (layer) {
            if (typeof layer[eventKey] === 'function') {
              layer[eventKey].call(layer, eventPacket);
            }

            if (layer.trigger) {
              layer.trigger(eventName, eventPacket);
            }
          });
        }
      }
    };

    Handler.prototype.findHover = function (x, y, exclude) {
      var list = this.storage.getDisplayList();
      var out = new HoveredResult(x, y);

      for (var i = list.length - 1; i >= 0; i--) {
        var hoverCheckResult = void 0;

        if (list[i] !== exclude && !list[i].ignore && (hoverCheckResult = isHover(list[i], x, y))) {
          !out.topTarget && (out.topTarget = list[i]);

          if (hoverCheckResult !== SILENT) {
            out.target = list[i];
            break;
          }
        }
      }

      return out;
    };

    Handler.prototype.processGesture = function (event, stage) {
      if (!this._gestureMgr) {
        this._gestureMgr = new GestureMgr();
      }

      var gestureMgr = this._gestureMgr;
      stage === 'start' && gestureMgr.clear();
      var gestureInfo = gestureMgr.recognize(event, this.findHover(event.zrX, event.zrY, null).target, this.proxy.dom);
      stage === 'end' && gestureMgr.clear();

      if (gestureInfo) {
        var type = gestureInfo.type;
        event.gestureEvent = type;
        var res = new HoveredResult();
        res.target = gestureInfo.target;
        this.dispatchToElement(res, type, gestureInfo.event);
      }
    };

    return Handler;
  }(Eventful);

  each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
    Handler.prototype[name] = function (event) {
      var x = event.zrX;
      var y = event.zrY;
      var isOutside = isOutsideBoundary(this, x, y);
      var hovered;
      var hoveredTarget;

      if (name !== 'mouseup' || !isOutside) {
        hovered = this.findHover(x, y);
        hoveredTarget = hovered.target;
      }

      if (name === 'mousedown') {
        this._downEl = hoveredTarget;
        this._downPoint = [event.zrX, event.zrY];
        this._upEl = hoveredTarget;
      } else if (name === 'mouseup') {
        this._upEl = hoveredTarget;
      } else if (name === 'click') {
        if (this._downEl !== this._upEl || !this._downPoint || dist(this._downPoint, [event.zrX, event.zrY]) > 4) {
          return;
        }

        this._downPoint = null;
      }

      this.dispatchToElement(hovered, name, event);
    };
  });

  function isHover(displayable, x, y) {
    if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) {
      var el = displayable;
      var isSilent = void 0;
      var ignoreClip = false;

      while (el) {
        if (el.ignoreClip) {
          ignoreClip = true;
        }

        if (!ignoreClip) {
          var clipPath = el.getClipPath();

          if (clipPath && !clipPath.contain(x, y)) {
            return false;
          }

          if (el.silent) {
            isSilent = true;
          }
        }

        var hostEl = el.__hostTarget;
        el = hostEl ? hostEl : el.parent;
      }

      return isSilent ? SILENT : true;
    }

    return false;
  }

  function isOutsideBoundary(handlerInstance, x, y) {
    var painter = handlerInstance.painter;
    return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight();
  }

  function create$1() {
    return [1, 0, 0, 1, 0, 0];
  }

  function identity(out) {
    out[0] = 1;
    out[1] = 0;
    out[2] = 0;
    out[3] = 1;
    out[4] = 0;
    out[5] = 0;
    return out;
  }

  function copy$1(out, m) {
    out[0] = m[0];
    out[1] = m[1];
    out[2] = m[2];
    out[3] = m[3];
    out[4] = m[4];
    out[5] = m[5];
    return out;
  }

  function mul$1(out, m1, m2) {
    var out0 = m1[0] * m2[0] + m1[2] * m2[1];
    var out1 = m1[1] * m2[0] + m1[3] * m2[1];
    var out2 = m1[0] * m2[2] + m1[2] * m2[3];
    var out3 = m1[1] * m2[2] + m1[3] * m2[3];
    var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
    var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
    out[0] = out0;
    out[1] = out1;
    out[2] = out2;
    out[3] = out3;
    out[4] = out4;
    out[5] = out5;
    return out;
  }

  function translate(out, a, v) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4] + v[0];
    out[5] = a[5] + v[1];
    return out;
  }

  function rotate(out, a, rad) {
    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];
    var st = Math.sin(rad);
    var ct = Math.cos(rad);
    out[0] = aa * ct + ab * st;
    out[1] = -aa * st + ab * ct;
    out[2] = ac * ct + ad * st;
    out[3] = -ac * st + ct * ad;
    out[4] = ct * atx + st * aty;
    out[5] = ct * aty - st * atx;
    return out;
  }

  function scale$1(out, a, v) {
    var vx = v[0];
    var vy = v[1];
    out[0] = a[0] * vx;
    out[1] = a[1] * vy;
    out[2] = a[2] * vx;
    out[3] = a[3] * vy;
    out[4] = a[4] * vx;
    out[5] = a[5] * vy;
    return out;
  }

  function invert(out, a) {
    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];
    var det = aa * ad - ab * ac;

    if (!det) {
      return null;
    }

    det = 1.0 / det;
    out[0] = ad * det;
    out[1] = -ab * det;
    out[2] = -ac * det;
    out[3] = aa * det;
    out[4] = (ac * aty - ad * atx) * det;
    out[5] = (ab * atx - aa * aty) * det;
    return out;
  }

  function clone$2(a) {
    var b = create$1();
    copy$1(b, a);
    return b;
  }

  var matrix = /*#__PURE__*/Object.freeze({
    __proto__: null,
    create: create$1,
    identity: identity,
    copy: copy$1,
    mul: mul$1,
    translate: translate,
    rotate: rotate,
    scale: scale$1,
    invert: invert,
    clone: clone$2
  });
  var mIdentity = identity;
  var EPSILON = 5e-5;

  function isNotAroundZero(val) {
    return val > EPSILON || val < -EPSILON;
  }

  var scaleTmp = [];
  var tmpTransform = [];
  var originTransform = create$1();
  var abs = Math.abs;

  var Transformable = function () {
    function Transformable() {}

    Transformable.prototype.setPosition = function (arr) {
      this.x = arr[0];
      this.y = arr[1];
    };

    Transformable.prototype.setScale = function (arr) {
      this.scaleX = arr[0];
      this.scaleY = arr[1];
    };

    Transformable.prototype.setOrigin = function (arr) {
      this.originX = arr[0];
      this.originY = arr[1];
    };

    Transformable.prototype.needLocalTransform = function () {
      return isNotAroundZero(this.rotation) || isNotAroundZero(this.x) || isNotAroundZero(this.y) || isNotAroundZero(this.scaleX - 1) || isNotAroundZero(this.scaleY - 1);
    };

    Transformable.prototype.updateTransform = function () {
      var parent = this.parent;
      var parentHasTransform = parent && parent.transform;
      var needLocalTransform = this.needLocalTransform();
      var m = this.transform;

      if (!(needLocalTransform || parentHasTransform)) {
        m && mIdentity(m);
        return;
      }

      m = m || create$1();

      if (needLocalTransform) {
        this.getLocalTransform(m);
      } else {
        mIdentity(m);
      }

      if (parentHasTransform) {
        if (needLocalTransform) {
          mul$1(m, parent.transform, m);
        } else {
          copy$1(m, parent.transform);
        }
      }

      this.transform = m;

      this._resolveGlobalScaleRatio(m);
    };

    Transformable.prototype._resolveGlobalScaleRatio = function (m) {
      var globalScaleRatio = this.globalScaleRatio;

      if (globalScaleRatio != null && globalScaleRatio !== 1) {
        this.getGlobalScale(scaleTmp);
        var relX = scaleTmp[0] < 0 ? -1 : 1;
        var relY = scaleTmp[1] < 0 ? -1 : 1;
        var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0;
        var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0;
        m[0] *= sx;
        m[1] *= sx;
        m[2] *= sy;
        m[3] *= sy;
      }

      this.invTransform = this.invTransform || create$1();
      invert(this.invTransform, m);
    };

    Transformable.prototype.getLocalTransform = function (m) {
      return Transformable.getLocalTransform(this, m);
    };

    Transformable.prototype.getComputedTransform = function () {
      var transformNode = this;
      var ancestors = [];

      while (transformNode) {
        ancestors.push(transformNode);
        transformNode = transformNode.parent;
      }

      while (transformNode = ancestors.pop()) {
        transformNode.updateTransform();
      }

      return this.transform;
    };

    Transformable.prototype.setLocalTransform = function (m) {
      if (!m) {
        return;
      }

      var sx = m[0] * m[0] + m[1] * m[1];
      var sy = m[2] * m[2] + m[3] * m[3];

      if (isNotAroundZero(sx - 1)) {
        sx = Math.sqrt(sx);
      }

      if (isNotAroundZero(sy - 1)) {
        sy = Math.sqrt(sy);
      }

      if (m[0] < 0) {
        sx = -sx;
      }

      if (m[3] < 0) {
        sy = -sy;
      }

      this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);

      if (sx < 0 && sy < 0) {
        this.rotation += Math.PI;
        sx = -sx;
        sy = -sy;
      }

      this.x = m[4];
      this.y = m[5];
      this.scaleX = sx;
      this.scaleY = sy;
    };

    Transformable.prototype.decomposeTransform = function () {
      if (!this.transform) {
        return;
      }

      var parent = this.parent;
      var m = this.transform;

      if (parent && parent.transform) {
        mul$1(tmpTransform, parent.invTransform, m);
        m = tmpTransform;
      }

      var ox = this.originX;
      var oy = this.originY;

      if (ox || oy) {
        originTransform[4] = ox;
        originTransform[5] = oy;
        mul$1(tmpTransform, m, originTransform);
        tmpTransform[4] -= ox;
        tmpTransform[5] -= oy;
        m = tmpTransform;
      }

      this.setLocalTransform(m);
    };

    Transformable.prototype.getGlobalScale = function (out) {
      var m = this.transform;
      out = out || [];

      if (!m) {
        out[0] = 1;
        out[1] = 1;
        return out;
      }

      out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
      out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]);

      if (m[0] < 0) {
        out[0] = -out[0];
      }

      if (m[3] < 0) {
        out[1] = -out[1];
      }

      return out;
    };

    Transformable.prototype.transformCoordToLocal = function (x, y) {
      var v2 = [x, y];
      var invTransform = this.invTransform;

      if (invTransform) {
        applyTransform(v2, v2, invTransform);
      }

      return v2;
    };

    Transformable.prototype.transformCoordToGlobal = function (x, y) {
      var v2 = [x, y];
      var transform = this.transform;

      if (transform) {
        applyTransform(v2, v2, transform);
      }

      return v2;
    };

    Transformable.prototype.getLineScale = function () {
      var m = this.transform;
      return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) : 1;
    };

    Transformable.getLocalTransform = function (target, m) {
      m = m || [];
      mIdentity(m);
      var ox = target.originX || 0;
      var oy = target.originY || 0;
      var sx = target.scaleX;
      var sy = target.scaleY;
      var rotation = target.rotation || 0;
      var x = target.x;
      var y = target.y;
      m[4] -= ox;
      m[5] -= oy;
      m[0] *= sx;
      m[1] *= sy;
      m[2] *= sx;
      m[3] *= sy;
      m[4] *= sx;
      m[5] *= sy;

      if (rotation) {
        rotate(m, m, rotation);
      }

      m[4] += ox;
      m[5] += oy;
      m[4] += x;
      m[5] += y;
      return m;
    };

    Transformable.initDefaultProps = function () {
      var proto = Transformable.prototype;
      proto.x = 0;
      proto.y = 0;
      proto.scaleX = 1;
      proto.scaleY = 1;
      proto.originX = 0;
      proto.originY = 0;
      proto.rotation = 0;
      proto.globalScaleRatio = 1;
    }();

    return Transformable;
  }();

  var easing = {
    linear: function (k) {
      return k;
    },
    quadraticIn: function (k) {
      return k * k;
    },
    quadraticOut: function (k) {
      return k * (2 - k);
    },
    quadraticInOut: function (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k;
      }

      return -0.5 * (--k * (k - 2) - 1);
    },
    cubicIn: function (k) {
      return k * k * k;
    },
    cubicOut: function (k) {
      return --k * k * k + 1;
    },
    cubicInOut: function (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k;
      }

      return 0.5 * ((k -= 2) * k * k + 2);
    },
    quarticIn: function (k) {
      return k * k * k * k;
    },
    quarticOut: function (k) {
      return 1 - --k * k * k * k;
    },
    quarticInOut: function (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k * k;
      }

      return -0.5 * ((k -= 2) * k * k * k - 2);
    },
    quinticIn: function (k) {
      return k * k * k * k * k;
    },
    quinticOut: function (k) {
      return --k * k * k * k * k + 1;
    },
    quinticInOut: function (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k * k * k;
      }

      return 0.5 * ((k -= 2) * k * k * k * k + 2);
    },
    sinusoidalIn: function (k) {
      return 1 - Math.cos(k * Math.PI / 2);
    },
    sinusoidalOut: function (k) {
      return Math.sin(k * Math.PI / 2);
    },
    sinusoidalInOut: function (k) {
      return 0.5 * (1 - Math.cos(Math.PI * k));
    },
    exponentialIn: function (k) {
      return k === 0 ? 0 : Math.pow(1024, k - 1);
    },
    exponentialOut: function (k) {
      return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
    },
    exponentialInOut: function (k) {
      if (k === 0) {
        return 0;
      }

      if (k === 1) {
        return 1;
      }

      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(1024, k - 1);
      }

      return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
    },
    circularIn: function (k) {
      return 1 - Math.sqrt(1 - k * k);
    },
    circularOut: function (k) {
      return Math.sqrt(1 - --k * k);
    },
    circularInOut: function (k) {
      if ((k *= 2) < 1) {
        return -0.5 * (Math.sqrt(1 - k * k) - 1);
      }

      return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
    },
    elasticIn: function (k) {
      var s;
      var a = 0.1;
      var p = 0.4;

      if (k === 0) {
        return 0;
      }

      if (k === 1) {
        return 1;
      }

      if (!a || a < 1) {
        a = 1;
        s = p / 4;
      } else {
        s = p * Math.asin(1 / a) / (2 * Math.PI);
      }

      return -(a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
    },
    elasticOut: function (k) {
      var s;
      var a = 0.1;
      var p = 0.4;

      if (k === 0) {
        return 0;
      }

      if (k === 1) {
        return 1;
      }

      if (!a || a < 1) {
        a = 1;
        s = p / 4;
      } else {
        s = p * Math.asin(1 / a) / (2 * Math.PI);
      }

      return a * Math.pow(2, -10 * k) * Math.sin((k - s) * (2 * Math.PI) / p) + 1;
    },
    elasticInOut: function (k) {
      var s;
      var a = 0.1;
      var p = 0.4;

      if (k === 0) {
        return 0;
      }

      if (k === 1) {
        return 1;
      }

      if (!a || a < 1) {
        a = 1;
        s = p / 4;
      } else {
        s = p * Math.asin(1 / a) / (2 * Math.PI);
      }

      if ((k *= 2) < 1) {
        return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
      }

      return a * Math.pow(2, -10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
    },
    backIn: function (k) {
      var s = 1.70158;
      return k * k * ((s + 1) * k - s);
    },
    backOut: function (k) {
      var s = 1.70158;
      return --k * k * ((s + 1) * k + s) + 1;
    },
    backInOut: function (k) {
      var s = 1.70158 * 1.525;

      if ((k *= 2) < 1) {
        return 0.5 * (k * k * ((s + 1) * k - s));
      }

      return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
    },
    bounceIn: function (k) {
      return 1 - easing.bounceOut(1 - k);
    },
    bounceOut: function (k) {
      if (k < 1 / 2.75) {
        return 7.5625 * k * k;
      } else if (k < 2 / 2.75) {
        return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75;
      } else if (k < 2.5 / 2.75) {
        return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375;
      } else {
        return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375;
      }
    },
    bounceInOut: function (k) {
      if (k < 0.5) {
        return easing.bounceIn(k * 2) * 0.5;
      }

      return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5;
    }
  };

  var Clip = function () {
    function Clip(opts) {
      this._initialized = false;
      this._startTime = 0;
      this._pausedTime = 0;
      this._paused = false;
      this._life = opts.life || 1000;
      this._delay = opts.delay || 0;
      this.loop = opts.loop == null ? false : opts.loop;
      this.gap = opts.gap || 0;
      this.easing = opts.easing || 'linear';
      this.onframe = opts.onframe;
      this.ondestroy = opts.ondestroy;
      this.onrestart = opts.onrestart;
    }

    Clip.prototype.step = function (globalTime, deltaTime) {
      if (!this._initialized) {
        this._startTime = globalTime + this._delay;
        this._initialized = true;
      }

      if (this._paused) {
        this._pausedTime += deltaTime;
        return;
      }

      var percent = (globalTime - this._startTime - this._pausedTime) / this._life;

      if (percent < 0) {
        percent = 0;
      }

      percent = Math.min(percent, 1);
      var easing$1 = this.easing;
      var easingFunc = typeof easing$1 === 'string' ? easing[easing$1] : easing$1;
      var schedule = typeof easingFunc === 'function' ? easingFunc(percent) : percent;
      this.onframe && this.onframe(schedule);

      if (percent === 1) {
        if (this.loop) {
          this._restart(globalTime);

          this.onrestart && this.onrestart();
        } else {
          return true;
        }
      }

      return false;
    };

    Clip.prototype._restart = function (globalTime) {
      var remainder = (globalTime - this._startTime - this._pausedTime) % this._life;
      this._startTime = globalTime - remainder + this.gap;
      this._pausedTime = 0;
    };

    Clip.prototype.pause = function () {
      this._paused = true;
    };

    Clip.prototype.resume = function () {
      this._paused = false;
    };

    return Clip;
  }();

  var Entry = function () {
    function Entry(val) {
      this.value = val;
    }

    return Entry;
  }();

  var LinkedList = function () {
    function LinkedList() {
      this._len = 0;
    }

    LinkedList.prototype.insert = function (val) {
      var entry = new Entry(val);
      this.insertEntry(entry);
      return entry;
    };

    LinkedList.prototype.insertEntry = function (entry) {
      if (!this.head) {
        this.head = this.tail = entry;
      } else {
        this.tail.next = entry;
        entry.prev = this.tail;
        entry.next = null;
        this.tail = entry;
      }

      this._len++;
    };

    LinkedList.prototype.remove = function (entry) {
      var prev = entry.prev;
      var next = entry.next;

      if (prev) {
        prev.next = next;
      } else {
        this.head = next;
      }

      if (next) {
        next.prev = prev;
      } else {
        this.tail = prev;
      }

      entry.next = entry.prev = null;
      this._len--;
    };

    LinkedList.prototype.len = function () {
      return this._len;
    };

    LinkedList.prototype.clear = function () {
      this.head = this.tail = null;
      this._len = 0;
    };

    return LinkedList;
  }();

  var LRU = function () {
    function LRU(maxSize) {
      this._list = new LinkedList();
      this._maxSize = 10;
      this._map = {};
      this._maxSize = maxSize;
    }

    LRU.prototype.put = function (key, value) {
      var list = this._list;
      var map = this._map;
      var removed = null;

      if (map[key] == null) {
        var len = list.len();
        var entry = this._lastRemovedEntry;

        if (len >= this._maxSize && len > 0) {
          var leastUsedEntry = list.head;
          list.remove(leastUsedEntry);
          delete map[leastUsedEntry.key];
          removed = leastUsedEntry.value;
          this._lastRemovedEntry = leastUsedEntry;
        }

        if (entry) {
          entry.value = value;
        } else {
          entry = new Entry(value);
        }

        entry.key = key;
        list.insertEntry(entry);
        map[key] = entry;
      }

      return removed;
    };

    LRU.prototype.get = function (key) {
      var entry = this._map[key];
      var list = this._list;

      if (entry != null) {
        if (entry !== list.tail) {
          list.remove(entry);
          list.insertEntry(entry);
        }

        return entry.value;
      }
    };

    LRU.prototype.clear = function () {
      this._list.clear();

      this._map = {};
    };

    LRU.prototype.len = function () {
      return this._list.len();
    };

    return LRU;
  }();

  var kCSSColorTable = {
    'transparent': [0, 0, 0, 0],
    'aliceblue': [240, 248, 255, 1],
    'antiquewhite': [250, 235, 215, 1],
    'aqua': [0, 255, 255, 1],
    'aquamarine': [127, 255, 212, 1],
    'azure': [240, 255, 255, 1],
    'beige': [245, 245, 220, 1],
    'bisque': [255, 228, 196, 1],
    'black': [0, 0, 0, 1],
    'blanchedalmond': [255, 235, 205, 1],
    'blue': [0, 0, 255, 1],
    'blueviolet': [138, 43, 226, 1],
    'brown': [165, 42, 42, 1],
    'burlywood': [222, 184, 135, 1],
    'cadetblue': [95, 158, 160, 1],
    'chartreuse': [127, 255, 0, 1],
    'chocolate': [210, 105, 30, 1],
    'coral': [255, 127, 80, 1],
    'cornflowerblue': [100, 149, 237, 1],
    'cornsilk': [255, 248, 220, 1],
    'crimson': [220, 20, 60, 1],
    'cyan': [0, 255, 255, 1],
    'darkblue': [0, 0, 139, 1],
    'darkcyan': [0, 139, 139, 1],
    'darkgoldenrod': [184, 134, 11, 1],
    'darkgray': [169, 169, 169, 1],
    'darkgreen': [0, 100, 0, 1],
    'darkgrey': [169, 169, 169, 1],
    'darkkhaki': [189, 183, 107, 1],
    'darkmagenta': [139, 0, 139, 1],
    'darkolivegreen': [85, 107, 47, 1],
    'darkorange': [255, 140, 0, 1],
    'darkorchid': [153, 50, 204, 1],
    'darkred': [139, 0, 0, 1],
    'darksalmon': [233, 150, 122, 1],
    'darkseagreen': [143, 188, 143, 1],
    'darkslateblue': [72, 61, 139, 1],
    'darkslategray': [47, 79, 79, 1],
    'darkslategrey': [47, 79, 79, 1],
    'darkturquoise': [0, 206, 209, 1],
    'darkviolet': [148, 0, 211, 1],
    'deeppink': [255, 20, 147, 1],
    'deepskyblue': [0, 191, 255, 1],
    'dimgray': [105, 105, 105, 1],
    'dimgrey': [105, 105, 105, 1],
    'dodgerblue': [30, 144, 255, 1],
    'firebrick': [178, 34, 34, 1],
    'floralwhite': [255, 250, 240, 1],
    'forestgreen': [34, 139, 34, 1],
    'fuchsia': [255, 0, 255, 1],
    'gainsboro': [220, 220, 220, 1],
    'ghostwhite': [248, 248, 255, 1],
    'gold': [255, 215, 0, 1],
    'goldenrod': [218, 165, 32, 1],
    'gray': [128, 128, 128, 1],
    'green': [0, 128, 0, 1],
    'greenyellow': [173, 255, 47, 1],
    'grey': [128, 128, 128, 1],
    'honeydew': [240, 255, 240, 1],
    'hotpink': [255, 105, 180, 1],
    'indianred': [205, 92, 92, 1],
    'indigo': [75, 0, 130, 1],
    'ivory': [255, 255, 240, 1],
    'khaki': [240, 230, 140, 1],
    'lavender': [230, 230, 250, 1],
    'lavenderblush': [255, 240, 245, 1],
    'lawngreen': [124, 252, 0, 1],
    'lemonchiffon': [255, 250, 205, 1],
    'lightblue': [173, 216, 230, 1],
    'lightcoral': [240, 128, 128, 1],
    'lightcyan': [224, 255, 255, 1],
    'lightgoldenrodyellow': [250, 250, 210, 1],
    'lightgray': [211, 211, 211, 1],
    'lightgreen': [144, 238, 144, 1],
    'lightgrey': [211, 211, 211, 1],
    'lightpink': [255, 182, 193, 1],
    'lightsalmon': [255, 160, 122, 1],
    'lightseagreen': [32, 178, 170, 1],
    'lightskyblue': [135, 206, 250, 1],
    'lightslategray': [119, 136, 153, 1],
    'lightslategrey': [119, 136, 153, 1],
    'lightsteelblue': [176, 196, 222, 1],
    'lightyellow': [255, 255, 224, 1],
    'lime': [0, 255, 0, 1],
    'limegreen': [50, 205, 50, 1],
    'linen': [250, 240, 230, 1],
    'magenta': [255, 0, 255, 1],
    'maroon': [128, 0, 0, 1],
    'mediumaquamarine': [102, 205, 170, 1],
    'mediumblue': [0, 0, 205, 1],
    'mediumorchid': [186, 85, 211, 1],
    'mediumpurple': [147, 112, 219, 1],
    'mediumseagreen': [60, 179, 113, 1],
    'mediumslateblue': [123, 104, 238, 1],
    'mediumspringgreen': [0, 250, 154, 1],
    'mediumturquoise': [72, 209, 204, 1],
    'mediumvioletred': [199, 21, 133, 1],
    'midnightblue': [25, 25, 112, 1],
    'mintcream': [245, 255, 250, 1],
    'mistyrose': [255, 228, 225, 1],
    'moccasin': [255, 228, 181, 1],
    'navajowhite': [255, 222, 173, 1],
    'navy': [0, 0, 128, 1],
    'oldlace': [253, 245, 230, 1],
    'olive': [128, 128, 0, 1],
    'olivedrab': [107, 142, 35, 1],
    'orange': [255, 165, 0, 1],
    'orangered': [255, 69, 0, 1],
    'orchid': [218, 112, 214, 1],
    'palegoldenrod': [238, 232, 170, 1],
    'palegreen': [152, 251, 152, 1],
    'paleturquoise': [175, 238, 238, 1],
    'palevioletred': [219, 112, 147, 1],
    'papayawhip': [255, 239, 213, 1],
    'peachpuff': [255, 218, 185, 1],
    'peru': [205, 133, 63, 1],
    'pink': [255, 192, 203, 1],
    'plum': [221, 160, 221, 1],
    'powderblue': [176, 224, 230, 1],
    'purple': [128, 0, 128, 1],
    'red': [255, 0, 0, 1],
    'rosybrown': [188, 143, 143, 1],
    'royalblue': [65, 105, 225, 1],
    'saddlebrown': [139, 69, 19, 1],
    'salmon': [250, 128, 114, 1],
    'sandybrown': [244, 164, 96, 1],
    'seagreen': [46, 139, 87, 1],
    'seashell': [255, 245, 238, 1],
    'sienna': [160, 82, 45, 1],
    'silver': [192, 192, 192, 1],
    'skyblue': [135, 206, 235, 1],
    'slateblue': [106, 90, 205, 1],
    'slategray': [112, 128, 144, 1],
    'slategrey': [112, 128, 144, 1],
    'snow': [255, 250, 250, 1],
    'springgreen': [0, 255, 127, 1],
    'steelblue': [70, 130, 180, 1],
    'tan': [210, 180, 140, 1],
    'teal': [0, 128, 128, 1],
    'thistle': [216, 191, 216, 1],
    'tomato': [255, 99, 71, 1],
    'turquoise': [64, 224, 208, 1],
    'violet': [238, 130, 238, 1],
    'wheat': [245, 222, 179, 1],
    'white': [255, 255, 255, 1],
    'whitesmoke': [245, 245, 245, 1],
    'yellow': [255, 255, 0, 1],
    'yellowgreen': [154, 205, 50, 1]
  };

  function clampCssByte(i) {
    i = Math.round(i);
    return i < 0 ? 0 : i > 255 ? 255 : i;
  }

  function clampCssAngle(i) {
    i = Math.round(i);
    return i < 0 ? 0 : i > 360 ? 360 : i;
  }

  function clampCssFloat(f) {
    return f < 0 ? 0 : f > 1 ? 1 : f;
  }

  function parseCssInt(val) {
    var str = val;

    if (str.length && str.charAt(str.length - 1) === '%') {
      return clampCssByte(parseFloat(str) / 100 * 255);
    }

    return clampCssByte(parseInt(str, 10));
  }

  function parseCssFloat(val) {
    var str = val;

    if (str.length && str.charAt(str.length - 1) === '%') {
      return clampCssFloat(parseFloat(str) / 100);
    }

    return clampCssFloat(parseFloat(str));
  }

  function cssHueToRgb(m1, m2, h) {
    if (h < 0) {
      h += 1;
    } else if (h > 1) {
      h -= 1;
    }

    if (h * 6 < 1) {
      return m1 + (m2 - m1) * h * 6;
    }

    if (h * 2 < 1) {
      return m2;
    }

    if (h * 3 < 2) {
      return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }

    return m1;
  }

  function lerpNumber(a, b, p) {
    return a + (b - a) * p;
  }

  function setRgba(out, r, g, b, a) {
    out[0] = r;
    out[1] = g;
    out[2] = b;
    out[3] = a;
    return out;
  }

  function copyRgba(out, a) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    return out;
  }

  var colorCache = new LRU(20);
  var lastRemovedArr = null;

  function putToCache(colorStr, rgbaArr) {
    if (lastRemovedArr) {
      copyRgba(lastRemovedArr, rgbaArr);
    }

    lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || rgbaArr.slice());
  }

  function parse(colorStr, rgbaArr) {
    if (!colorStr) {
      return;
    }

    rgbaArr = rgbaArr || [];
    var cached = colorCache.get(colorStr);

    if (cached) {
      return copyRgba(rgbaArr, cached);
    }

    colorStr = colorStr + '';
    var str = colorStr.replace(/ /g, '').toLowerCase();

    if (str in kCSSColorTable) {
      copyRgba(rgbaArr, kCSSColorTable[str]);
      putToCache(colorStr, rgbaArr);
      return rgbaArr;
    }

    var strLen = str.length;

    if (str.charAt(0) === '#') {
      if (strLen === 4 || strLen === 5) {
        var iv = parseInt(str.slice(1, 4), 16);

        if (!(iv >= 0 && iv <= 0xfff)) {
          setRgba(rgbaArr, 0, 0, 0, 1);
          return;
        }

        setRgba(rgbaArr, (iv & 0xf00) >> 4 | (iv & 0xf00) >> 8, iv & 0xf0 | (iv & 0xf0) >> 4, iv & 0xf | (iv & 0xf) << 4, strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1);
        putToCache(colorStr, rgbaArr);
        return rgbaArr;
      } else if (strLen === 7 || strLen === 9) {
        var iv = parseInt(str.slice(1, 7), 16);

        if (!(iv >= 0 && iv <= 0xffffff)) {
          setRgba(rgbaArr, 0, 0, 0, 1);
          return;
        }

        setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1);
        putToCache(colorStr, rgbaArr);
        return rgbaArr;
      }

      return;
    }

    var op = str.indexOf('(');
    var ep = str.indexOf(')');

    if (op !== -1 && ep + 1 === strLen) {
      var fname = str.substr(0, op);
      var params = str.substr(op + 1, ep - (op + 1)).split(',');
      var alpha = 1;

      switch (fname) {
        case 'rgba':
          if (params.length !== 4) {
            return params.length === 3 ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1) : setRgba(rgbaArr, 0, 0, 0, 1);
          }

          alpha = parseCssFloat(params.pop());

        case 'rgb':
          if (params.length !== 3) {
            setRgba(rgbaArr, 0, 0, 0, 1);
            return;
          }

          setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), alpha);
          putToCache(colorStr, rgbaArr);
          return rgbaArr;

        case 'hsla':
          if (params.length !== 4) {
            setRgba(rgbaArr, 0, 0, 0, 1);
            return;
          }

          params[3] = parseCssFloat(params[3]);
          hsla2rgba(params, rgbaArr);
          putToCache(colorStr, rgbaArr);
          return rgbaArr;

        case 'hsl':
          if (params.length !== 3) {
            setRgba(rgbaArr, 0, 0, 0, 1);
            return;
          }

          hsla2rgba(params, rgbaArr);
          putToCache(colorStr, rgbaArr);
          return rgbaArr;

        default:
          return;
      }
    }

    setRgba(rgbaArr, 0, 0, 0, 1);
    return;
  }

  function hsla2rgba(hsla, rgba) {
    var h = (parseFloat(hsla[0]) % 360 + 360) % 360 / 360;
    var s = parseCssFloat(hsla[1]);
    var l = parseCssFloat(hsla[2]);
    var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
    var m1 = l * 2 - m2;
    rgba = rgba || [];
    setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1);

    if (hsla.length === 4) {
      rgba[3] = hsla[3];
    }

    return rgba;
  }

  function rgba2hsla(rgba) {
    if (!rgba) {
      return;
    }

    var R = rgba[0] / 255;
    var G = rgba[1] / 255;
    var B = rgba[2] / 255;
    var vMin = Math.min(R, G, B);
    var vMax = Math.max(R, G, B);
    var delta = vMax - vMin;
    var L = (vMax + vMin) / 2;
    var H;
    var S;

    if (delta === 0) {
      H = 0;
      S = 0;
    } else {
      if (L < 0.5) {
        S = delta / (vMax + vMin);
      } else {
        S = delta / (2 - vMax - vMin);
      }

      var deltaR = ((vMax - R) / 6 + delta / 2) / delta;
      var deltaG = ((vMax - G) / 6 + delta / 2) / delta;
      var deltaB = ((vMax - B) / 6 + delta / 2) / delta;

      if (R === vMax) {
        H = deltaB - deltaG;
      } else if (G === vMax) {
        H = 1 / 3 + deltaR - deltaB;
      } else if (B === vMax) {
        H = 2 / 3 + deltaG - deltaR;
      }

      if (H < 0) {
        H += 1;
      }

      if (H > 1) {
        H -= 1;
      }
    }

    var hsla = [H * 360, S, L];

    if (rgba[3] != null) {
      hsla.push(rgba[3]);
    }

    return hsla;
  }

  function lift(color, level) {
    var colorArr = parse(color);

    if (colorArr) {
      for (var i = 0; i < 3; i++) {
        if (level < 0) {
          colorArr[i] = colorArr[i] * (1 - level) | 0;
        } else {
          colorArr[i] = (255 - colorArr[i]) * level + colorArr[i] | 0;
        }

        if (colorArr[i] > 255) {
          colorArr[i] = 255;
        } else if (colorArr[i] < 0) {
          colorArr[i] = 0;
        }
      }

      return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
    }
  }

  function toHex(color) {
    var colorArr = parse(color);

    if (colorArr) {
      return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + +colorArr[2]).toString(16).slice(1);
    }
  }

  function fastLerp(normalizedValue, colors, out) {
    if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) {
      return;
    }

    out = out || [];
    var value = normalizedValue * (colors.length - 1);
    var leftIndex = Math.floor(value);
    var rightIndex = Math.ceil(value);
    var leftColor = colors[leftIndex];
    var rightColor = colors[rightIndex];
    var dv = value - leftIndex;
    out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv));
    out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv));
    out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv));
    out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv));
    return out;
  }

  var fastMapToColor = fastLerp;

  function lerp$1(normalizedValue, colors, fullOutput) {
    if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) {
      return;
    }

    var value = normalizedValue * (colors.length - 1);
    var leftIndex = Math.floor(value);
    var rightIndex = Math.ceil(value);
    var leftColor = parse(colors[leftIndex]);
    var rightColor = parse(colors[rightIndex]);
    var dv = value - leftIndex;
    var color = stringify([clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv))], 'rgba');
    return fullOutput ? {
      color: color,
      leftIndex: leftIndex,
      rightIndex: rightIndex,
      value: value
    } : color;
  }

  var mapToColor = lerp$1;

  function modifyHSL(color, h, s, l) {
    var colorArr = parse(color);

    if (color) {
      colorArr = rgba2hsla(colorArr);
      h != null && (colorArr[0] = clampCssAngle(h));
      s != null && (colorArr[1] = parseCssFloat(s));
      l != null && (colorArr[2] = parseCssFloat(l));
      return stringify(hsla2rgba(colorArr), 'rgba');
    }
  }

  function modifyAlpha(color, alpha) {
    var colorArr = parse(color);

    if (colorArr && alpha != null) {
      colorArr[3] = clampCssFloat(alpha);
      return stringify(colorArr, 'rgba');
    }
  }

  function stringify(arrColor, type) {
    if (!arrColor || !arrColor.length) {
      return;
    }

    var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];

    if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
      colorStr += ',' + arrColor[3];
    }

    return type + '(' + colorStr + ')';
  }

  function lum(color, backgroundLum) {
    var arr = parse(color);
    return arr ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255 + (1 - arr[3]) * backgroundLum : 0;
  }

  function random() {
    var r = Math.round(Math.random() * 255);
    var g = Math.round(Math.random() * 255);
    var b = Math.round(Math.random() * 255);
    return 'rgb(' + r + ',' + g + ',' + b + ')';
  }

  var color = /*#__PURE__*/Object.freeze({
    __proto__: null,
    parse: parse,
    lift: lift,
    toHex: toHex,
    fastLerp: fastLerp,
    fastMapToColor: fastMapToColor,
    lerp: lerp$1,
    mapToColor: mapToColor,
    modifyHSL: modifyHSL,
    modifyAlpha: modifyAlpha,
    stringify: stringify,
    lum: lum,
    random: random
  });
  var arraySlice = Array.prototype.slice;

  function interpolateNumber(p0, p1, percent) {
    return (p1 - p0) * percent + p0;
  }

  function step(p0, p1, percent) {
    return percent > 0.5 ? p1 : p0;
  }

  function interpolate1DArray(out, p0, p1, percent) {
    var len = p0.length;

    for (var i = 0; i < len; i++) {
      out[i] = interpolateNumber(p0[i], p1[i], percent);
    }
  }

  function interpolate2DArray(out, p0, p1, percent) {
    var len = p0.length;
    var len2 = len && p0[0].length;

    for (var i = 0; i < len; i++) {
      if (!out[i]) {
        out[i] = [];
      }

      for (var j = 0; j < len2; j++) {
        out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
      }
    }
  }

  function add1DArray(out, p0, p1, sign) {
    var len = p0.length;

    for (var i = 0; i < len; i++) {
      out[i] = p0[i] + p1[i] * sign;
    }

    return out;
  }

  function add2DArray(out, p0, p1, sign) {
    var len = p0.length;
    var len2 = len && p0[0].length;

    for (var i = 0; i < len; i++) {
      if (!out[i]) {
        out[i] = [];
      }

      for (var j = 0; j < len2; j++) {
        out[i][j] = p0[i][j] + p1[i][j] * sign;
      }
    }

    return out;
  }

  function fillArray(val0, val1, arrDim) {
    var arr0 = val0;
    var arr1 = val1;

    if (!arr0.push || !arr1.push) {
      return;
    }

    var arr0Len = arr0.length;
    var arr1Len = arr1.length;

    if (arr0Len !== arr1Len) {
      var isPreviousLarger = arr0Len > arr1Len;

      if (isPreviousLarger) {
        arr0.length = arr1Len;
      } else {
        for (var i = arr0Len; i < arr1Len; i++) {
          arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
        }
      }
    }

    var len2 = arr0[0] && arr0[0].length;

    for (var i = 0; i < arr0.length; i++) {
      if (arrDim === 1) {
        if (isNaN(arr0[i])) {
          arr0[i] = arr1[i];
        }
      } else {
        for (var j = 0; j < len2; j++) {
          if (isNaN(arr0[i][j])) {
            arr0[i][j] = arr1[i][j];
          }
        }
      }
    }
  }

  function is1DArraySame(arr0, arr1) {
    var len = arr0.length;

    if (len !== arr1.length) {
      return false;
    }

    for (var i = 0; i < len; i++) {
      if (arr0[i] !== arr1[i]) {
        return false;
      }
    }

    return true;
  }

  function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
    var v0 = (p2 - p0) * 0.5;
    var v1 = (p3 - p1) * 0.5;
    return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1;
  }

  function catmullRomInterpolate1DArray(out, p0, p1, p2, p3, t, t2, t3) {
    var len = p0.length;

    for (var i = 0; i < len; i++) {
      out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3);
    }
  }

  function catmullRomInterpolate2DArray(out, p0, p1, p2, p3, t, t2, t3) {
    var len = p0.length;
    var len2 = p0[0].length;

    for (var i = 0; i < len; i++) {
      if (!out[i]) {
        out[1] = [];
      }

      for (var j = 0; j < len2; j++) {
        out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3);
      }
    }
  }

  function cloneValue(value) {
    if (isArrayLike(value)) {
      var len = value.length;

      if (isArrayLike(value[0])) {
        var ret = [];

        for (var i = 0; i < len; i++) {
          ret.push(arraySlice.call(value[i]));
        }

        return ret;
      }

      return arraySlice.call(value);
    }

    return value;
  }

  function rgba2String(rgba) {
    rgba[0] = Math.floor(rgba[0]);
    rgba[1] = Math.floor(rgba[1]);
    rgba[2] = Math.floor(rgba[2]);
    return 'rgba(' + rgba.join(',') + ')';
  }

  function guessArrayDim(value) {
    return isArrayLike(value && value[0]) ? 2 : 1;
  }

  var tmpRgba = [0, 0, 0, 0];

  var Track = function () {
    function Track(propName) {
      this.keyframes = [];
      this.maxTime = 0;
      this.arrDim = 0;
      this.interpolable = true;
      this._needsSort = false;
      this._isAllValueEqual = true;
      this._lastFrame = 0;
      this._lastFramePercent = 0;
      this.propName = propName;
    }

    Track.prototype.isFinished = function () {
      return this._finished;
    };

    Track.prototype.setFinished = function () {
      this._finished = true;

      if (this._additiveTrack) {
        this._additiveTrack.setFinished();
      }
    };

    Track.prototype.needsAnimate = function () {
      return !this._isAllValueEqual && this.keyframes.length >= 2 && this.interpolable;
    };

    Track.prototype.getAdditiveTrack = function () {
      return this._additiveTrack;
    };

    Track.prototype.addKeyframe = function (time, value) {
      if (time >= this.maxTime) {
        this.maxTime = time;
      } else {
        this._needsSort = true;
      }

      var keyframes = this.keyframes;
      var len = keyframes.length;

      if (this.interpolable) {
        if (isArrayLike(value)) {
          var arrayDim = guessArrayDim(value);

          if (len > 0 && this.arrDim !== arrayDim) {
            this.interpolable = false;
            return;
          }

          if (arrayDim === 1 && typeof value[0] !== 'number' || arrayDim === 2 && typeof value[0][0] !== 'number') {
            this.interpolable = false;
            return;
          }

          if (len > 0) {
            var lastFrame = keyframes[len - 1];

            if (this._isAllValueEqual) {
              if (arrayDim === 1) {
                if (!is1DArraySame(value, lastFrame.value)) {
                  this._isAllValueEqual = false;
                }
              } else {
                this._isAllValueEqual = false;
              }
            }
          }

          this.arrDim = arrayDim;
        } else {
          if (this.arrDim > 0) {
            this.interpolable = false;
            return;
          }

          if (typeof value === 'string') {
            var colorArray = parse(value);

            if (colorArray) {
              value = colorArray;
              this.isValueColor = true;
            } else {
              this.interpolable = false;
            }
          } else if (typeof value !== 'number') {
            this.interpolable = false;
            return;
          }

          if (this._isAllValueEqual && len > 0) {
            var lastFrame = keyframes[len - 1];

            if (this.isValueColor && !is1DArraySame(lastFrame.value, value)) {
              this._isAllValueEqual = false;
            } else if (lastFrame.value !== value) {
              this._isAllValueEqual = false;
            }
          }
        }
      }

      var kf = {
        time: time,
        value: value,
        percent: 0
      };
      this.keyframes.push(kf);
      return kf;
    };

    Track.prototype.prepare = function (additiveTrack) {
      var kfs = this.keyframes;

      if (this._needsSort) {
        kfs.sort(function (a, b) {
          return a.time - b.time;
        });
      }

      var arrDim = this.arrDim;
      var kfsLen = kfs.length;
      var lastKf = kfs[kfsLen - 1];

      for (var i = 0; i < kfsLen; i++) {
        kfs[i].percent = kfs[i].time / this.maxTime;

        if (arrDim > 0 && i !== kfsLen - 1) {
          fillArray(kfs[i].value, lastKf.value, arrDim);
        }
      }

      if (additiveTrack && this.needsAnimate() && additiveTrack.needsAnimate() && arrDim === additiveTrack.arrDim && this.isValueColor === additiveTrack.isValueColor && !additiveTrack._finished) {
        this._additiveTrack = additiveTrack;
        var startValue = kfs[0].value;

        for (var i = 0; i < kfsLen; i++) {
          if (arrDim === 0) {
            if (this.isValueColor) {
              kfs[i].additiveValue = add1DArray([], kfs[i].value, startValue, -1);
            } else {
              kfs[i].additiveValue = kfs[i].value - startValue;
            }
          } else if (arrDim === 1) {
            kfs[i].additiveValue = add1DArray([], kfs[i].value, startValue, -1);
          } else if (arrDim === 2) {
            kfs[i].additiveValue = add2DArray([], kfs[i].value, startValue, -1);
          }
        }
      }
    };

    Track.prototype.step = function (target, percent) {
      if (this._finished) {
        return;
      }

      if (this._additiveTrack && this._additiveTrack._finished) {
        this._additiveTrack = null;
      }

      var isAdditive = this._additiveTrack != null;
      var valueKey = isAdditive ? 'additiveValue' : 'value';
      var keyframes = this.keyframes;
      var kfsNum = this.keyframes.length;
      var propName = this.propName;
      var arrDim = this.arrDim;
      var isValueColor = this.isValueColor;
      var frameIdx;

      if (percent < 0) {
        frameIdx = 0;
      } else if (percent < this._lastFramePercent) {
        var start = Math.min(this._lastFrame + 1, kfsNum - 1);

        for (frameIdx = start; frameIdx >= 0; frameIdx--) {
          if (keyframes[frameIdx].percent <= percent) {
            break;
          }
        }

        frameIdx = Math.min(frameIdx, kfsNum - 2);
      } else {
        for (frameIdx = this._lastFrame; frameIdx < kfsNum; frameIdx++) {
          if (keyframes[frameIdx].percent > percent) {
            break;
          }
        }

        frameIdx = Math.min(frameIdx - 1, kfsNum - 2);
      }

      var nextFrame = keyframes[frameIdx + 1];
      var frame = keyframes[frameIdx];

      if (!(frame && nextFrame)) {
        return;
      }

      this._lastFrame = frameIdx;
      this._lastFramePercent = percent;
      var range = nextFrame.percent - frame.percent;

      if (range === 0) {
        return;
      }

      var w = (percent - frame.percent) / range;
      var targetArr = isAdditive ? this._additiveValue : isValueColor ? tmpRgba : target[propName];

      if ((arrDim > 0 || isValueColor) && !targetArr) {
        targetArr = this._additiveValue = [];
      }

      if (this.useSpline) {
        var p1 = keyframes[frameIdx][valueKey];
        var p0 = keyframes[frameIdx === 0 ? frameIdx : frameIdx - 1][valueKey];
        var p2 = keyframes[frameIdx > kfsNum - 2 ? kfsNum - 1 : frameIdx + 1][valueKey];
        var p3 = keyframes[frameIdx > kfsNum - 3 ? kfsNum - 1 : frameIdx + 2][valueKey];

        if (arrDim > 0) {
          arrDim === 1 ? catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w) : catmullRomInterpolate2DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w);
        } else if (isValueColor) {
          catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w);

          if (!isAdditive) {
            target[propName] = rgba2String(targetArr);
          }
        } else {
          var value = void 0;

          if (!this.interpolable) {
            value = p2;
          } else {
            value = catmullRomInterpolate(p0, p1, p2, p3, w, w * w, w * w * w);
          }

          if (isAdditive) {
            this._additiveValue = value;
          } else {
            target[propName] = value;
          }
        }
      } else {
        if (arrDim > 0) {
          arrDim === 1 ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w) : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
        } else if (isValueColor) {
          interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);

          if (!isAdditive) {
            target[propName] = rgba2String(targetArr);
          }
        } else {
          var value = void 0;

          if (!this.interpolable) {
            value = step(frame[valueKey], nextFrame[valueKey], w);
          } else {
            value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w);
          }

          if (isAdditive) {
            this._additiveValue = value;
          } else {
            target[propName] = value;
          }
        }
      }

      if (isAdditive) {
        this._addToTarget(target);
      }
    };

    Track.prototype._addToTarget = function (target) {
      var arrDim = this.arrDim;
      var propName = this.propName;
      var additiveValue = this._additiveValue;

      if (arrDim === 0) {
        if (this.isValueColor) {
          parse(target[propName], tmpRgba);
          add1DArray(tmpRgba, tmpRgba, additiveValue, 1);
          target[propName] = rgba2String(tmpRgba);
        } else {
          target[propName] = target[propName] + additiveValue;
        }
      } else if (arrDim === 1) {
        add1DArray(target[propName], target[propName], additiveValue, 1);
      } else if (arrDim === 2) {
        add2DArray(target[propName], target[propName], additiveValue, 1);
      }
    };

    return Track;
  }();

  var Animator = function () {
    function Animator(target, loop, additiveTo) {
      this._tracks = {};
      this._trackKeys = [];
      this._delay = 0;
      this._maxTime = 0;
      this._paused = false;
      this._started = 0;
      this._clip = null;
      this._target = target;
      this._loop = loop;

      if (loop && additiveTo) {
        logError('Can\' use additive animation on looped animation.');
        return;
      }

      this._additiveAnimators = additiveTo;
    }

    Animator.prototype.getTarget = function () {
      return this._target;
    };

    Animator.prototype.changeTarget = function (target) {
      this._target = target;
    };

    Animator.prototype.when = function (time, props) {
      return this.whenWithKeys(time, props, keys(props));
    };

    Animator.prototype.whenWithKeys = function (time, props, propNames) {
      var tracks = this._tracks;

      for (var i = 0; i < propNames.length; i++) {
        var propName = propNames[i];
        var track = tracks[propName];

        if (!track) {
          track = tracks[propName] = new Track(propName);
          var initialValue = void 0;

          var additiveTrack = this._getAdditiveTrack(propName);

          if (additiveTrack) {
            var lastFinalKf = additiveTrack.keyframes[additiveTrack.keyframes.length - 1];
            initialValue = lastFinalKf && lastFinalKf.value;

            if (additiveTrack.isValueColor && initialValue) {
              initialValue = rgba2String(initialValue);
            }
          } else {
            initialValue = this._target[propName];
          }

          if (initialValue == null) {
            continue;
          }

          if (time !== 0) {
            track.addKeyframe(0, cloneValue(initialValue));
          }

          this._trackKeys.push(propName);
        }

        track.addKeyframe(time, cloneValue(props[propName]));
      }

      this._maxTime = Math.max(this._maxTime, time);
      return this;
    };

    Animator.prototype.pause = function () {
      this._clip.pause();

      this._paused = true;
    };

    Animator.prototype.resume = function () {
      this._clip.resume();

      this._paused = false;
    };

    Animator.prototype.isPaused = function () {
      return !!this._paused;
    };

    Animator.prototype._doneCallback = function () {
      this._setTracksFinished();

      this._clip = null;
      var doneList = this._doneList;

      if (doneList) {
        var len = doneList.length;

        for (var i = 0; i < len; i++) {
          doneList[i].call(this);
        }
      }
    };

    Animator.prototype._abortedCallback = function () {
      this._setTracksFinished();

      var animation = this.animation;
      var abortedList = this._abortedList;

      if (animation) {
        animation.removeClip(this._clip);
      }

      this._clip = null;

      if (abortedList) {
        for (var i = 0; i < abortedList.length; i++) {
          abortedList[i].call(this);
        }
      }
    };

    Animator.prototype._setTracksFinished = function () {
      var tracks = this._tracks;
      var tracksKeys = this._trackKeys;

      for (var i = 0; i < tracksKeys.length; i++) {
        tracks[tracksKeys[i]].setFinished();
      }
    };

    Animator.prototype._getAdditiveTrack = function (trackName) {
      var additiveTrack;
      var additiveAnimators = this._additiveAnimators;

      if (additiveAnimators) {
        for (var i = 0; i < additiveAnimators.length; i++) {
          var track = additiveAnimators[i].getTrack(trackName);

          if (track) {
            additiveTrack = track;
          }
        }
      }

      return additiveTrack;
    };

    Animator.prototype.start = function (easing, forceAnimate) {
      if (this._started > 0) {
        return;
      }

      this._started = 1;
      var self = this;
      var tracks = [];

      for (var i = 0; i < this._trackKeys.length; i++) {
        var propName = this._trackKeys[i];
        var track = this._tracks[propName];

        var additiveTrack = this._getAdditiveTrack(propName);

        var kfs = track.keyframes;
        track.prepare(additiveTrack);

        if (track.needsAnimate()) {
          tracks.push(track);
        } else if (!track.interpolable) {
          var lastKf = kfs[kfs.length - 1];

          if (lastKf) {
            self._target[track.propName] = lastKf.value;
          }
        }
      }

      if (tracks.length || forceAnimate) {
        var clip = new Clip({
          life: this._maxTime,
          loop: this._loop,
          delay: this._delay,
          onframe: function (percent) {
            self._started = 2;
            var additiveAnimators = self._additiveAnimators;

            if (additiveAnimators) {
              var stillHasAdditiveAnimator = false;

              for (var i = 0; i < additiveAnimators.length; i++) {
                if (additiveAnimators[i]._clip) {
                  stillHasAdditiveAnimator = true;
                  break;
                }
              }

              if (!stillHasAdditiveAnimator) {
                self._additiveAnimators = null;
              }
            }

            for (var i = 0; i < tracks.length; i++) {
              tracks[i].step(self._target, percent);
            }

            var onframeList = self._onframeList;

            if (onframeList) {
              for (var i = 0; i < onframeList.length; i++) {
                onframeList[i](self._target, percent);
              }
            }
          },
          ondestroy: function () {
            self._doneCallback();
          }
        });
        this._clip = clip;

        if (this.animation) {
          this.animation.addClip(clip);
        }

        if (easing && easing !== 'spline') {
          clip.easing = easing;
        }
      } else {
        this._doneCallback();
      }

      return this;
    };

    Animator.prototype.stop = function (forwardToLast) {
      if (!this._clip) {
        return;
      }

      var clip = this._clip;

      if (forwardToLast) {
        clip.onframe(1);
      }

      this._abortedCallback();
    };

    Animator.prototype.delay = function (time) {
      this._delay = time;
      return this;
    };

    Animator.prototype.during = function (cb) {
      if (cb) {
        if (!this._onframeList) {
          this._onframeList = [];
        }

        this._onframeList.push(cb);
      }

      return this;
    };

    Animator.prototype.done = function (cb) {
      if (cb) {
        if (!this._doneList) {
          this._doneList = [];
        }

        this._doneList.push(cb);
      }

      return this;
    };

    Animator.prototype.aborted = function (cb) {
      if (cb) {
        if (!this._abortedList) {
          this._abortedList = [];
        }

        this._abortedList.push(cb);
      }

      return this;
    };

    Animator.prototype.getClip = function () {
      return this._clip;
    };

    Animator.prototype.getTrack = function (propName) {
      return this._tracks[propName];
    };

    Animator.prototype.stopTracks = function (propNames, forwardToLast) {
      if (!propNames.length || !this._clip) {
        return true;
      }

      var tracks = this._tracks;
      var tracksKeys = this._trackKeys;

      for (var i = 0; i < propNames.length; i++) {
        var track = tracks[propNames[i]];

        if (track) {
          if (forwardToLast) {
            track.step(this._target, 1);
          } else if (this._started === 1) {
            track.step(this._target, 0);
          }

          track.setFinished();
        }
      }

      var allAborted = true;

      for (var i = 0; i < tracksKeys.length; i++) {
        if (!tracks[tracksKeys[i]].isFinished()) {
          allAborted = false;
          break;
        }
      }

      if (allAborted) {
        this._abortedCallback();
      }

      return allAborted;
    };

    Animator.prototype.saveFinalToTarget = function (target, trackKeys) {
      if (!target) {
        return;
      }

      trackKeys = trackKeys || this._trackKeys;

      for (var i = 0; i < trackKeys.length; i++) {
        var propName = trackKeys[i];
        var track = this._tracks[propName];

        if (!track || track.isFinished()) {
          continue;
        }

        var kfs = track.keyframes;
        var lastKf = kfs[kfs.length - 1];

        if (lastKf) {
          var val = cloneValue(lastKf.value);

          if (track.isValueColor) {
            val = rgba2String(val);
          }

          target[propName] = val;
        }
      }
    };

    Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) {
      trackKeys = trackKeys || keys(finalProps);

      for (var i = 0; i < trackKeys.length; i++) {
        var propName = trackKeys[i];
        var track = this._tracks[propName];

        if (!track) {
          continue;
        }

        var kfs = track.keyframes;

        if (kfs.length > 1) {
          var lastKf = kfs.pop();
          track.addKeyframe(lastKf.time, finalProps[propName]);
          track.prepare(track.getAdditiveTrack());
        }
      }
    };

    return Animator;
  }();

  var Point = function () {
    function Point(x, y) {
      this.x = x || 0;
      this.y = y || 0;
    }

    Point.prototype.copy = function (other) {
      this.x = other.x;
      this.y = other.y;
      return this;
    };

    Point.prototype.clone = function () {
      return new Point(this.x, this.y);
    };

    Point.prototype.set = function (x, y) {
      this.x = x;
      this.y = y;
      return this;
    };

    Point.prototype.equal = function (other) {
      return other.x === this.x && other.y === this.y;
    };

    Point.prototype.add = function (other) {
      this.x += other.x;
      this.y += other.y;
      return this;
    };

    Point.prototype.scale = function (scalar) {
      this.x *= scalar;
      this.y *= scalar;
    };

    Point.prototype.scaleAndAdd = function (other, scalar) {
      this.x += other.x * scalar;
      this.y += other.y * scalar;
    };

    Point.prototype.sub = function (other) {
      this.x -= other.x;
      this.y -= other.y;
      return this;
    };

    Point.prototype.dot = function (other) {
      return this.x * other.x + this.y * other.y;
    };

    Point.prototype.len = function () {
      return Math.sqrt(this.x * this.x + this.y * this.y);
    };

    Point.prototype.lenSquare = function () {
      return this.x * this.x + this.y * this.y;
    };

    Point.prototype.normalize = function () {
      var len = this.len();
      this.x /= len;
      this.y /= len;
      return this;
    };

    Point.prototype.distance = function (other) {
      var dx = this.x - other.x;
      var dy = this.y - other.y;
      return Math.sqrt(dx * dx + dy * dy);
    };

    Point.prototype.distanceSquare = function (other) {
      var dx = this.x - other.x;
      var dy = this.y - other.y;
      return dx * dx + dy * dy;
    };

    Point.prototype.negate = function () {
      this.x = -this.x;
      this.y = -this.y;
      return this;
    };

    Point.prototype.transform = function (m) {
      if (!m) {
        return;
      }

      var x = this.x;
      var y = this.y;
      this.x = m[0] * x + m[2] * y + m[4];
      this.y = m[1] * x + m[3] * y + m[5];
      return this;
    };

    Point.prototype.toArray = function (out) {
      out[0] = this.x;
      out[1] = this.y;
      return out;
    };

    Point.prototype.fromArray = function (input) {
      this.x = input[0];
      this.y = input[1];
    };

    Point.set = function (p, x, y) {
      p.x = x;
      p.y = y;
    };

    Point.copy = function (p, p2) {
      p.x = p2.x;
      p.y = p2.y;
    };

    Point.len = function (p) {
      return Math.sqrt(p.x * p.x + p.y * p.y);
    };

    Point.lenSquare = function (p) {
      return p.x * p.x + p.y * p.y;
    };

    Point.dot = function (p0, p1) {
      return p0.x * p1.x + p0.y * p1.y;
    };

    Point.add = function (out, p0, p1) {
      out.x = p0.x + p1.x;
      out.y = p0.y + p1.y;
    };

    Point.sub = function (out, p0, p1) {
      out.x = p0.x - p1.x;
      out.y = p0.y - p1.y;
    };

    Point.scale = function (out, p0, scalar) {
      out.x = p0.x * scalar;
      out.y = p0.y * scalar;
    };

    Point.scaleAndAdd = function (out, p0, p1, scalar) {
      out.x = p0.x + p1.x * scalar;
      out.y = p0.y + p1.y * scalar;
    };

    Point.lerp = function (out, p0, p1, t) {
      var onet = 1 - t;
      out.x = onet * p0.x + t * p1.x;
      out.y = onet * p0.y + t * p1.y;
    };

    return Point;
  }();

  var mathMin = Math.min;
  var mathMax = Math.max;
  var lt = new Point();
  var rb = new Point();
  var lb = new Point();
  var rt = new Point();
  var minTv = new Point();
  var maxTv = new Point();

  var BoundingRect = function () {
    function BoundingRect(x, y, width, height) {
      if (width < 0 && isFinite(width)) {
        x = x + width;
        width = -width;
      }

      if (height < 0 && isFinite(height)) {
        y = y + height;
        height = -height;
      }

      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
    }

    BoundingRect.prototype.union = function (other) {
      var x = mathMin(other.x, this.x);
      var y = mathMin(other.y, this.y);

      if (isFinite(this.x) && isFinite(this.width)) {
        this.width = mathMax(other.x + other.width, this.x + this.width) - x;
      } else {
        this.width = other.width;
      }

      if (isFinite(this.y) && isFinite(this.height)) {
        this.height = mathMax(other.y + other.height, this.y + this.height) - y;
      } else {
        this.height = other.height;
      }

      this.x = x;
      this.y = y;
    };

    BoundingRect.prototype.applyTransform = function (m) {
      BoundingRect.applyTransform(this, this, m);
    };

    BoundingRect.prototype.calculateTransform = function (b) {
      var a = this;
      var sx = b.width / a.width;
      var sy = b.height / a.height;
      var m = create$1();
      translate(m, m, [-a.x, -a.y]);
      scale$1(m, m, [sx, sy]);
      translate(m, m, [b.x, b.y]);
      return m;
    };

    BoundingRect.prototype.intersect = function (b, mtv) {
      if (!b) {
        return false;
      }

      if (!(b instanceof BoundingRect)) {
        b = BoundingRect.create(b);
      }

      var a = this;
      var ax0 = a.x;
      var ax1 = a.x + a.width;
      var ay0 = a.y;
      var ay1 = a.y + a.height;
      var bx0 = b.x;
      var bx1 = b.x + b.width;
      var by0 = b.y;
      var by1 = b.y + b.height;
      var overlap = !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);

      if (mtv) {
        var dMin = Infinity;
        var dMax = 0;
        var d0 = Math.abs(ax1 - bx0);
        var d1 = Math.abs(bx1 - ax0);
        var d2 = Math.abs(ay1 - by0);
        var d3 = Math.abs(by1 - ay0);
        var dx = Math.min(d0, d1);
        var dy = Math.min(d2, d3);

        if (ax1 < bx0 || bx1 < ax0) {
          if (dx > dMax) {
            dMax = dx;

            if (d0 < d1) {
              Point.set(maxTv, -d0, 0);
            } else {
              Point.set(maxTv, d1, 0);
            }
          }
        } else {
          if (dx < dMin) {
            dMin = dx;

            if (d0 < d1) {
              Point.set(minTv, d0, 0);
            } else {
              Point.set(minTv, -d1, 0);
            }
          }
        }

        if (ay1 < by0 || by1 < ay0) {
          if (dy > dMax) {
            dMax = dy;

            if (d2 < d3) {
              Point.set(maxTv, 0, -d2);
            } else {
              Point.set(maxTv, 0, d3);
            }
          }
        } else {
          if (dx < dMin) {
            dMin = dx;

            if (d2 < d3) {
              Point.set(minTv, 0, d2);
            } else {
              Point.set(minTv, 0, -d3);
            }
          }
        }
      }

      if (mtv) {
        Point.copy(mtv, overlap ? minTv : maxTv);
      }

      return overlap;
    };

    BoundingRect.prototype.contain = function (x, y) {
      var rect = this;
      return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
    };

    BoundingRect.prototype.clone = function () {
      return new BoundingRect(this.x, this.y, this.width, this.height);
    };

    BoundingRect.prototype.copy = function (other) {
      BoundingRect.copy(this, other);
    };

    BoundingRect.prototype.plain = function () {
      return {
        x: this.x,
        y: this.y,
        width: this.width,
        height: this.height
      };
    };

    BoundingRect.prototype.isFinite = function () {
      return isFinite(this.x) && isFinite(this.y) && isFinite(this.width) && isFinite(this.height);
    };

    BoundingRect.prototype.isZero = function () {
      return this.width === 0 || this.height === 0;
    };

    BoundingRect.create = function (rect) {
      return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
    };

    BoundingRect.copy = function (target, source) {
      target.x = source.x;
      target.y = source.y;
      target.width = source.width;
      target.height = source.height;
    };

    BoundingRect.applyTransform = function (target, source, m) {
      if (!m) {
        if (target !== source) {
          BoundingRect.copy(target, source);
        }

        return;
      }

      if (m[1] < 1e-5 && m[1] > -1e-5 && m[2] < 1e-5 && m[2] > -1e-5) {
        var sx = m[0];
        var sy = m[3];
        var tx = m[4];
        var ty = m[5];
        target.x = source.x * sx + tx;
        target.y = source.y * sy + ty;
        target.width = source.width * sx;
        target.height = source.height * sy;

        if (target.width < 0) {
          target.x += target.width;
          target.width = -target.width;
        }

        if (target.height < 0) {
          target.y += target.height;
          target.height = -target.height;
        }

        return;
      }

      lt.x = lb.x = source.x;
      lt.y = rt.y = source.y;
      rb.x = rt.x = source.x + source.width;
      rb.y = lb.y = source.y + source.height;
      lt.transform(m);
      rt.transform(m);
      rb.transform(m);
      lb.transform(m);
      target.x = mathMin(lt.x, rb.x, lb.x, rt.x);
      target.y = mathMin(lt.y, rb.y, lb.y, rt.y);
      var maxX = mathMax(lt.x, rb.x, lb.x, rt.x);
      var maxY = mathMax(lt.y, rb.y, lb.y, rt.y);
      target.width = maxX - target.x;
      target.height = maxY - target.y;
    };

    return BoundingRect;
  }();

  var textWidthCache = {};
  var DEFAULT_FONT = '12px sans-serif';

  var _ctx;

  var _cachedFont;

  function defaultMeasureText(text, font) {
    if (!_ctx) {
      _ctx = createCanvas().getContext('2d');
    }

    if (_cachedFont !== font) {
      _cachedFont = _ctx.font = font || DEFAULT_FONT;
    }

    return _ctx.measureText(text);
  }

  var methods$1 = {
    measureText: defaultMeasureText
  };

  function getWidth(text, font) {
    font = font || DEFAULT_FONT;
    var cacheOfFont = textWidthCache[font];

    if (!cacheOfFont) {
      cacheOfFont = textWidthCache[font] = new LRU(500);
    }

    var width = cacheOfFont.get(text);

    if (width == null) {
      width = methods$1.measureText(text, font).width;
      cacheOfFont.put(text, width);
    }

    return width;
  }

  function innerGetBoundingRect(text, font, textAlign, textBaseline) {
    var width = getWidth(text, font);
    var height = getLineHeight(font);
    var x = adjustTextX(0, width, textAlign);
    var y = adjustTextY(0, height, textBaseline);
    var rect = new BoundingRect(x, y, width, height);
    return rect;
  }

  function getBoundingRect(text, font, textAlign, textBaseline) {
    var textLines = ((text || '') + '').split('\n');
    var len = textLines.length;

    if (len === 1) {
      return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline);
    } else {
      var uniondRect = new BoundingRect(0, 0, 0, 0);

      for (var i = 0; i < textLines.length; i++) {
        var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline);
        i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect);
      }

      return uniondRect;
    }
  }

  function adjustTextX(x, width, textAlign) {
    if (textAlign === 'right') {
      x -= width;
    } else if (textAlign === 'center') {
      x -= width / 2;
    }

    return x;
  }

  function adjustTextY(y, height, verticalAlign) {
    if (verticalAlign === 'middle') {
      y -= height / 2;
    } else if (verticalAlign === 'bottom') {
      y -= height;
    }

    return y;
  }

  function getLineHeight(font) {
    return getWidth('国', font);
  }

  function parsePercent(value, maxValue) {
    if (typeof value === 'string') {
      if (value.lastIndexOf('%') >= 0) {
        return parseFloat(value) / 100 * maxValue;
      }

      return parseFloat(value);
    }

    return value;
  }

  function calculateTextPosition(out, opts, rect) {
    var textPosition = opts.position || 'inside';
    var distance = opts.distance != null ? opts.distance : 5;
    var height = rect.height;
    var width = rect.width;
    var halfHeight = height / 2;
    var x = rect.x;
    var y = rect.y;
    var textAlign = 'left';
    var textVerticalAlign = 'top';

    if (textPosition instanceof Array) {
      x += parsePercent(textPosition[0], rect.width);
      y += parsePercent(textPosition[1], rect.height);
      textAlign = null;
      textVerticalAlign = null;
    } else {
      switch (textPosition) {
        case 'left':
          x -= distance;
          y += halfHeight;
          textAlign = 'right';
          textVerticalAlign = 'middle';
          break;

        case 'right':
          x += distance + width;
          y += halfHeight;
          textVerticalAlign = 'middle';
          break;

        case 'top':
          x += width / 2;
          y -= distance;
          textAlign = 'center';
          textVerticalAlign = 'bottom';
          break;

        case 'bottom':
          x += width / 2;
          y += height + distance;
          textAlign = 'center';
          break;

        case 'inside':
          x += width / 2;
          y += halfHeight;
          textAlign = 'center';
          textVerticalAlign = 'middle';
          break;

        case 'insideLeft':
          x += distance;
          y += halfHeight;
          textVerticalAlign = 'middle';
          break;

        case 'insideRight':
          x += width - distance;
          y += halfHeight;
          textAlign = 'right';
          textVerticalAlign = 'middle';
          break;

        case 'insideTop':
          x += width / 2;
          y += distance;
          textAlign = 'center';
          break;

        case 'insideBottom':
          x += width / 2;
          y += height - distance;
          textAlign = 'center';
          textVerticalAlign = 'bottom';
          break;

        case 'insideTopLeft':
          x += distance;
          y += distance;
          break;

        case 'insideTopRight':
          x += width - distance;
          y += distance;
          textAlign = 'right';
          break;

        case 'insideBottomLeft':
          x += distance;
          y += height - distance;
          textVerticalAlign = 'bottom';
          break;

        case 'insideBottomRight':
          x += width - distance;
          y += height - distance;
          textAlign = 'right';
          textVerticalAlign = 'bottom';
          break;
      }
    }

    out = out || {};
    out.x = x;
    out.y = y;
    out.align = textAlign;
    out.verticalAlign = textVerticalAlign;
    return out;
  }

  var dpr = 1;

  if (typeof window !== 'undefined') {
    dpr = Math.max(window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI || 1, 1);
  }

  var devicePixelRatio = dpr;
  var DARK_MODE_THRESHOLD = 0.4;
  var DARK_LABEL_COLOR = '#333';
  var LIGHT_LABEL_COLOR = '#ccc';
  var LIGHTER_LABEL_COLOR = '#eee';
  var PRESERVED_NORMAL_STATE = '__zr_normal__';
  var PRIMARY_STATES_KEYS = ['x', 'y', 'scaleX', 'scaleY', 'originX', 'originY', 'rotation', 'ignore'];
  var DEFAULT_ANIMATABLE_MAP = {
    x: true,
    y: true,
    scaleX: true,
    scaleY: true,
    originX: true,
    originY: true,
    rotation: true,
    ignore: false
  };
  var tmpTextPosCalcRes = {};
  var tmpBoundingRect = new BoundingRect(0, 0, 0, 0);

  var Element = function () {
    function Element(props) {
      this.id = guid();
      this.animators = [];
      this.currentStates = [];
      this.states = {};

      this._init(props);
    }

    Element.prototype._init = function (props) {
      this.attr(props);
    };

    Element.prototype.drift = function (dx, dy, e) {
      switch (this.draggable) {
        case 'horizontal':
          dy = 0;
          break;

        case 'vertical':
          dx = 0;
          break;
      }

      var m = this.transform;

      if (!m) {
        m = this.transform = [1, 0, 0, 1, 0, 0];
      }

      m[4] += dx;
      m[5] += dy;
      this.decomposeTransform();
      this.markRedraw();
    };

    Element.prototype.beforeUpdate = function () {};

    Element.prototype.afterUpdate = function () {};

    Element.prototype.update = function () {
      this.updateTransform();

      if (this.__dirty) {
        this.updateInnerText();
      }
    };

    Element.prototype.updateInnerText = function (forceUpdate) {
      var textEl = this._textContent;

      if (textEl && (!textEl.ignore || forceUpdate)) {
        if (!this.textConfig) {
          this.textConfig = {};
        }

        var textConfig = this.textConfig;
        var isLocal = textConfig.local;
        var attachedTransform = textEl.attachedTransform;
        var textAlign = void 0;
        var textVerticalAlign = void 0;
        var textStyleChanged = false;

        if (isLocal) {
          attachedTransform.parent = this;
        } else {
          attachedTransform.parent = null;
        }

        var innerOrigin = false;
        attachedTransform.x = textEl.x;
        attachedTransform.y = textEl.y;
        attachedTransform.originX = textEl.originX;
        attachedTransform.originY = textEl.originY;
        attachedTransform.rotation = textEl.rotation;
        attachedTransform.scaleX = textEl.scaleX;
        attachedTransform.scaleY = textEl.scaleY;

        if (textConfig.position != null) {
          var layoutRect = tmpBoundingRect;

          if (textConfig.layoutRect) {
            layoutRect.copy(textConfig.layoutRect);
          } else {
            layoutRect.copy(this.getBoundingRect());
          }

          if (!isLocal) {
            layoutRect.applyTransform(this.transform);
          }

          if (this.calculateTextPosition) {
            this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
          } else {
            calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
          }

          attachedTransform.x = tmpTextPosCalcRes.x;
          attachedTransform.y = tmpTextPosCalcRes.y;
          textAlign = tmpTextPosCalcRes.align;
          textVerticalAlign = tmpTextPosCalcRes.verticalAlign;
          var textOrigin = textConfig.origin;

          if (textOrigin && textConfig.rotation != null) {
            var relOriginX = void 0;
            var relOriginY = void 0;

            if (textOrigin === 'center') {
              relOriginX = layoutRect.width * 0.5;
              relOriginY = layoutRect.height * 0.5;
            } else {
              relOriginX = parsePercent(textOrigin[0], layoutRect.width);
              relOriginY = parsePercent(textOrigin[1], layoutRect.height);
            }

            innerOrigin = true;
            attachedTransform.originX = -attachedTransform.x + relOriginX + (isLocal ? 0 : layoutRect.x);
            attachedTransform.originY = -attachedTransform.y + relOriginY + (isLocal ? 0 : layoutRect.y);
          }
        }

        if (textConfig.rotation != null) {
          attachedTransform.rotation = textConfig.rotation;
        }

        var textOffset = textConfig.offset;

        if (textOffset) {
          attachedTransform.x += textOffset[0];
          attachedTransform.y += textOffset[1];

          if (!innerOrigin) {
            attachedTransform.originX = -textOffset[0];
            attachedTransform.originY = -textOffset[1];
          }
        }

        var isInside = textConfig.inside == null ? typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0 : textConfig.inside;
        var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {});
        var textFill = void 0;
        var textStroke = void 0;
        var autoStroke = void 0;

        if (isInside && this.canBeInsideText()) {
          textFill = textConfig.insideFill;
          textStroke = textConfig.insideStroke;

          if (textFill == null || textFill === 'auto') {
            textFill = this.getInsideTextFill();
          }

          if (textStroke == null || textStroke === 'auto') {
            textStroke = this.getInsideTextStroke(textFill);
            autoStroke = true;
          }
        } else {
          textFill = textConfig.outsideFill;
          textStroke = textConfig.outsideStroke;

          if (textFill == null || textFill === 'auto') {
            textFill = this.getOutsideFill();
          }

          if (textStroke == null || textStroke === 'auto') {
            textStroke = this.getOutsideStroke(textFill);
            autoStroke = true;
          }
        }

        textFill = textFill || '#000';

        if (textFill !== innerTextDefaultStyle.fill || textStroke !== innerTextDefaultStyle.stroke || autoStroke !== innerTextDefaultStyle.autoStroke || textAlign !== innerTextDefaultStyle.align || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) {
          textStyleChanged = true;
          innerTextDefaultStyle.fill = textFill;
          innerTextDefaultStyle.stroke = textStroke;
          innerTextDefaultStyle.autoStroke = autoStroke;
          innerTextDefaultStyle.align = textAlign;
          innerTextDefaultStyle.verticalAlign = textVerticalAlign;
          textEl.setDefaultTextStyle(innerTextDefaultStyle);
        }

        if (textStyleChanged) {
          textEl.dirtyStyle();
        }

        textEl.markRedraw();
      }
    };

    Element.prototype.canBeInsideText = function () {
      return true;
    };

    Element.prototype.getInsideTextFill = function () {
      return '#fff';
    };

    Element.prototype.getInsideTextStroke = function (textFill) {
      return '#000';
    };

    Element.prototype.getOutsideFill = function () {
      return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR;
    };

    Element.prototype.getOutsideStroke = function (textFill) {
      var backgroundColor = this.__zr && this.__zr.getBackgroundColor();

      var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor);

      if (!colorArr) {
        colorArr = [255, 255, 255, 1];
      }

      var alpha = colorArr[3];

      var isDark = this.__zr.isDarkMode();

      for (var i = 0; i < 3; i++) {
        colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha);
      }

      colorArr[3] = 1;
      return stringify(colorArr, 'rgba');
    };

    Element.prototype.traverse = function (cb, context) {};

    Element.prototype.attrKV = function (key, value) {
      if (key === 'textConfig') {
        this.setTextConfig(value);
      } else if (key === 'textContent') {
        this.setTextContent(value);
      } else if (key === 'clipPath') {
        this.setClipPath(value);
      } else if (key === 'extra') {
        this.extra = this.extra || {};
        extend(this.extra, value);
      } else {
        this[key] = value;
      }
    };

    Element.prototype.hide = function () {
      this.ignore = true;
      this.markRedraw();
    };

    Element.prototype.show = function () {
      this.ignore = false;
      this.markRedraw();
    };

    Element.prototype.attr = function (keyOrObj, value) {
      if (typeof keyOrObj === 'string') {
        this.attrKV(keyOrObj, value);
      } else if (isObject(keyOrObj)) {
        var obj = keyOrObj;
        var keysArr = keys(obj);

        for (var i = 0; i < keysArr.length; i++) {
          var key = keysArr[i];
          this.attrKV(key, keyOrObj[key]);
        }
      }

      this.markRedraw();
      return this;
    };

    Element.prototype.saveCurrentToNormalState = function (toState) {
      this._innerSaveToNormal(toState);

      var normalState = this._normalState;

      for (var i = 0; i < this.animators.length; i++) {
        var animator = this.animators[i];
        var fromStateTransition = animator.__fromStateTransition;

        if (fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) {
          continue;
        }

        var targetName = animator.targetName;
        var target = targetName ? normalState[targetName] : normalState;
        animator.saveFinalToTarget(target);
      }
    };

    Element.prototype._innerSaveToNormal = function (toState) {
      var normalState = this._normalState;

      if (!normalState) {
        normalState = this._normalState = {};
      }

      if (toState.textConfig && !normalState.textConfig) {
        normalState.textConfig = this.textConfig;
      }

      this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS);
    };

    Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) {
      for (var i = 0; i < primaryKeys.length; i++) {
        var key = primaryKeys[i];

        if (toState[key] != null && !(key in normalState)) {
          normalState[key] = this[key];
        }
      }
    };

    Element.prototype.hasState = function () {
      return this.currentStates.length > 0;
    };

    Element.prototype.getState = function (name) {
      return this.states[name];
    };

    Element.prototype.ensureState = function (name) {
      var states = this.states;

      if (!states[name]) {
        states[name] = {};
      }

      return states[name];
    };

    Element.prototype.clearStates = function (noAnimation) {
      this.useState(PRESERVED_NORMAL_STATE, false, noAnimation);
    };

    Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation) {
      var toNormalState = stateName === PRESERVED_NORMAL_STATE;
      var hasStates = this.hasState();

      if (!hasStates && toNormalState) {
        return;
      }

      var currentStates = this.currentStates;
      var animationCfg = this.stateTransition;

      if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) {
        return;
      }

      var state;

      if (this.stateProxy && !toNormalState) {
        state = this.stateProxy(stateName);
      }

      if (!state) {
        state = this.states && this.states[stateName];
      }

      if (!state && !toNormalState) {
        logError("State " + stateName + " not exists.");
        return;
      }

      if (!toNormalState) {
        this.saveCurrentToNormalState(state);
      }

      var useHoverLayer = !!(state && state.hoverLayer);

      if (useHoverLayer) {
        this._toggleHoverLayerFlag(true);
      }

      this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);

      if (this._textContent) {
        this._textContent.useState(stateName, keepCurrentStates);
      }

      if (this._textGuide) {
        this._textGuide.useState(stateName, keepCurrentStates);
      }

      if (toNormalState) {
        this.currentStates = [];
        this._normalState = {};
      } else {
        if (!keepCurrentStates) {
          this.currentStates = [stateName];
        } else {
          this.currentStates.push(stateName);
        }
      }

      this._updateAnimationTargets();

      this.markRedraw();

      if (!useHoverLayer && this.__inHover) {
        this._toggleHoverLayerFlag(false);

        this.__dirty &= ~Element.REDARAW_BIT;
      }

      return state;
    };

    Element.prototype.useStates = function (states, noAnimation) {
      if (!states.length) {
        this.clearStates();
      } else {
        var stateObjects = [];
        var currentStates = this.currentStates;
        var len = states.length;
        var notChange = len === currentStates.length;

        if (notChange) {
          for (var i = 0; i < len; i++) {
            if (states[i] !== currentStates[i]) {
              notChange = false;
              break;
            }
          }
        }

        if (notChange) {
          return;
        }

        for (var i = 0; i < len; i++) {
          var stateName = states[i];
          var stateObj = void 0;

          if (this.stateProxy) {
            stateObj = this.stateProxy(stateName, states);
          }

          if (!stateObj) {
            stateObj = this.states[stateName];
          }

          if (stateObj) {
            stateObjects.push(stateObj);
          }
        }

        var useHoverLayer = !!(stateObjects[len - 1] && stateObjects[len - 1].hoverLayer);

        if (useHoverLayer) {
          this._toggleHoverLayerFlag(true);
        }

        var mergedState = this._mergeStates(stateObjects);

        var animationCfg = this.stateTransition;
        this.saveCurrentToNormalState(mergedState);

        this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);

        if (this._textContent) {
          this._textContent.useStates(states);
        }

        if (this._textGuide) {
          this._textGuide.useStates(states);
        }

        this._updateAnimationTargets();

        this.currentStates = states.slice();
        this.markRedraw();

        if (!useHoverLayer && this.__inHover) {
          this._toggleHoverLayerFlag(false);

          this.__dirty &= ~Element.REDARAW_BIT;
        }
      }
    };

    Element.prototype._updateAnimationTargets = function () {
      for (var i = 0; i < this.animators.length; i++) {
        var animator = this.animators[i];

        if (animator.targetName) {
          animator.changeTarget(this[animator.targetName]);
        }
      }
    };

    Element.prototype.removeState = function (state) {
      var idx = indexOf(this.currentStates, state);

      if (idx >= 0) {
        var currentStates = this.currentStates.slice();
        currentStates.splice(idx, 1);
        this.useStates(currentStates);
      }
    };

    Element.prototype.replaceState = function (oldState, newState, forceAdd) {
      var currentStates = this.currentStates.slice();
      var idx = indexOf(currentStates, oldState);
      var newStateExists = indexOf(currentStates, newState) >= 0;

      if (idx >= 0) {
        if (!newStateExists) {
          currentStates[idx] = newState;
        } else {
          currentStates.splice(idx, 1);
        }
      } else if (forceAdd && !newStateExists) {
        currentStates.push(newState);
      }

      this.useStates(currentStates);
    };

    Element.prototype.toggleState = function (state, enable) {
      if (enable) {
        this.useState(state, true);
      } else {
        this.removeState(state);
      }
    };

    Element.prototype._mergeStates = function (states) {
      var mergedState = {};
      var mergedTextConfig;

      for (var i = 0; i < states.length; i++) {
        var state = states[i];
        extend(mergedState, state);

        if (state.textConfig) {
          mergedTextConfig = mergedTextConfig || {};
          extend(mergedTextConfig, state.textConfig);
        }
      }

      if (mergedTextConfig) {
        mergedState.textConfig = mergedTextConfig;
      }

      return mergedState;
    };

    Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
      var needsRestoreToNormal = !(state && keepCurrentStates);

      if (state && state.textConfig) {
        this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig);
        extend(this.textConfig, state.textConfig);
      } else if (needsRestoreToNormal) {
        if (normalState.textConfig) {
          this.textConfig = normalState.textConfig;
        }
      }

      var transitionTarget = {};
      var hasTransition = false;

      for (var i = 0; i < PRIMARY_STATES_KEYS.length; i++) {
        var key = PRIMARY_STATES_KEYS[i];
        var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key];

        if (state && state[key] != null) {
          if (propNeedsTransition) {
            hasTransition = true;
            transitionTarget[key] = state[key];
          } else {
            this[key] = state[key];
          }
        } else if (needsRestoreToNormal) {
          if (normalState[key] != null) {
            if (propNeedsTransition) {
              hasTransition = true;
              transitionTarget[key] = normalState[key];
            } else {
              this[key] = normalState[key];
            }
          }
        }
      }

      if (!transition) {
        for (var i = 0; i < this.animators.length; i++) {
          var animator = this.animators[i];
          var targetName = animator.targetName;

          animator.__changeFinalValue(targetName ? (state || normalState)[targetName] : state || normalState);
        }
      }

      if (hasTransition) {
        this._transitionState(stateName, transitionTarget, animationCfg);
      }
    };

    Element.prototype._attachComponent = function (componentEl) {
      if (componentEl.__zr && !componentEl.__hostTarget) {
        throw new Error('Text element has been added to zrender.');
      }

      if (componentEl === this) {
        throw new Error('Recursive component attachment.');
      }

      var zr = this.__zr;

      if (zr) {
        componentEl.addSelfToZr(zr);
      }

      componentEl.__zr = zr;
      componentEl.__hostTarget = this;
    };

    Element.prototype._detachComponent = function (componentEl) {
      if (componentEl.__zr) {
        componentEl.removeSelfFromZr(componentEl.__zr);
      }

      componentEl.__zr = null;
      componentEl.__hostTarget = null;
    };

    Element.prototype.getClipPath = function () {
      return this._clipPath;
    };

    Element.prototype.setClipPath = function (clipPath) {
      if (this._clipPath && this._clipPath !== clipPath) {
        this.removeClipPath();
      }

      this._attachComponent(clipPath);

      this._clipPath = clipPath;
      this.markRedraw();
    };

    Element.prototype.removeClipPath = function () {
      var clipPath = this._clipPath;

      if (clipPath) {
        this._detachComponent(clipPath);

        this._clipPath = null;
        this.markRedraw();
      }
    };

    Element.prototype.getTextContent = function () {
      return this._textContent;
    };

    Element.prototype.setTextContent = function (textEl) {
      var previousTextContent = this._textContent;

      if (previousTextContent === textEl) {
        return;
      }

      if (previousTextContent && previousTextContent !== textEl) {
        this.removeTextContent();
      }

      if (textEl.__zr && !textEl.__hostTarget) {
        throw new Error('Text element has been added to zrender.');
      }

      textEl.attachedTransform = new Transformable();

      this._attachComponent(textEl);

      this._textContent = textEl;
      this.markRedraw();
    };

    Element.prototype.setTextConfig = function (cfg) {
      if (!this.textConfig) {
        this.textConfig = {};
      }

      extend(this.textConfig, cfg);
      this.markRedraw();
    };

    Element.prototype.removeTextContent = function () {
      var textEl = this._textContent;

      if (textEl) {
        textEl.attachedTransform = null;

        this._detachComponent(textEl);

        this._textContent = null;
        this._innerTextDefaultStyle = null;
        this.markRedraw();
      }
    };

    Element.prototype.getTextGuideLine = function () {
      return this._textGuide;
    };

    Element.prototype.setTextGuideLine = function (guideLine) {
      if (this._textGuide && this._textGuide !== guideLine) {
        this.removeTextGuideLine();
      }

      this._attachComponent(guideLine);

      this._textGuide = guideLine;
      this.markRedraw();
    };

    Element.prototype.removeTextGuideLine = function () {
      var textGuide = this._textGuide;

      if (textGuide) {
        this._detachComponent(textGuide);

        this._textGuide = null;
        this.markRedraw();
      }
    };

    Element.prototype.markRedraw = function () {
      this.__dirty |= Element.REDARAW_BIT;
      var zr = this.__zr;

      if (zr) {
        if (this.__inHover) {
          zr.refreshHover();
        } else {
          zr.refresh();
        }
      }

      if (this.__hostTarget) {
        this.__hostTarget.markRedraw();
      }
    };

    Element.prototype.dirty = function () {
      this.markRedraw();
    };

    Element.prototype._toggleHoverLayerFlag = function (inHover) {
      this.__inHover = inHover;
      var textContent = this._textContent;
      var textGuide = this._textGuide;

      if (textContent) {
        textContent.__inHover = inHover;
      }

      if (textGuide) {
        textGuide.__inHover = inHover;
      }
    };

    Element.prototype.addSelfToZr = function (zr) {
      this.__zr = zr;
      var animators = this.animators;

      if (animators) {
        for (var i = 0; i < animators.length; i++) {
          zr.animation.addAnimator(animators[i]);
        }
      }

      if (this._clipPath) {
        this._clipPath.addSelfToZr(zr);
      }

      if (this._textContent) {
        this._textContent.addSelfToZr(zr);
      }

      if (this._textGuide) {
        this._textGuide.addSelfToZr(zr);
      }
    };

    Element.prototype.removeSelfFromZr = function (zr) {
      this.__zr = null;
      var animators = this.animators;

      if (animators) {
        for (var i = 0; i < animators.length; i++) {
          zr.animation.removeAnimator(animators[i]);
        }
      }

      if (this._clipPath) {
        this._clipPath.removeSelfFromZr(zr);
      }

      if (this._textContent) {
        this._textContent.removeSelfFromZr(zr);
      }

      if (this._textGuide) {
        this._textGuide.removeSelfFromZr(zr);
      }
    };

    Element.prototype.animate = function (key, loop) {
      var target = key ? this[key] : this;

      if (!target) {
        logError('Property "' + key + '" is not existed in element ' + this.id);
        return;
      }

      var animator = new Animator(target, loop);
      this.addAnimator(animator, key);
      return animator;
    };

    Element.prototype.addAnimator = function (animator, key) {
      var zr = this.__zr;
      var el = this;
      animator.during(function () {
        el.updateDuringAnimation(key);
      }).done(function () {
        var animators = el.animators;
        var idx = indexOf(animators, animator);

        if (idx >= 0) {
          animators.splice(idx, 1);
        }
      });
      this.animators.push(animator);

      if (zr) {
        zr.animation.addAnimator(animator);
      }

      zr && zr.wakeUp();
    };

    Element.prototype.updateDuringAnimation = function (key) {
      this.markRedraw();
    };

    Element.prototype.stopAnimation = function (scope, forwardToLast) {
      var animators = this.animators;
      var len = animators.length;
      var leftAnimators = [];

      for (var i = 0; i < len; i++) {
        var animator = animators[i];

        if (!scope || scope === animator.scope) {
          animator.stop(forwardToLast);
        } else {
          leftAnimators.push(animator);
        }
      }

      this.animators = leftAnimators;
      return this;
    };

    Element.prototype.animateTo = function (target, cfg, animationProps) {
      animateTo(this, target, cfg, animationProps);
    };

    Element.prototype.animateFrom = function (target, cfg, animationProps) {
      animateTo(this, target, cfg, animationProps, true);
    };

    Element.prototype._transitionState = function (stateName, target, cfg, animationProps) {
      var animators = animateTo(this, target, cfg, animationProps);

      for (var i = 0; i < animators.length; i++) {
        animators[i].__fromStateTransition = stateName;
      }
    };

    Element.prototype.getBoundingRect = function () {
      return null;
    };

    Element.prototype.getPaintRect = function () {
      return null;
    };

    Element.REDARAW_BIT = 1;

    Element.initDefaultProps = function () {
      var elProto = Element.prototype;
      elProto.type = 'element';
      elProto.name = '';
      elProto.ignore = false;
      elProto.silent = false;
      elProto.isGroup = false;
      elProto.draggable = false;
      elProto.dragging = false;
      elProto.ignoreClip = false;
      elProto.__inHover = false;
      elProto.__dirty = Element.REDARAW_BIT;
      var logs = {};

      function logDeprecatedError(key, xKey, yKey) {
        if (!logs[key + xKey + yKey]) {
          console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead");
          logs[key + xKey + yKey] = true;
        }
      }

      function createLegacyProperty(key, privateKey, xKey, yKey) {
        Object.defineProperty(elProto, key, {
          get: function () {
            logDeprecatedError(key, xKey, yKey);

            if (!this[privateKey]) {
              var pos = this[privateKey] = [];
              enhanceArray(this, pos);
            }

            return this[privateKey];
          },
          set: function (pos) {
            logDeprecatedError(key, xKey, yKey);
            this[xKey] = pos[0];
            this[yKey] = pos[1];
            this[privateKey] = pos;
            enhanceArray(this, pos);
          }
        });

        function enhanceArray(self, pos) {
          Object.defineProperty(pos, 0, {
            get: function () {
              return self[xKey];
            },
            set: function (val) {
              self[xKey] = val;
            }
          });
          Object.defineProperty(pos, 1, {
            get: function () {
              return self[yKey];
            },
            set: function (val) {
              self[yKey] = val;
            }
          });
        }
      }

      if (Object.defineProperty && (!env.browser.ie || env.browser.version > 8)) {
        createLegacyProperty('position', '_legacyPos', 'x', 'y');
        createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY');
        createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY');
      }
    }();

    return Element;
  }();

  mixin(Element, Eventful);
  mixin(Element, Transformable);

  function animateTo(animatable, target, cfg, animationProps, reverse) {
    cfg = cfg || {};
    var animators = [];
    animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse);
    var finishCount = animators.length;
    var doneHappened = false;
    var cfgDone = cfg.done;
    var cfgAborted = cfg.aborted;

    var doneCb = function () {
      doneHappened = true;
      finishCount--;

      if (finishCount <= 0) {
        doneHappened ? cfgDone && cfgDone() : cfgAborted && cfgAborted();
      }
    };

    var abortedCb = function () {
      finishCount--;

      if (finishCount <= 0) {
        doneHappened ? cfgDone && cfgDone() : cfgAborted && cfgAborted();
      }
    };

    if (!finishCount) {
      cfgDone && cfgDone();
    }

    if (animators.length > 0 && cfg.during) {
      animators[0].during(function (target, percent) {
        cfg.during(percent);
      });
    }

    for (var i = 0; i < animators.length; i++) {
      var animator = animators[i];

      if (doneCb) {
        animator.done(doneCb);
      }

      if (abortedCb) {
        animator.aborted(abortedCb);
      }

      animator.start(cfg.easing, cfg.force);
    }

    return animators;
  }

  function copyArrShallow(source, target, len) {
    for (var i = 0; i < len; i++) {
      source[i] = target[i];
    }
  }

  function is2DArray(value) {
    return isArrayLike(value[0]);
  }

  function copyValue(target, source, key) {
    if (isArrayLike(source[key])) {
      if (!isArrayLike(target[key])) {
        target[key] = [];
      }

      if (isTypedArray(source[key])) {
        var len = source[key].length;

        if (target[key].length !== len) {
          target[key] = new source[key].constructor(len);
          copyArrShallow(target[key], source[key], len);
        }
      } else {
        var sourceArr = source[key];
        var targetArr = target[key];
        var len0 = sourceArr.length;

        if (is2DArray(sourceArr)) {
          var len1 = sourceArr[0].length;

          for (var i = 0; i < len0; i++) {
            if (!targetArr[i]) {
              targetArr[i] = Array.prototype.slice.call(sourceArr[i]);
            } else {
              copyArrShallow(targetArr[i], sourceArr[i], len1);
            }
          }
        } else {
          copyArrShallow(targetArr, sourceArr, len0);
        }

        targetArr.length = sourceArr.length;
      }
    } else {
      target[key] = source[key];
    }
  }

  function animateToShallow(animatable, topKey, source, target, cfg, animationProps, animators, reverse) {
    var animatableKeys = [];
    var changedKeys = [];
    var targetKeys = keys(target);
    var duration = cfg.duration;
    var delay = cfg.delay;
    var additive = cfg.additive;
    var setToFinal = cfg.setToFinal;
    var animateAll = !isObject(animationProps);

    for (var k = 0; k < targetKeys.length; k++) {
      var innerKey = targetKeys[k];

      if (source[innerKey] != null && target[innerKey] != null && (animateAll || animationProps[innerKey])) {
        if (isObject(target[innerKey]) && !isArrayLike(target[innerKey])) {
          if (topKey) {
            if (!reverse) {
              source[innerKey] = target[innerKey];
              animatable.updateDuringAnimation(topKey);
            }

            continue;
          }

          animateToShallow(animatable, innerKey, source[innerKey], target[innerKey], cfg, animationProps && animationProps[innerKey], animators, reverse);
        } else {
          animatableKeys.push(innerKey);
          changedKeys.push(innerKey);
        }
      } else if (!reverse) {
        source[innerKey] = target[innerKey];
        animatable.updateDuringAnimation(topKey);
        changedKeys.push(innerKey);
      }
    }

    var keyLen = animatableKeys.length;

    if (keyLen > 0 || cfg.force && !animators.length) {
      var existsAnimators = animatable.animators;
      var existsAnimatorsOnSameTarget = [];

      for (var i = 0; i < existsAnimators.length; i++) {
        if (existsAnimators[i].targetName === topKey) {
          existsAnimatorsOnSameTarget.push(existsAnimators[i]);
        }
      }

      if (!additive && existsAnimatorsOnSameTarget.length) {
        for (var i = 0; i < existsAnimatorsOnSameTarget.length; i++) {
          var allAborted = existsAnimatorsOnSameTarget[i].stopTracks(changedKeys);

          if (allAborted) {
            var idx = indexOf(existsAnimators, existsAnimatorsOnSameTarget[i]);
            existsAnimators.splice(idx, 1);
          }
        }
      }

      var revertedSource = void 0;
      var reversedTarget = void 0;
      var sourceClone = void 0;

      if (reverse) {
        reversedTarget = {};

        if (setToFinal) {
          revertedSource = {};
        }

        for (var i = 0; i < keyLen; i++) {
          var innerKey = animatableKeys[i];
          reversedTarget[innerKey] = source[innerKey];

          if (setToFinal) {
            revertedSource[innerKey] = target[innerKey];
          } else {
            source[innerKey] = target[innerKey];
          }
        }
      } else if (setToFinal) {
        sourceClone = {};

        for (var i = 0; i < keyLen; i++) {
          var innerKey = animatableKeys[i];
          sourceClone[innerKey] = cloneValue(source[innerKey]);
          copyValue(source, target, innerKey);
        }
      }

      var animator = new Animator(source, false, additive ? existsAnimatorsOnSameTarget : null);
      animator.targetName = topKey;

      if (cfg.scope) {
        animator.scope = cfg.scope;
      }

      if (setToFinal && revertedSource) {
        animator.whenWithKeys(0, revertedSource, animatableKeys);
      }

      if (sourceClone) {
        animator.whenWithKeys(0, sourceClone, animatableKeys);
      }

      animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animatableKeys).delay(delay || 0);
      animatable.addAnimator(animator, topKey);
      animators.push(animator);
    }
  }

  var DEFAULT_MIN_MERGE = 32;
  var DEFAULT_MIN_GALLOPING = 7;

  function minRunLength(n) {
    var r = 0;

    while (n >= DEFAULT_MIN_MERGE) {
      r |= n & 1;
      n >>= 1;
    }

    return n + r;
  }

  function makeAscendingRun(array, lo, hi, compare) {
    var runHi = lo + 1;

    if (runHi === hi) {
      return 1;
    }

    if (compare(array[runHi++], array[lo]) < 0) {
      while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
        runHi++;
      }

      reverseRun(array, lo, runHi);
    } else {
      while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
        runHi++;
      }
    }

    return runHi - lo;
  }

  function reverseRun(array, lo, hi) {
    hi--;

    while (lo < hi) {
      var t = array[lo];
      array[lo++] = array[hi];
      array[hi--] = t;
    }
  }

  function binaryInsertionSort(array, lo, hi, start, compare) {
    if (start === lo) {
      start++;
    }

    for (; start < hi; start++) {
      var pivot = array[start];
      var left = lo;
      var right = start;
      var mid;

      while (left < right) {
        mid = left + right >>> 1;

        if (compare(pivot, array[mid]) < 0) {
          right = mid;
        } else {
          left = mid + 1;
        }
      }

      var n = start - left;

      switch (n) {
        case 3:
          array[left + 3] = array[left + 2];

        case 2:
          array[left + 2] = array[left + 1];

        case 1:
          array[left + 1] = array[left];
          break;

        default:
          while (n > 0) {
            array[left + n] = array[left + n - 1];
            n--;
          }

      }

      array[left] = pivot;
    }
  }

  function gallopLeft(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;

    if (compare(value, array[start + hint]) > 0) {
      maxOffset = length - hint;

      while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
        lastOffset = offset;
        offset = (offset << 1) + 1;

        if (offset <= 0) {
          offset = maxOffset;
        }
      }

      if (offset > maxOffset) {
        offset = maxOffset;
      }

      lastOffset += hint;
      offset += hint;
    } else {
      maxOffset = hint + 1;

      while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
        lastOffset = offset;
        offset = (offset << 1) + 1;

        if (offset <= 0) {
          offset = maxOffset;
        }
      }

      if (offset > maxOffset) {
        offset = maxOffset;
      }

      var tmp = lastOffset;
      lastOffset = hint - offset;
      offset = hint - tmp;
    }

    lastOffset++;

    while (lastOffset < offset) {
      var m = lastOffset + (offset - lastOffset >>> 1);

      if (compare(value, array[start + m]) > 0) {
        lastOffset = m + 1;
      } else {
        offset = m;
      }
    }

    return offset;
  }

  function gallopRight(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;

    if (compare(value, array[start + hint]) < 0) {
      maxOffset = hint + 1;

      while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
        lastOffset = offset;
        offset = (offset << 1) + 1;

        if (offset <= 0) {
          offset = maxOffset;
        }
      }

      if (offset > maxOffset) {
        offset = maxOffset;
      }

      var tmp = lastOffset;
      lastOffset = hint - offset;
      offset = hint - tmp;
    } else {
      maxOffset = length - hint;

      while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
        lastOffset = offset;
        offset = (offset << 1) + 1;

        if (offset <= 0) {
          offset = maxOffset;
        }
      }

      if (offset > maxOffset) {
        offset = maxOffset;
      }

      lastOffset += hint;
      offset += hint;
    }

    lastOffset++;

    while (lastOffset < offset) {
      var m = lastOffset + (offset - lastOffset >>> 1);

      if (compare(value, array[start + m]) < 0) {
        offset = m;
      } else {
        lastOffset = m + 1;
      }
    }

    return offset;
  }

  function TimSort(array, compare) {
    var minGallop = DEFAULT_MIN_GALLOPING;
    var length = 0;
    var runStart;
    var runLength;
    var stackSize = 0;
    length = array.length;
    var tmp = [];
    runStart = [];
    runLength = [];

    function pushRun(_runStart, _runLength) {
      runStart[stackSize] = _runStart;
      runLength[stackSize] = _runLength;
      stackSize += 1;
    }

    function mergeRuns() {
      while (stackSize > 1) {
        var n = stackSize - 2;

        if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) {
          if (runLength[n - 1] < runLength[n + 1]) {
            n--;
          }
        } else if (runLength[n] > runLength[n + 1]) {
          break;
        }

        mergeAt(n);
      }
    }

    function forceMergeRuns() {
      while (stackSize > 1) {
        var n = stackSize - 2;

        if (n > 0 && runLength[n - 1] < runLength[n + 1]) {
          n--;
        }

        mergeAt(n);
      }
    }

    function mergeAt(i) {
      var start1 = runStart[i];
      var length1 = runLength[i];
      var start2 = runStart[i + 1];
      var length2 = runLength[i + 1];
      runLength[i] = length1 + length2;

      if (i === stackSize - 3) {
        runStart[i + 1] = runStart[i + 2];
        runLength[i + 1] = runLength[i + 2];
      }

      stackSize--;
      var k = gallopRight(array[start2], array, start1, length1, 0, compare);
      start1 += k;
      length1 -= k;

      if (length1 === 0) {
        return;
      }

      length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);

      if (length2 === 0) {
        return;
      }

      if (length1 <= length2) {
        mergeLow(start1, length1, start2, length2);
      } else {
        mergeHigh(start1, length1, start2, length2);
      }
    }

    function mergeLow(start1, length1, start2, length2) {
      var i = 0;

      for (i = 0; i < length1; i++) {
        tmp[i] = array[start1 + i];
      }

      var cursor1 = 0;
      var cursor2 = start2;
      var dest = start1;
      array[dest++] = array[cursor2++];

      if (--length2 === 0) {
        for (i = 0; i < length1; i++) {
          array[dest + i] = tmp[cursor1 + i];
        }

        return;
      }

      if (length1 === 1) {
        for (i = 0; i < length2; i++) {
          array[dest + i] = array[cursor2 + i];
        }

        array[dest + length2] = tmp[cursor1];
        return;
      }

      var _minGallop = minGallop;
      var count1;
      var count2;
      var exit;

      while (1) {
        count1 = 0;
        count2 = 0;
        exit = false;

        do {
          if (compare(array[cursor2], tmp[cursor1]) < 0) {
            array[dest++] = array[cursor2++];
            count2++;
            count1 = 0;

            if (--length2 === 0) {
              exit = true;
              break;
            }
          } else {
            array[dest++] = tmp[cursor1++];
            count1++;
            count2 = 0;

            if (--length1 === 1) {
              exit = true;
              break;
            }
          }
        } while ((count1 | count2) < _minGallop);

        if (exit) {
          break;
        }

        do {
          count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);

          if (count1 !== 0) {
            for (i = 0; i < count1; i++) {
              array[dest + i] = tmp[cursor1 + i];
            }

            dest += count1;
            cursor1 += count1;
            length1 -= count1;

            if (length1 <= 1) {
              exit = true;
              break;
            }
          }

          array[dest++] = array[cursor2++];

          if (--length2 === 0) {
            exit = true;
            break;
          }

          count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);

          if (count2 !== 0) {
            for (i = 0; i < count2; i++) {
              array[dest + i] = array[cursor2 + i];
            }

            dest += count2;
            cursor2 += count2;
            length2 -= count2;

            if (length2 === 0) {
              exit = true;
              break;
            }
          }

          array[dest++] = tmp[cursor1++];

          if (--length1 === 1) {
            exit = true;
            break;
          }

          _minGallop--;
        } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

        if (exit) {
          break;
        }

        if (_minGallop < 0) {
          _minGallop = 0;
        }

        _minGallop += 2;
      }

      minGallop = _minGallop;
      minGallop < 1 && (minGallop = 1);

      if (length1 === 1) {
        for (i = 0; i < length2; i++) {
          array[dest + i] = array[cursor2 + i];
        }

        array[dest + length2] = tmp[cursor1];
      } else if (length1 === 0) {
        throw new Error();
      } else {
        for (i = 0; i < length1; i++) {
          array[dest + i] = tmp[cursor1 + i];
        }
      }
    }

    function mergeHigh(start1, length1, start2, length2) {
      var i = 0;

      for (i = 0; i < length2; i++) {
        tmp[i] = array[start2 + i];
      }

      var cursor1 = start1 + length1 - 1;
      var cursor2 = length2 - 1;
      var dest = start2 + length2 - 1;
      var customCursor = 0;
      var customDest = 0;
      array[dest--] = array[cursor1--];

      if (--length1 === 0) {
        customCursor = dest - (length2 - 1);

        for (i = 0; i < length2; i++) {
          array[customCursor + i] = tmp[i];
        }

        return;
      }

      if (length2 === 1) {
        dest -= length1;
        cursor1 -= length1;
        customDest = dest + 1;
        customCursor = cursor1 + 1;

        for (i = length1 - 1; i >= 0; i--) {
          array[customDest + i] = array[customCursor + i];
        }

        array[dest] = tmp[cursor2];
        return;
      }

      var _minGallop = minGallop;

      while (true) {
        var count1 = 0;
        var count2 = 0;
        var exit = false;

        do {
          if (compare(tmp[cursor2], array[cursor1]) < 0) {
            array[dest--] = array[cursor1--];
            count1++;
            count2 = 0;

            if (--length1 === 0) {
              exit = true;
              break;
            }
          } else {
            array[dest--] = tmp[cursor2--];
            count2++;
            count1 = 0;

            if (--length2 === 1) {
              exit = true;
              break;
            }
          }
        } while ((count1 | count2) < _minGallop);

        if (exit) {
          break;
        }

        do {
          count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);

          if (count1 !== 0) {
            dest -= count1;
            cursor1 -= count1;
            length1 -= count1;
            customDest = dest + 1;
            customCursor = cursor1 + 1;

            for (i = count1 - 1; i >= 0; i--) {
              array[customDest + i] = array[customCursor + i];
            }

            if (length1 === 0) {
              exit = true;
              break;
            }
          }

          array[dest--] = tmp[cursor2--];

          if (--length2 === 1) {
            exit = true;
            break;
          }

          count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);

          if (count2 !== 0) {
            dest -= count2;
            cursor2 -= count2;
            length2 -= count2;
            customDest = dest + 1;
            customCursor = cursor2 + 1;

            for (i = 0; i < count2; i++) {
              array[customDest + i] = tmp[customCursor + i];
            }

            if (length2 <= 1) {
              exit = true;
              break;
            }
          }

          array[dest--] = array[cursor1--];

          if (--length1 === 0) {
            exit = true;
            break;
          }

          _minGallop--;
        } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

        if (exit) {
          break;
        }

        if (_minGallop < 0) {
          _minGallop = 0;
        }

        _minGallop += 2;
      }

      minGallop = _minGallop;

      if (minGallop < 1) {
        minGallop = 1;
      }

      if (length2 === 1) {
        dest -= length1;
        cursor1 -= length1;
        customDest = dest + 1;
        customCursor = cursor1 + 1;

        for (i = length1 - 1; i >= 0; i--) {
          array[customDest + i] = array[customCursor + i];
        }

        array[dest] = tmp[cursor2];
      } else if (length2 === 0) {
        throw new Error();
      } else {
        customCursor = dest - (length2 - 1);

        for (i = 0; i < length2; i++) {
          array[customCursor + i] = tmp[i];
        }
      }
    }

    return {
      mergeRuns: mergeRuns,
      forceMergeRuns: forceMergeRuns,
      pushRun: pushRun
    };
  }

  function sort(array, compare, lo, hi) {
    if (!lo) {
      lo = 0;
    }

    if (!hi) {
      hi = array.length;
    }

    var remaining = hi - lo;

    if (remaining < 2) {
      return;
    }

    var runLength = 0;

    if (remaining < DEFAULT_MIN_MERGE) {
      runLength = makeAscendingRun(array, lo, hi, compare);
      binaryInsertionSort(array, lo, hi, lo + runLength, compare);
      return;
    }

    var ts = TimSort(array, compare);
    var minRun = minRunLength(remaining);

    do {
      runLength = makeAscendingRun(array, lo, hi, compare);

      if (runLength < minRun) {
        var force = remaining;

        if (force > minRun) {
          force = minRun;
        }

        binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
        runLength = force;
      }

      ts.pushRun(lo, runLength);
      ts.mergeRuns();
      remaining -= runLength;
      lo += runLength;
    } while (remaining !== 0);

    ts.forceMergeRuns();
  }

  var invalidZErrorLogged = false;

  function logInvalidZError() {
    if (invalidZErrorLogged) {
      return;
    }

    invalidZErrorLogged = true;
    console.warn('z / z2 / zlevel of displayable is invalid, which may cause unexpected errors');
  }

  function shapeCompareFunc(a, b) {
    if (a.zlevel === b.zlevel) {
      if (a.z === b.z) {
        return a.z2 - b.z2;
      }

      return a.z - b.z;
    }

    return a.zlevel - b.zlevel;
  }

  var Storage = function () {
    function Storage() {
      this._roots = [];
      this._displayList = [];
      this._displayListLen = 0;
      this.displayableSortFunc = shapeCompareFunc;
    }

    Storage.prototype.traverse = function (cb, context) {
      for (var i = 0; i < this._roots.length; i++) {
        this._roots[i].traverse(cb, context);
      }
    };

    Storage.prototype.getDisplayList = function (update, includeIgnore) {
      includeIgnore = includeIgnore || false;
      var displayList = this._displayList;

      if (update || !displayList.length) {
        this.updateDisplayList(includeIgnore);
      }

      return displayList;
    };

    Storage.prototype.updateDisplayList = function (includeIgnore) {
      this._displayListLen = 0;
      var roots = this._roots;
      var displayList = this._displayList;

      for (var i = 0, len = roots.length; i < len; i++) {
        this._updateAndAddDisplayable(roots[i], null, includeIgnore);
      }

      displayList.length = this._displayListLen;
      env.canvasSupported && sort(displayList, shapeCompareFunc);
    };

    Storage.prototype._updateAndAddDisplayable = function (el, clipPaths, includeIgnore) {
      if (el.ignore && !includeIgnore) {
        return;
      }

      el.beforeUpdate();
      el.update();
      el.afterUpdate();
      var userSetClipPath = el.getClipPath();

      if (el.ignoreClip) {
        clipPaths = null;
      } else if (userSetClipPath) {
        if (clipPaths) {
          clipPaths = clipPaths.slice();
        } else {
          clipPaths = [];
        }

        var currentClipPath = userSetClipPath;
        var parentClipPath = el;

        while (currentClipPath) {
          currentClipPath.parent = parentClipPath;
          currentClipPath.updateTransform();
          clipPaths.push(currentClipPath);
          parentClipPath = currentClipPath;
          currentClipPath = currentClipPath.getClipPath();
        }
      }

      if (el.childrenRef) {
        var children = el.childrenRef();

        for (var i = 0; i < children.length; i++) {
          var child = children[i];

          if (el.__dirty) {
            child.__dirty |= Element.REDARAW_BIT;
          }

          this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
        }

        el.__dirty = 0;
      } else {
        var disp = el;

        if (clipPaths && clipPaths.length) {
          disp.__clipPaths = clipPaths;
        } else if (disp.__clipPaths && disp.__clipPaths.length > 0) {
          disp.__clipPaths = [];
        }

        if (isNaN(disp.z)) {
          logInvalidZError();
          disp.z = 0;
        }

        if (isNaN(disp.z2)) {
          logInvalidZError();
          disp.z2 = 0;
        }

        if (isNaN(disp.zlevel)) {
          logInvalidZError();
          disp.zlevel = 0;
        }

        this._displayList[this._displayListLen++] = disp;
      }

      var decalEl = el.getDecalElement && el.getDecalElement();

      if (decalEl) {
        this._updateAndAddDisplayable(decalEl, clipPaths, includeIgnore);
      }

      var textGuide = el.getTextGuideLine();

      if (textGuide) {
        this._updateAndAddDisplayable(textGuide, clipPaths, includeIgnore);
      }

      var textEl = el.getTextContent();

      if (textEl) {
        this._updateAndAddDisplayable(textEl, clipPaths, includeIgnore);
      }
    };

    Storage.prototype.addRoot = function (el) {
      if (el.__zr && el.__zr.storage === this) {
        return;
      }

      this._roots.push(el);
    };

    Storage.prototype.delRoot = function (el) {
      if (el instanceof Array) {
        for (var i = 0, l = el.length; i < l; i++) {
          this.delRoot(el[i]);
        }

        return;
      }

      var idx = indexOf(this._roots, el);

      if (idx >= 0) {
        this._roots.splice(idx, 1);
      }
    };

    Storage.prototype.delAllRoots = function () {
      this._roots = [];
      this._displayList = [];
      this._displayListLen = 0;
      return;
    };

    Storage.prototype.getRoots = function () {
      return this._roots;
    };

    Storage.prototype.dispose = function () {
      this._displayList = null;
      this._roots = null;
    };

    return Storage;
  }();

  var requestAnimationFrame;

  requestAnimationFrame = typeof window !== 'undefined' && (window.requestAnimationFrame && window.requestAnimationFrame.bind(window) || window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window) || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame) || function (func) {
    return setTimeout(func, 16);
  };

  var requestAnimationFrame$1 = requestAnimationFrame;

  var Animation = function (_super) {
    __extends(Animation, _super);

    function Animation(opts) {
      var _this = _super.call(this) || this;

      _this._running = false;
      _this._time = 0;
      _this._pausedTime = 0;
      _this._pauseStart = 0;
      _this._paused = false;
      opts = opts || {};
      _this.stage = opts.stage || {};

      _this.onframe = opts.onframe || function () {};

      return _this;
    }

    Animation.prototype.addClip = function (clip) {
      if (clip.animation) {
        this.removeClip(clip);
      }

      if (!this._clipsHead) {
        this._clipsHead = this._clipsTail = clip;
      } else {
        this._clipsTail.next = clip;
        clip.prev = this._clipsTail;
        clip.next = null;
        this._clipsTail = clip;
      }

      clip.animation = this;
    };

    Animation.prototype.addAnimator = function (animator) {
      animator.animation = this;
      var clip = animator.getClip();

      if (clip) {
        this.addClip(clip);
      }
    };

    Animation.prototype.removeClip = function (clip) {
      if (!clip.animation) {
        return;
      }

      var prev = clip.prev;
      var next = clip.next;

      if (prev) {
        prev.next = next;
      } else {
        this._clipsHead = next;
      }

      if (next) {
        next.prev = prev;
      } else {
        this._clipsTail = prev;
      }

      clip.next = clip.prev = clip.animation = null;
    };

    Animation.prototype.removeAnimator = function (animator) {
      var clip = animator.getClip();

      if (clip) {
        this.removeClip(clip);
      }

      animator.animation = null;
    };

    Animation.prototype.update = function (notTriggerFrameAndStageUpdate) {
      var time = new Date().getTime() - this._pausedTime;

      var delta = time - this._time;
      var clip = this._clipsHead;

      while (clip) {
        var nextClip = clip.next;
        var finished = clip.step(time, delta);

        if (finished) {
          clip.ondestroy && clip.ondestroy();
          this.removeClip(clip);
          clip = nextClip;
        } else {
          clip = nextClip;
        }
      }

      this._time = time;

      if (!notTriggerFrameAndStageUpdate) {
        this.onframe(delta);
        this.trigger('frame', delta);
        this.stage.update && this.stage.update();
      }
    };

    Animation.prototype._startLoop = function () {
      var self = this;
      this._running = true;

      function step() {
        if (self._running) {
          requestAnimationFrame$1(step);
          !self._paused && self.update();
        }
      }

      requestAnimationFrame$1(step);
    };

    Animation.prototype.start = function () {
      if (this._running) {
        return;
      }

      this._time = new Date().getTime();
      this._pausedTime = 0;

      this._startLoop();
    };

    Animation.prototype.stop = function () {
      this._running = false;
    };

    Animation.prototype.pause = function () {
      if (!this._paused) {
        this._pauseStart = new Date().getTime();
        this._paused = true;
      }
    };

    Animation.prototype.resume = function () {
      if (this._paused) {
        this._pausedTime += new Date().getTime() - this._pauseStart;
        this._paused = false;
      }
    };

    Animation.prototype.clear = function () {
      var clip = this._clipsHead;

      while (clip) {
        var nextClip = clip.next;
        clip.prev = clip.next = clip.animation = null;
        clip = nextClip;
      }

      this._clipsHead = this._clipsTail = null;
    };

    Animation.prototype.isFinished = function () {
      return this._clipsHead == null;
    };

    Animation.prototype.animate = function (target, options) {
      options = options || {};
      this.start();
      var animator = new Animator(target, options.loop);
      this.addAnimator(animator);
      return animator;
    };

    return Animation;
  }(Eventful);

  var TOUCH_CLICK_DELAY = 300;
  var globalEventSupported = env.domSupported;

  var localNativeListenerNames = function () {
    var mouseHandlerNames = ['click', 'dblclick', 'mousewheel', 'wheel', 'mouseout', 'mouseup', 'mousedown', 'mousemove', 'contextmenu'];
    var touchHandlerNames = ['touchstart', 'touchend', 'touchmove'];
    var pointerEventNameMap = {
      pointerdown: 1,
      pointerup: 1,
      pointermove: 1,
      pointerout: 1
    };
    var pointerHandlerNames = map(mouseHandlerNames, function (name) {
      var nm = name.replace('mouse', 'pointer');
      return pointerEventNameMap.hasOwnProperty(nm) ? nm : name;
    });
    return {
      mouse: mouseHandlerNames,
      touch: touchHandlerNames,
      pointer: pointerHandlerNames
    };
  }();

  var globalNativeListenerNames = {
    mouse: ['mousemove', 'mouseup'],
    pointer: ['pointermove', 'pointerup']
  };
  var wheelEventSupported = false;

  function isPointerFromTouch(event) {
    var pointerType = event.pointerType;
    return pointerType === 'pen' || pointerType === 'touch';
  }

  function setTouchTimer(scope) {
    scope.touching = true;

    if (scope.touchTimer != null) {
      clearTimeout(scope.touchTimer);
      scope.touchTimer = null;
    }

    scope.touchTimer = setTimeout(function () {
      scope.touching = false;
      scope.touchTimer = null;
    }, 700);
  }

  function markTouch(event) {
    event && (event.zrByTouch = true);
  }

  function normalizeGlobalEvent(instance, event) {
    return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true);
  }

  function isLocalEl(instance, el) {
    var elTmp = el;
    var isLocal = false;

    while (elTmp && elTmp.nodeType !== 9 && !(isLocal = elTmp.domBelongToZr || elTmp !== el && elTmp === instance.painterRoot)) {
      elTmp = elTmp.parentNode;
    }

    return isLocal;
  }

  var FakeGlobalEvent = function () {
    function FakeGlobalEvent(instance, event) {
      this.stopPropagation = noop;
      this.stopImmediatePropagation = noop;
      this.preventDefault = noop;
      this.type = event.type;
      this.target = this.currentTarget = instance.dom;
      this.pointerType = event.pointerType;
      this.clientX = event.clientX;
      this.clientY = event.clientY;
    }

    return FakeGlobalEvent;
  }();

  var localDOMHandlers = {
    mousedown: function (event) {
      event = normalizeEvent(this.dom, event);
      this.__mayPointerCapture = [event.zrX, event.zrY];
      this.trigger('mousedown', event);
    },
    mousemove: function (event) {
      event = normalizeEvent(this.dom, event);
      var downPoint = this.__mayPointerCapture;

      if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) {
        this.__togglePointerCapture(true);
      }

      this.trigger('mousemove', event);
    },
    mouseup: function (event) {
      event = normalizeEvent(this.dom, event);

      this.__togglePointerCapture(false);

      this.trigger('mouseup', event);
    },
    mouseout: function (event) {
      if (event.target !== this.dom) {
        return;
      }

      event = normalizeEvent(this.dom, event);

      if (this.__pointerCapturing) {
        event.zrEventControl = 'no_globalout';
      }

      var element = event.toElement || event.relatedTarget;
      event.zrIsToLocalDOM = isLocalEl(this, element);
      this.trigger('mouseout', event);
    },
    wheel: function (event) {
      wheelEventSupported = true;
      event = normalizeEvent(this.dom, event);
      this.trigger('mousewheel', event);
    },
    mousewheel: function (event) {
      if (wheelEventSupported) {
        return;
      }

      event = normalizeEvent(this.dom, event);
      this.trigger('mousewheel', event);
    },
    touchstart: function (event) {
      event = normalizeEvent(this.dom, event);
      markTouch(event);
      this.__lastTouchMoment = new Date();
      this.handler.processGesture(event, 'start');
      localDOMHandlers.mousemove.call(this, event);
      localDOMHandlers.mousedown.call(this, event);
    },
    touchmove: function (event) {
      event = normalizeEvent(this.dom, event);
      markTouch(event);
      this.handler.processGesture(event, 'change');
      localDOMHandlers.mousemove.call(this, event);
    },
    touchend: function (event) {
      event = normalizeEvent(this.dom, event);
      markTouch(event);
      this.handler.processGesture(event, 'end');
      localDOMHandlers.mouseup.call(this, event);

      if (+new Date() - +this.__lastTouchMoment < TOUCH_CLICK_DELAY) {
        localDOMHandlers.click.call(this, event);
      }
    },
    pointerdown: function (event) {
      localDOMHandlers.mousedown.call(this, event);
    },
    pointermove: function (event) {
      if (!isPointerFromTouch(event)) {
        localDOMHandlers.mousemove.call(this, event);
      }
    },
    pointerup: function (event) {
      localDOMHandlers.mouseup.call(this, event);
    },
    pointerout: function (event) {
      if (!isPointerFromTouch(event)) {
        localDOMHandlers.mouseout.call(this, event);
      }
    }
  };
  each(['click', 'dblclick', 'contextmenu'], function (name) {
    localDOMHandlers[name] = function (event) {
      event = normalizeEvent(this.dom, event);
      this.trigger(name, event);
    };
  });
  var globalDOMHandlers = {
    pointermove: function (event) {
      if (!isPointerFromTouch(event)) {
        globalDOMHandlers.mousemove.call(this, event);
      }
    },
    pointerup: function (event) {
      globalDOMHandlers.mouseup.call(this, event);
    },
    mousemove: function (event) {
      this.trigger('mousemove', event);
    },
    mouseup: function (event) {
      var pointerCaptureReleasing = this.__pointerCapturing;

      this.__togglePointerCapture(false);

      this.trigger('mouseup', event);

      if (pointerCaptureReleasing) {
        event.zrEventControl = 'only_globalout';
        this.trigger('mouseout', event);
      }
    }
  };

  function mountLocalDOMEventListeners(instance, scope) {
    var domHandlers = scope.domHandlers;

    if (env.pointerEventsSupported) {
      each(localNativeListenerNames.pointer, function (nativeEventName) {
        mountSingleDOMEventListener(scope, nativeEventName, function (event) {
          domHandlers[nativeEventName].call(instance, event);
        });
      });
    } else {
      if (env.touchEventsSupported) {
        each(localNativeListenerNames.touch, function (nativeEventName) {
          mountSingleDOMEventListener(scope, nativeEventName, function (event) {
            domHandlers[nativeEventName].call(instance, event);
            setTouchTimer(scope);
          });
        });
      }

      each(localNativeListenerNames.mouse, function (nativeEventName) {
        mountSingleDOMEventListener(scope, nativeEventName, function (event) {
          event = getNativeEvent(event);

          if (!scope.touching) {
            domHandlers[nativeEventName].call(instance, event);
          }
        });
      });
    }
  }

  function mountGlobalDOMEventListeners(instance, scope) {
    if (env.pointerEventsSupported) {
      each(globalNativeListenerNames.pointer, mount);
    } else if (!env.touchEventsSupported) {
      each(globalNativeListenerNames.mouse, mount);
    }

    function mount(nativeEventName) {
      function nativeEventListener(event) {
        event = getNativeEvent(event);

        if (!isLocalEl(instance, event.target)) {
          event = normalizeGlobalEvent(instance, event);
          scope.domHandlers[nativeEventName].call(instance, event);
        }
      }

      mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, {
        capture: true
      });
    }
  }

  function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) {
    scope.mounted[nativeEventName] = listener;
    scope.listenerOpts[nativeEventName] = opt;
    addEventListener(scope.domTarget, nativeEventName, listener, opt);
  }

  function unmountDOMEventListeners(scope) {
    var mounted = scope.mounted;

    for (var nativeEventName in mounted) {
      if (mounted.hasOwnProperty(nativeEventName)) {
        removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]);
      }
    }

    scope.mounted = {};
  }

  var DOMHandlerScope = function () {
    function DOMHandlerScope(domTarget, domHandlers) {
      this.mounted = {};
      this.listenerOpts = {};
      this.touching = false;
      this.domTarget = domTarget;
      this.domHandlers = domHandlers;
    }

    return DOMHandlerScope;
  }();

  var HandlerDomProxy = function (_super) {
    __extends(HandlerDomProxy, _super);

    function HandlerDomProxy(dom, painterRoot) {
      var _this = _super.call(this) || this;

      _this.__pointerCapturing = false;
      _this.dom = dom;
      _this.painterRoot = painterRoot;
      _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers);

      if (globalEventSupported) {
        _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers);
      }

      mountLocalDOMEventListeners(_this, _this._localHandlerScope);
      return _this;
    }

    HandlerDomProxy.prototype.dispose = function () {
      unmountDOMEventListeners(this._localHandlerScope);

      if (globalEventSupported) {
        unmountDOMEventListeners(this._globalHandlerScope);
      }
    };

    HandlerDomProxy.prototype.setCursor = function (cursorStyle) {
      this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
    };

    HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) {
      this.__mayPointerCapture = null;

      if (globalEventSupported && +this.__pointerCapturing ^ +isPointerCapturing) {
        this.__pointerCapturing = isPointerCapturing;
        var globalHandlerScope = this._globalHandlerScope;
        isPointerCapturing ? mountGlobalDOMEventListeners(this, globalHandlerScope) : unmountDOMEventListeners(globalHandlerScope);
      }
    };

    return HandlerDomProxy;
  }(Eventful);

  var STYLE_MAGIC_KEY = '__zr_style_' + Math.round(Math.random() * 10);
  var DEFAULT_COMMON_STYLE = {
    shadowBlur: 0,
    shadowOffsetX: 0,
    shadowOffsetY: 0,
    shadowColor: '#000',
    opacity: 1,
    blend: 'source-over'
  };
  var DEFAULT_COMMON_ANIMATION_PROPS = {
    style: {
      shadowBlur: true,
      shadowOffsetX: true,
      shadowOffsetY: true,
      shadowColor: true,
      opacity: true
    }
  };
  DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true;
  var PRIMARY_STATES_KEYS$1 = ['z', 'z2', 'invisible'];

  var Displayable = function (_super) {
    __extends(Displayable, _super);

    function Displayable(props) {
      return _super.call(this, props) || this;
    }

    Displayable.prototype._init = function (props) {
      var keysArr = keys(props);

      for (var i = 0; i < keysArr.length; i++) {
        var key = keysArr[i];

        if (key === 'style') {
          this.useStyle(props[key]);
        } else {
          _super.prototype.attrKV.call(this, key, props[key]);
        }
      }

      if (!this.style) {
        this.useStyle({});
      }
    };

    Displayable.prototype.beforeBrush = function () {};

    Displayable.prototype.afterBrush = function () {};

    Displayable.prototype.innerBeforeBrush = function () {};

    Displayable.prototype.innerAfterBrush = function () {};

    Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) {
      var m = this.transform;

      if (this.ignore || this.invisible || this.style.opacity === 0 || this.culling && isDisplayableCulled(this, viewWidth, viewHeight) || m && !m[0] && !m[3]) {
        return false;
      }

      if (considerClipPath && this.__clipPaths) {
        for (var i = 0; i < this.__clipPaths.length; ++i) {
          if (this.__clipPaths[i].isZeroArea()) {
            return false;
          }
        }
      }

      if (considerAncestors && this.parent) {
        var parent_1 = this.parent;

        while (parent_1) {
          if (parent_1.ignore) {
            return false;
          }

          parent_1 = parent_1.parent;
        }
      }

      return true;
    };

    Displayable.prototype.contain = function (x, y) {
      return this.rectContain(x, y);
    };

    Displayable.prototype.traverse = function (cb, context) {
      cb.call(context, this);
    };

    Displayable.prototype.rectContain = function (x, y) {
      var coord = this.transformCoordToLocal(x, y);
      var rect = this.getBoundingRect();
      return rect.contain(coord[0], coord[1]);
    };

    Displayable.prototype.getPaintRect = function () {
      var rect = this._paintRect;

      if (!this._paintRect || this.__dirty) {
        var transform = this.transform;
        var elRect = this.getBoundingRect();
        var style = this.style;
        var shadowSize = style.shadowBlur || 0;
        var shadowOffsetX = style.shadowOffsetX || 0;
        var shadowOffsetY = style.shadowOffsetY || 0;
        rect = this._paintRect || (this._paintRect = new BoundingRect(0, 0, 0, 0));

        if (transform) {
          BoundingRect.applyTransform(rect, elRect, transform);
        } else {
          rect.copy(elRect);
        }

        if (shadowSize || shadowOffsetX || shadowOffsetY) {
          rect.width += shadowSize * 2 + Math.abs(shadowOffsetX);
          rect.height += shadowSize * 2 + Math.abs(shadowOffsetY);
          rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize);
          rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize);
        }

        var tolerance = this.dirtyRectTolerance;

        if (!rect.isZero()) {
          rect.x = Math.floor(rect.x - tolerance);
          rect.y = Math.floor(rect.y - tolerance);
          rect.width = Math.ceil(rect.width + 1 + tolerance * 2);
          rect.height = Math.ceil(rect.height + 1 + tolerance * 2);
        }
      }

      return rect;
    };

    Displayable.prototype.setPrevPaintRect = function (paintRect) {
      if (paintRect) {
        this._prevPaintRect = this._prevPaintRect || new BoundingRect(0, 0, 0, 0);

        this._prevPaintRect.copy(paintRect);
      } else {
        this._prevPaintRect = null;
      }
    };

    Displayable.prototype.getPrevPaintRect = function () {
      return this._prevPaintRect;
    };

    Displayable.prototype.animateStyle = function (loop) {
      return this.animate('style', loop);
    };

    Displayable.prototype.updateDuringAnimation = function (targetKey) {
      if (targetKey === 'style') {
        this.dirtyStyle();
      } else {
        this.markRedraw();
      }
    };

    Displayable.prototype.attrKV = function (key, value) {
      if (key !== 'style') {
        _super.prototype.attrKV.call(this, key, value);
      } else {
        if (!this.style) {
          this.useStyle(value);
        } else {
          this.setStyle(value);
        }
      }
    };

    Displayable.prototype.setStyle = function (keyOrObj, value) {
      if (typeof keyOrObj === 'string') {
        this.style[keyOrObj] = value;
      } else {
        extend(this.style, keyOrObj);
      }

      this.dirtyStyle();
      return this;
    };

    Displayable.prototype.dirtyStyle = function () {
      this.markRedraw();
      this.__dirty |= Displayable.STYLE_CHANGED_BIT;

      if (this._rect) {
        this._rect = null;
      }
    };

    Displayable.prototype.dirty = function () {
      this.dirtyStyle();
    };

    Displayable.prototype.styleChanged = function () {
      return !!(this.__dirty & Displayable.STYLE_CHANGED_BIT);
    };

    Displayable.prototype.styleUpdated = function () {
      this.__dirty &= ~Displayable.STYLE_CHANGED_BIT;
    };

    Displayable.prototype.createStyle = function (obj) {
      return createObject(DEFAULT_COMMON_STYLE, obj);
    };

    Displayable.prototype.useStyle = function (obj) {
      if (!obj[STYLE_MAGIC_KEY]) {
        obj = this.createStyle(obj);
      }

      if (this.__inHover) {
        this.__hoverStyle = obj;
      } else {
        this.style = obj;
      }

      this.dirtyStyle();
    };

    Displayable.prototype.isStyleObject = function (obj) {
      return obj[STYLE_MAGIC_KEY];
    };

    Displayable.prototype._innerSaveToNormal = function (toState) {
      _super.prototype._innerSaveToNormal.call(this, toState);

      var normalState = this._normalState;

      if (toState.style && !normalState.style) {
        normalState.style = this._mergeStyle(this.createStyle(), this.style);
      }

      this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS$1);
    };

    Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
      _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);

      var needsRestoreToNormal = !(state && keepCurrentStates);
      var targetStyle;

      if (state && state.style) {
        if (transition) {
          if (keepCurrentStates) {
            targetStyle = state.style;
          } else {
            targetStyle = this._mergeStyle(this.createStyle(), normalState.style);

            this._mergeStyle(targetStyle, state.style);
          }
        } else {
          targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style);

          this._mergeStyle(targetStyle, state.style);
        }
      } else if (needsRestoreToNormal) {
        targetStyle = normalState.style;
      }

      if (targetStyle) {
        if (transition) {
          var sourceStyle = this.style;
          this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle);

          if (needsRestoreToNormal) {
            var changedKeys = keys(sourceStyle);

            for (var i = 0; i < changedKeys.length; i++) {
              var key = changedKeys[i];

              if (key in targetStyle) {
                targetStyle[key] = targetStyle[key];
                this.style[key] = sourceStyle[key];
              }
            }
          }

          var targetKeys = keys(targetStyle);

          for (var i = 0; i < targetKeys.length; i++) {
            var key = targetKeys[i];
            this.style[key] = this.style[key];
          }

          this._transitionState(stateName, {
            style: targetStyle
          }, animationCfg, this.getAnimationStyleProps());
        } else {
          this.useStyle(targetStyle);
        }
      }

      for (var i = 0; i < PRIMARY_STATES_KEYS$1.length; i++) {
        var key = PRIMARY_STATES_KEYS$1[i];

        if (state && state[key] != null) {
          this[key] = state[key];
        } else if (needsRestoreToNormal) {
          if (normalState[key] != null) {
            this[key] = normalState[key];
          }
        }
      }
    };

    Displayable.prototype._mergeStates = function (states) {
      var mergedState = _super.prototype._mergeStates.call(this, states);

      var mergedStyle;

      for (var i = 0; i < states.length; i++) {
        var state = states[i];

        if (state.style) {
          mergedStyle = mergedStyle || {};

          this._mergeStyle(mergedStyle, state.style);
        }
      }

      if (mergedStyle) {
        mergedState.style = mergedStyle;
      }

      return mergedState;
    };

    Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) {
      extend(targetStyle, sourceStyle);
      return targetStyle;
    };

    Displayable.prototype.getAnimationStyleProps = function () {
      return DEFAULT_COMMON_ANIMATION_PROPS;
    };

    Displayable.STYLE_CHANGED_BIT = 2;

    Displayable.initDefaultProps = function () {
      var dispProto = Displayable.prototype;
      dispProto.type = 'displayable';
      dispProto.invisible = false;
      dispProto.z = 0;
      dispProto.z2 = 0;
      dispProto.zlevel = 0;
      dispProto.culling = false;
      dispProto.cursor = 'pointer';
      dispProto.rectHover = false;
      dispProto.incremental = false;
      dispProto._rect = null;
      dispProto.dirtyRectTolerance = 0;
      dispProto.__dirty = Element.REDARAW_BIT | Displayable.STYLE_CHANGED_BIT;
    }();

    return Displayable;
  }(Element);

  var tmpRect = new BoundingRect(0, 0, 0, 0);
  var viewRect = new BoundingRect(0, 0, 0, 0);

  function isDisplayableCulled(el, width, height) {
    tmpRect.copy(el.getBoundingRect());

    if (el.transform) {
      tmpRect.applyTransform(el.transform);
    }

    viewRect.width = width;
    viewRect.height = height;
    return !tmpRect.intersect(viewRect);
  }

  var mathPow = Math.pow;
  var mathSqrt = Math.sqrt;
  var EPSILON$1 = 1e-8;
  var EPSILON_NUMERIC = 1e-4;
  var THREE_SQRT = mathSqrt(3);
  var ONE_THIRD = 1 / 3;

  var _v0 = create();

  var _v1 = create();

  var _v2 = create();

  function isAroundZero(val) {
    return val > -EPSILON$1 && val < EPSILON$1;
  }

  function isNotAroundZero$1(val) {
    return val > EPSILON$1 || val < -EPSILON$1;
  }

  function cubicAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return onet * onet * (onet * p0 + 3 * t * p1) + t * t * (t * p3 + 3 * onet * p2);
  }

  function cubicDerivativeAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + (p3 - p2) * t * t);
  }

  function cubicRootAt(p0, p1, p2, p3, val, roots) {
    var a = p3 + 3 * (p1 - p2) - p0;
    var b = 3 * (p2 - p1 * 2 + p0);
    var c = 3 * (p1 - p0);
    var d = p0 - val;
    var A = b * b - 3 * a * c;
    var B = b * c - 9 * a * d;
    var C = c * c - 3 * b * d;
    var n = 0;

    if (isAroundZero(A) && isAroundZero(B)) {
      if (isAroundZero(b)) {
        roots[0] = 0;
      } else {
        var t1 = -c / b;

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }
      }
    } else {
      var disc = B * B - 4 * A * C;

      if (isAroundZero(disc)) {
        var K = B / A;
        var t1 = -b / a + K;
        var t2 = -K / 2;

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }

        if (t2 >= 0 && t2 <= 1) {
          roots[n++] = t2;
        }
      } else if (disc > 0) {
        var discSqrt = mathSqrt(disc);
        var Y1 = A * b + 1.5 * a * (-B + discSqrt);
        var Y2 = A * b + 1.5 * a * (-B - discSqrt);

        if (Y1 < 0) {
          Y1 = -mathPow(-Y1, ONE_THIRD);
        } else {
          Y1 = mathPow(Y1, ONE_THIRD);
        }

        if (Y2 < 0) {
          Y2 = -mathPow(-Y2, ONE_THIRD);
        } else {
          Y2 = mathPow(Y2, ONE_THIRD);
        }

        var t1 = (-b - (Y1 + Y2)) / (3 * a);

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }
      } else {
        var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A));
        var theta = Math.acos(T) / 3;
        var ASqrt = mathSqrt(A);
        var tmp = Math.cos(theta);
        var t1 = (-b - 2 * ASqrt * tmp) / (3 * a);
        var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a);
        var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a);

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }

        if (t2 >= 0 && t2 <= 1) {
          roots[n++] = t2;
        }

        if (t3 >= 0 && t3 <= 1) {
          roots[n++] = t3;
        }
      }
    }

    return n;
  }

  function cubicExtrema(p0, p1, p2, p3, extrema) {
    var b = 6 * p2 - 12 * p1 + 6 * p0;
    var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2;
    var c = 3 * p1 - 3 * p0;
    var n = 0;

    if (isAroundZero(a)) {
      if (isNotAroundZero$1(b)) {
        var t1 = -c / b;

        if (t1 >= 0 && t1 <= 1) {
          extrema[n++] = t1;
        }
      }
    } else {
      var disc = b * b - 4 * a * c;

      if (isAroundZero(disc)) {
        extrema[0] = -b / (2 * a);
      } else if (disc > 0) {
        var discSqrt = mathSqrt(disc);
        var t1 = (-b + discSqrt) / (2 * a);
        var t2 = (-b - discSqrt) / (2 * a);

        if (t1 >= 0 && t1 <= 1) {
          extrema[n++] = t1;
        }

        if (t2 >= 0 && t2 <= 1) {
          extrema[n++] = t2;
        }
      }
    }

    return n;
  }

  function cubicSubdivide(p0, p1, p2, p3, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p23 = (p3 - p2) * t + p2;
    var p012 = (p12 - p01) * t + p01;
    var p123 = (p23 - p12) * t + p12;
    var p0123 = (p123 - p012) * t + p012;
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;
    out[3] = p0123;
    out[4] = p0123;
    out[5] = p123;
    out[6] = p23;
    out[7] = p3;
  }

  function cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, out) {
    var t;
    var interval = 0.005;
    var d = Infinity;
    var prev;
    var next;
    var d1;
    var d2;
    _v0[0] = x;
    _v0[1] = y;

    for (var _t = 0; _t < 1; _t += 0.05) {
      _v1[0] = cubicAt(x0, x1, x2, x3, _t);
      _v1[1] = cubicAt(y0, y1, y2, y3, _t);
      d1 = distSquare(_v0, _v1);

      if (d1 < d) {
        t = _t;
        d = d1;
      }
    }

    d = Infinity;

    for (var i = 0; i < 32; i++) {
      if (interval < EPSILON_NUMERIC) {
        break;
      }

      prev = t - interval;
      next = t + interval;
      _v1[0] = cubicAt(x0, x1, x2, x3, prev);
      _v1[1] = cubicAt(y0, y1, y2, y3, prev);
      d1 = distSquare(_v1, _v0);

      if (prev >= 0 && d1 < d) {
        t = prev;
        d = d1;
      } else {
        _v2[0] = cubicAt(x0, x1, x2, x3, next);
        _v2[1] = cubicAt(y0, y1, y2, y3, next);
        d2 = distSquare(_v2, _v0);

        if (next <= 1 && d2 < d) {
          t = next;
          d = d2;
        } else {
          interval *= 0.5;
        }
      }
    }

    if (out) {
      out[0] = cubicAt(x0, x1, x2, x3, t);
      out[1] = cubicAt(y0, y1, y2, y3, t);
    }

    return mathSqrt(d);
  }

  function cubicLength(x0, y0, x1, y1, x2, y2, x3, y3, iteration) {
    var px = x0;
    var py = y0;
    var d = 0;
    var step = 1 / iteration;

    for (var i = 1; i <= iteration; i++) {
      var t = i * step;
      var x = cubicAt(x0, x1, x2, x3, t);
      var y = cubicAt(y0, y1, y2, y3, t);
      var dx = x - px;
      var dy = y - py;
      d += Math.sqrt(dx * dx + dy * dy);
      px = x;
      py = y;
    }

    return d;
  }

  function quadraticAt(p0, p1, p2, t) {
    var onet = 1 - t;
    return onet * (onet * p0 + 2 * t * p1) + t * t * p2;
  }

  function quadraticDerivativeAt(p0, p1, p2, t) {
    return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1));
  }

  function quadraticRootAt(p0, p1, p2, val, roots) {
    var a = p0 - 2 * p1 + p2;
    var b = 2 * (p1 - p0);
    var c = p0 - val;
    var n = 0;

    if (isAroundZero(a)) {
      if (isNotAroundZero$1(b)) {
        var t1 = -c / b;

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }
      }
    } else {
      var disc = b * b - 4 * a * c;

      if (isAroundZero(disc)) {
        var t1 = -b / (2 * a);

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }
      } else if (disc > 0) {
        var discSqrt = mathSqrt(disc);
        var t1 = (-b + discSqrt) / (2 * a);
        var t2 = (-b - discSqrt) / (2 * a);

        if (t1 >= 0 && t1 <= 1) {
          roots[n++] = t1;
        }

        if (t2 >= 0 && t2 <= 1) {
          roots[n++] = t2;
        }
      }
    }

    return n;
  }

  function quadraticExtremum(p0, p1, p2) {
    var divider = p0 + p2 - 2 * p1;

    if (divider === 0) {
      return 0.5;
    } else {
      return (p0 - p1) / divider;
    }
  }

  function quadraticSubdivide(p0, p1, p2, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p012 = (p12 - p01) * t + p01;
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;
    out[3] = p012;
    out[4] = p12;
    out[5] = p2;
  }

  function quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, out) {
    var t;
    var interval = 0.005;
    var d = Infinity;
    _v0[0] = x;
    _v0[1] = y;

    for (var _t = 0; _t < 1; _t += 0.05) {
      _v1[0] = quadraticAt(x0, x1, x2, _t);
      _v1[1] = quadraticAt(y0, y1, y2, _t);
      var d1 = distSquare(_v0, _v1);

      if (d1 < d) {
        t = _t;
        d = d1;
      }
    }

    d = Infinity;

    for (var i = 0; i < 32; i++) {
      if (interval < EPSILON_NUMERIC) {
        break;
      }

      var prev = t - interval;
      var next = t + interval;
      _v1[0] = quadraticAt(x0, x1, x2, prev);
      _v1[1] = quadraticAt(y0, y1, y2, prev);
      var d1 = distSquare(_v1, _v0);

      if (prev >= 0 && d1 < d) {
        t = prev;
        d = d1;
      } else {
        _v2[0] = quadraticAt(x0, x1, x2, next);
        _v2[1] = quadraticAt(y0, y1, y2, next);
        var d2 = distSquare(_v2, _v0);

        if (next <= 1 && d2 < d) {
          t = next;
          d = d2;
        } else {
          interval *= 0.5;
        }
      }
    }

    if (out) {
      out[0] = quadraticAt(x0, x1, x2, t);
      out[1] = quadraticAt(y0, y1, y2, t);
    }

    return mathSqrt(d);
  }

  function quadraticLength(x0, y0, x1, y1, x2, y2, iteration) {
    var px = x0;
    var py = y0;
    var d = 0;
    var step = 1 / iteration;

    for (var i = 1; i <= iteration; i++) {
      var t = i * step;
      var x = quadraticAt(x0, x1, x2, t);
      var y = quadraticAt(y0, y1, y2, t);
      var dx = x - px;
      var dy = y - py;
      d += Math.sqrt(dx * dx + dy * dy);
      px = x;
      py = y;
    }

    return d;
  }

  var mathMin$1 = Math.min;
  var mathMax$1 = Math.max;
  var mathSin = Math.sin;
  var mathCos = Math.cos;
  var PI2 = Math.PI * 2;
  var start = create();
  var end = create();
  var extremity = create();

  function fromPoints(points, min, max) {
    if (points.length === 0) {
      return;
    }

    var p = points[0];
    var left = p[0];
    var right = p[0];
    var top = p[1];
    var bottom = p[1];

    for (var i = 1; i < points.length; i++) {
      p = points[i];
      left = mathMin$1(left, p[0]);
      right = mathMax$1(right, p[0]);
      top = mathMin$1(top, p[1]);
      bottom = mathMax$1(bottom, p[1]);
    }

    min[0] = left;
    min[1] = top;
    max[0] = right;
    max[1] = bottom;
  }

  function fromLine(x0, y0, x1, y1, min, max) {
    min[0] = mathMin$1(x0, x1);
    min[1] = mathMin$1(y0, y1);
    max[0] = mathMax$1(x0, x1);
    max[1] = mathMax$1(y0, y1);
  }

  var xDim = [];
  var yDim = [];

  function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) {
    var cubicExtrema$1 = cubicExtrema;
    var cubicAt$1 = cubicAt;
    var n = cubicExtrema$1(x0, x1, x2, x3, xDim);
    min[0] = Infinity;
    min[1] = Infinity;
    max[0] = -Infinity;
    max[1] = -Infinity;

    for (var i = 0; i < n; i++) {
      var x = cubicAt$1(x0, x1, x2, x3, xDim[i]);
      min[0] = mathMin$1(x, min[0]);
      max[0] = mathMax$1(x, max[0]);
    }

    n = cubicExtrema$1(y0, y1, y2, y3, yDim);

    for (var i = 0; i < n; i++) {
      var y = cubicAt$1(y0, y1, y2, y3, yDim[i]);
      min[1] = mathMin$1(y, min[1]);
      max[1] = mathMax$1(y, max[1]);
    }

    min[0] = mathMin$1(x0, min[0]);
    max[0] = mathMax$1(x0, max[0]);
    min[0] = mathMin$1(x3, min[0]);
    max[0] = mathMax$1(x3, max[0]);
    min[1] = mathMin$1(y0, min[1]);
    max[1] = mathMax$1(y0, max[1]);
    min[1] = mathMin$1(y3, min[1]);
    max[1] = mathMax$1(y3, max[1]);
  }

  function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) {
    var quadraticExtremum$1 = quadraticExtremum;
    var quadraticAt$1 = quadraticAt;
    var tx = mathMax$1(mathMin$1(quadraticExtremum$1(x0, x1, x2), 1), 0);
    var ty = mathMax$1(mathMin$1(quadraticExtremum$1(y0, y1, y2), 1), 0);
    var x = quadraticAt$1(x0, x1, x2, tx);
    var y = quadraticAt$1(y0, y1, y2, ty);
    min[0] = mathMin$1(x0, x2, x);
    min[1] = mathMin$1(y0, y2, y);
    max[0] = mathMax$1(x0, x2, x);
    max[1] = mathMax$1(y0, y2, y);
  }

  function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min$1, max$1) {
    var vec2Min = min;
    var vec2Max = max;
    var diff = Math.abs(startAngle - endAngle);

    if (diff % PI2 < 1e-4 && diff > 1e-4) {
      min$1[0] = x - rx;
      min$1[1] = y - ry;
      max$1[0] = x + rx;
      max$1[1] = y + ry;
      return;
    }

    start[0] = mathCos(startAngle) * rx + x;
    start[1] = mathSin(startAngle) * ry + y;
    end[0] = mathCos(endAngle) * rx + x;
    end[1] = mathSin(endAngle) * ry + y;
    vec2Min(min$1, start, end);
    vec2Max(max$1, start, end);
    startAngle = startAngle % PI2;

    if (startAngle < 0) {
      startAngle = startAngle + PI2;
    }

    endAngle = endAngle % PI2;

    if (endAngle < 0) {
      endAngle = endAngle + PI2;
    }

    if (startAngle > endAngle && !anticlockwise) {
      endAngle += PI2;
    } else if (startAngle < endAngle && anticlockwise) {
      startAngle += PI2;
    }

    if (anticlockwise) {
      var tmp = endAngle;
      endAngle = startAngle;
      startAngle = tmp;
    }

    for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
      if (angle > startAngle) {
        extremity[0] = mathCos(angle) * rx + x;
        extremity[1] = mathSin(angle) * ry + y;
        vec2Min(min$1, extremity, min$1);
        vec2Max(max$1, extremity, max$1);
      }
    }
  }

  var CMD = {
    M: 1,
    L: 2,
    C: 3,
    Q: 4,
    A: 5,
    Z: 6,
    R: 7
  };
  var tmpOutX = [];
  var tmpOutY = [];
  var min$1 = [];
  var max$1 = [];
  var min2 = [];
  var max2 = [];
  var mathMin$2 = Math.min;
  var mathMax$2 = Math.max;
  var mathCos$1 = Math.cos;
  var mathSin$1 = Math.sin;
  var mathSqrt$1 = Math.sqrt;
  var mathAbs = Math.abs;
  var PI = Math.PI;
  var PI2$1 = PI * 2;
  var hasTypedArray = typeof Float32Array !== 'undefined';
  var tmpAngles = [];

  function modPI2(radian) {
    var n = Math.round(radian / PI * 1e8) / 1e8;
    return n % 2 * PI;
  }

  function normalizeArcAngles(angles, anticlockwise) {
    var newStartAngle = modPI2(angles[0]);

    if (newStartAngle < 0) {
      newStartAngle += PI2$1;
    }

    var delta = newStartAngle - angles[0];
    var newEndAngle = angles[1];
    newEndAngle += delta;

    if (!anticlockwise && newEndAngle - newStartAngle >= PI2$1) {
      newEndAngle = newStartAngle + PI2$1;
    } else if (anticlockwise && newStartAngle - newEndAngle >= PI2$1) {
      newEndAngle = newStartAngle - PI2$1;
    } else if (!anticlockwise && newStartAngle > newEndAngle) {
      newEndAngle = newStartAngle + (PI2$1 - modPI2(newStartAngle - newEndAngle));
    } else if (anticlockwise && newStartAngle < newEndAngle) {
      newEndAngle = newStartAngle - (PI2$1 - modPI2(newEndAngle - newStartAngle));
    }

    angles[0] = newStartAngle;
    angles[1] = newEndAngle;
  }

  var PathProxy = function () {
    function PathProxy(notSaveData) {
      this.dpr = 1;
      this._version = 0;
      this._xi = 0;
      this._yi = 0;
      this._x0 = 0;
      this._y0 = 0;
      this._len = 0;

      if (notSaveData) {
        this._saveData = false;
      }

      if (this._saveData) {
        this.data = [];
      }
    }

    PathProxy.prototype.increaseVersion = function () {
      this._version++;
    };

    PathProxy.prototype.getVersion = function () {
      return this._version;
    };

    PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) {
      segmentIgnoreThreshold = segmentIgnoreThreshold || 0;

      if (segmentIgnoreThreshold > 0) {
        this._ux = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sx) || 0;
        this._uy = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sy) || 0;
      }
    };

    PathProxy.prototype.setDPR = function (dpr) {
      this.dpr = dpr;
    };

    PathProxy.prototype.setContext = function (ctx) {
      this._ctx = ctx;
    };

    PathProxy.prototype.getContext = function () {
      return this._ctx;
    };

    PathProxy.prototype.beginPath = function () {
      this._ctx && this._ctx.beginPath();
      this.reset();
      return this;
    };

    PathProxy.prototype.reset = function () {
      if (this._saveData) {
        this._len = 0;
      }

      if (this._lineDash) {
        this._lineDash = null;
        this._dashOffset = 0;
      }

      if (this._pathSegLen) {
        this._pathSegLen = null;
        this._pathLen = 0;
      }

      this._version++;
    };

    PathProxy.prototype.moveTo = function (x, y) {
      this.addData(CMD.M, x, y);
      this._ctx && this._ctx.moveTo(x, y);
      this._x0 = x;
      this._y0 = y;
      this._xi = x;
      this._yi = y;
      return this;
    };

    PathProxy.prototype.lineTo = function (x, y) {
      var exceedUnit = mathAbs(x - this._xi) > this._ux || mathAbs(y - this._yi) > this._uy || this._len < 5;
      this.addData(CMD.L, x, y);

      if (this._ctx && exceedUnit) {
        this._needsDash ? this._dashedLineTo(x, y) : this._ctx.lineTo(x, y);
      }

      if (exceedUnit) {
        this._xi = x;
        this._yi = y;
      }

      return this;
    };

    PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) {
      this.addData(CMD.C, x1, y1, x2, y2, x3, y3);

      if (this._ctx) {
        this._needsDash ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
      }

      this._xi = x3;
      this._yi = y3;
      return this;
    };

    PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) {
      this.addData(CMD.Q, x1, y1, x2, y2);

      if (this._ctx) {
        this._needsDash ? this._dashedQuadraticTo(x1, y1, x2, y2) : this._ctx.quadraticCurveTo(x1, y1, x2, y2);
      }

      this._xi = x2;
      this._yi = y2;
      return this;
    };

    PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) {
      tmpAngles[0] = startAngle;
      tmpAngles[1] = endAngle;
      normalizeArcAngles(tmpAngles, anticlockwise);
      startAngle = tmpAngles[0];
      endAngle = tmpAngles[1];
      var delta = endAngle - startAngle;
      this.addData(CMD.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1);
      this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
      this._xi = mathCos$1(endAngle) * r + cx;
      this._yi = mathSin$1(endAngle) * r + cy;
      return this;
    };

    PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) {
      if (this._ctx) {
        this._ctx.arcTo(x1, y1, x2, y2, radius);
      }

      return this;
    };

    PathProxy.prototype.rect = function (x, y, w, h) {
      this._ctx && this._ctx.rect(x, y, w, h);
      this.addData(CMD.R, x, y, w, h);
      return this;
    };

    PathProxy.prototype.closePath = function () {
      this.addData(CMD.Z);
      var ctx = this._ctx;
      var x0 = this._x0;
      var y0 = this._y0;

      if (ctx) {
        this._needsDash && this._dashedLineTo(x0, y0);
        ctx.closePath();
      }

      this._xi = x0;
      this._yi = y0;
      return this;
    };

    PathProxy.prototype.fill = function (ctx) {
      ctx && ctx.fill();
      this.toStatic();
    };

    PathProxy.prototype.stroke = function (ctx) {
      ctx && ctx.stroke();
      this.toStatic();
    };

    PathProxy.prototype.setLineDash = function (lineDash) {
      if (lineDash instanceof Array) {
        this._lineDash = lineDash;
        this._dashIdx = 0;
        var lineDashSum = 0;

        for (var i = 0; i < lineDash.length; i++) {
          lineDashSum += lineDash[i];
        }

        this._dashSum = lineDashSum;
        this._needsDash = true;
      } else {
        this._lineDash = null;
        this._needsDash = false;
      }

      return this;
    };

    PathProxy.prototype.setLineDashOffset = function (offset) {
      this._dashOffset = offset;
      return this;
    };

    PathProxy.prototype.len = function () {
      return this._len;
    };

    PathProxy.prototype.setData = function (data) {
      var len = data.length;

      if (!(this.data && this.data.length === len) && hasTypedArray) {
        this.data = new Float32Array(len);
      }

      for (var i = 0; i < len; i++) {
        this.data[i] = data[i];
      }

      this._len = len;
    };

    PathProxy.prototype.appendPath = function (path) {
      if (!(path instanceof Array)) {
        path = [path];
      }

      var len = path.length;
      var appendSize = 0;
      var offset = this._len;

      for (var i = 0; i < len; i++) {
        appendSize += path[i].len();
      }

      if (hasTypedArray && this.data instanceof Float32Array) {
        this.data = new Float32Array(offset + appendSize);
      }

      for (var i = 0; i < len; i++) {
        var appendPathData = path[i].data;

        for (var k = 0; k < appendPathData.length; k++) {
          this.data[offset++] = appendPathData[k];
        }
      }

      this._len = offset;
    };

    PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) {
      if (!this._saveData) {
        return;
      }

      var data = this.data;

      if (this._len + arguments.length > data.length) {
        this._expandData();

        data = this.data;
      }

      for (var i = 0; i < arguments.length; i++) {
        data[this._len++] = arguments[i];
      }
    };

    PathProxy.prototype._expandData = function () {
      if (!(this.data instanceof Array)) {
        var newData = [];

        for (var i = 0; i < this._len; i++) {
          newData[i] = this.data[i];
        }

        this.data = newData;
      }
    };

    PathProxy.prototype._dashedLineTo = function (x1, y1) {
      var dashSum = this._dashSum;
      var lineDash = this._lineDash;
      var ctx = this._ctx;
      var offset = this._dashOffset;
      var x0 = this._xi;
      var y0 = this._yi;
      var dx = x1 - x0;
      var dy = y1 - y0;
      var dist = mathSqrt$1(dx * dx + dy * dy);
      var x = x0;
      var y = y0;
      var nDash = lineDash.length;
      var dash;
      var idx;
      dx /= dist;
      dy /= dist;

      if (offset < 0) {
        offset = dashSum + offset;
      }

      offset %= dashSum;
      x -= offset * dx;
      y -= offset * dy;

      while (dx > 0 && x <= x1 || dx < 0 && x >= x1 || dx === 0 && (dy > 0 && y <= y1 || dy < 0 && y >= y1)) {
        idx = this._dashIdx;
        dash = lineDash[idx];
        x += dx * dash;
        y += dy * dash;
        this._dashIdx = (idx + 1) % nDash;

        if (dx > 0 && x < x0 || dx < 0 && x > x0 || dy > 0 && y < y0 || dy < 0 && y > y0) {
          continue;
        }

        ctx[idx % 2 ? 'moveTo' : 'lineTo'](dx >= 0 ? mathMin$2(x, x1) : mathMax$2(x, x1), dy >= 0 ? mathMin$2(y, y1) : mathMax$2(y, y1));
      }

      dx = x - x1;
      dy = y - y1;
      this._dashOffset = -mathSqrt$1(dx * dx + dy * dy);
    };

    PathProxy.prototype._dashedBezierTo = function (x1, y1, x2, y2, x3, y3) {
      var ctx = this._ctx;
      var dashSum = this._dashSum;
      var offset = this._dashOffset;
      var lineDash = this._lineDash;
      var x0 = this._xi;
      var y0 = this._yi;
      var bezierLen = 0;
      var idx = this._dashIdx;
      var nDash = lineDash.length;
      var t;
      var dx;
      var dy;
      var x;
      var y;
      var tmpLen = 0;

      if (offset < 0) {
        offset = dashSum + offset;
      }

      offset %= dashSum;

      for (t = 0; t < 1; t += 0.1) {
        dx = cubicAt(x0, x1, x2, x3, t + 0.1) - cubicAt(x0, x1, x2, x3, t);
        dy = cubicAt(y0, y1, y2, y3, t + 0.1) - cubicAt(y0, y1, y2, y3, t);
        bezierLen += mathSqrt$1(dx * dx + dy * dy);
      }

      for (; idx < nDash; idx++) {
        tmpLen += lineDash[idx];

        if (tmpLen > offset) {
          break;
        }
      }

      t = (tmpLen - offset) / bezierLen;

      while (t <= 1) {
        x = cubicAt(x0, x1, x2, x3, t);
        y = cubicAt(y0, y1, y2, y3, t);
        idx % 2 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
        t += lineDash[idx] / bezierLen;
        idx = (idx + 1) % nDash;
      }

      idx % 2 !== 0 && ctx.lineTo(x3, y3);
      dx = x3 - x;
      dy = y3 - y;
      this._dashOffset = -mathSqrt$1(dx * dx + dy * dy);
    };

    PathProxy.prototype._dashedQuadraticTo = function (x1, y1, x2, y2) {
      var x3 = x2;
      var y3 = y2;
      x2 = (x2 + 2 * x1) / 3;
      y2 = (y2 + 2 * y1) / 3;
      x1 = (this._xi + 2 * x1) / 3;
      y1 = (this._yi + 2 * y1) / 3;

      this._dashedBezierTo(x1, y1, x2, y2, x3, y3);
    };

    PathProxy.prototype.toStatic = function () {
      if (!this._saveData) {
        return;
      }

      var data = this.data;

      if (data instanceof Array) {
        data.length = this._len;

        if (hasTypedArray && this._len > 11) {
          this.data = new Float32Array(data);
        }
      }
    };

    PathProxy.prototype.getBoundingRect = function () {
      min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE;
      max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE;
      var data = this.data;
      var xi = 0;
      var yi = 0;
      var x0 = 0;
      var y0 = 0;
      var i;

      for (i = 0; i < this._len;) {
        var cmd = data[i++];
        var isFirst = i === 1;

        if (isFirst) {
          xi = data[i];
          yi = data[i + 1];
          x0 = xi;
          y0 = yi;
        }

        switch (cmd) {
          case CMD.M:
            xi = x0 = data[i++];
            yi = y0 = data[i++];
            min2[0] = x0;
            min2[1] = y0;
            max2[0] = x0;
            max2[1] = y0;
            break;

          case CMD.L:
            fromLine(xi, yi, data[i], data[i + 1], min2, max2);
            xi = data[i++];
            yi = data[i++];
            break;

          case CMD.C:
            fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2);
            xi = data[i++];
            yi = data[i++];
            break;

          case CMD.Q:
            fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2);
            xi = data[i++];
            yi = data[i++];
            break;

          case CMD.A:
            var cx = data[i++];
            var cy = data[i++];
            var rx = data[i++];
            var ry = data[i++];
            var startAngle = data[i++];
            var endAngle = data[i++] + startAngle;
            i += 1;
            var anticlockwise = !data[i++];

            if (isFirst) {
              x0 = mathCos$1(startAngle) * rx + cx;
              y0 = mathSin$1(startAngle) * ry + cy;
            }

            fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2);
            xi = mathCos$1(endAngle) * rx + cx;
            yi = mathSin$1(endAngle) * ry + cy;
            break;

          case CMD.R:
            x0 = xi = data[i++];
            y0 = yi = data[i++];
            var width = data[i++];
            var height = data[i++];
            fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
            break;

          case CMD.Z:
            xi = x0;
            yi = y0;
            break;
        }

        min(min$1, min$1, min2);
        max(max$1, max$1, max2);
      }

      if (i === 0) {
        min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
      }

      return new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
    };

    PathProxy.prototype._calculateLength = function () {
      var data = this.data;
      var len = this._len;
      var ux = this._ux;
      var uy = this._uy;
      var xi = 0;
      var yi = 0;
      var x0 = 0;
      var y0 = 0;

      if (!this._pathSegLen) {
        this._pathSegLen = [];
      }

      var pathSegLen = this._pathSegLen;
      var pathTotalLen = 0;
      var segCount = 0;

      for (var i = 0; i < len;) {
        var cmd = data[i++];
        var isFirst = i === 1;

        if (isFirst) {
          xi = data[i];
          yi = data[i + 1];
          x0 = xi;
          y0 = yi;
        }

        var l = -1;

        switch (cmd) {
          case CMD.M:
            xi = x0 = data[i++];
            yi = y0 = data[i++];
            break;

          case CMD.L:
            {
              var x2 = data[i++];
              var y2 = data[i++];
              var dx = x2 - xi;
              var dy = y2 - yi;

              if (mathAbs(dx) > ux || mathAbs(dy) > uy || i === len - 1) {
                l = Math.sqrt(dx * dx + dy * dy);
                xi = x2;
                yi = y2;
              }

              break;
            }

          case CMD.C:
            {
              var x1 = data[i++];
              var y1 = data[i++];
              var x2 = data[i++];
              var y2 = data[i++];
              var x3 = data[i++];
              var y3 = data[i++];
              l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10);
              xi = x3;
              yi = y3;
              break;
            }

          case CMD.Q:
            {
              var x1 = data[i++];
              var y1 = data[i++];
              var x2 = data[i++];
              var y2 = data[i++];
              l = quadraticLength(xi, yi, x1, y1, x2, y2, 10);
              xi = x2;
              yi = y2;
              break;
            }

          case CMD.A:
            var cx = data[i++];
            var cy = data[i++];
            var rx = data[i++];
            var ry = data[i++];
            var startAngle = data[i++];
            var delta = data[i++];
            var endAngle = delta + startAngle;
            i += 1;
            var anticlockwise = !data[i++];

            if (isFirst) {
              x0 = mathCos$1(startAngle) * rx + cx;
              y0 = mathSin$1(startAngle) * ry + cy;
            }

            l = mathMax$2(rx, ry) * mathMin$2(PI2$1, Math.abs(delta));
            xi = mathCos$1(endAngle) * rx + cx;
            yi = mathSin$1(endAngle) * ry + cy;
            break;

          case CMD.R:
            {
              x0 = xi = data[i++];
              y0 = yi = data[i++];
              var width = data[i++];
              var height = data[i++];
              l = width * 2 + height * 2;
              break;
            }

          case CMD.Z:
            {
              var dx = x0 - xi;
              var dy = y0 - yi;
              l = Math.sqrt(dx * dx + dy * dy);
              xi = x0;
              yi = y0;
              break;
            }
        }

        if (l >= 0) {
          pathSegLen[segCount++] = l;
          pathTotalLen += l;
        }
      }

      this._pathLen = pathTotalLen;
      return pathTotalLen;
    };

    PathProxy.prototype.rebuildPath = function (ctx, percent) {
      var d = this.data;
      var ux = this._ux;
      var uy = this._uy;
      var len = this._len;
      var x0;
      var y0;
      var xi;
      var yi;
      var x;
      var y;
      var drawPart = percent < 1;
      var pathSegLen;
      var pathTotalLen;
      var accumLength = 0;
      var segCount = 0;
      var displayedLength;

      if (drawPart) {
        if (!this._pathSegLen) {
          this._calculateLength();
        }

        pathSegLen = this._pathSegLen;
        pathTotalLen = this._pathLen;
        displayedLength = percent * pathTotalLen;

        if (!displayedLength) {
          return;
        }
      }

      lo: for (var i = 0; i < len;) {
        var cmd = d[i++];
        var isFirst = i === 1;

        if (isFirst) {
          xi = d[i];
          yi = d[i + 1];
          x0 = xi;
          y0 = yi;
        }

        switch (cmd) {
          case CMD.M:
            x0 = xi = d[i++];
            y0 = yi = d[i++];
            ctx.moveTo(xi, yi);
            break;

          case CMD.L:
            {
              x = d[i++];
              y = d[i++];

              if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len - 1) {
                if (drawPart) {
                  var l = pathSegLen[segCount++];

                  if (accumLength + l > displayedLength) {
                    var t = (displayedLength - accumLength) / l;
                    ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t);
                    break lo;
                  }

                  accumLength += l;
                }

                ctx.lineTo(x, y);
                xi = x;
                yi = y;
              }

              break;
            }

          case CMD.C:
            {
              var x1 = d[i++];
              var y1 = d[i++];
              var x2 = d[i++];
              var y2 = d[i++];
              var x3 = d[i++];
              var y3 = d[i++];

              if (drawPart) {
                var l = pathSegLen[segCount++];

                if (accumLength + l > displayedLength) {
                  var t = (displayedLength - accumLength) / l;
                  cubicSubdivide(xi, x1, x2, x3, t, tmpOutX);
                  cubicSubdivide(yi, y1, y2, y3, t, tmpOutY);
                  ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]);
                  break lo;
                }

                accumLength += l;
              }

              ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
              xi = x3;
              yi = y3;
              break;
            }

          case CMD.Q:
            {
              var x1 = d[i++];
              var y1 = d[i++];
              var x2 = d[i++];
              var y2 = d[i++];

              if (drawPart) {
                var l = pathSegLen[segCount++];

                if (accumLength + l > displayedLength) {
                  var t = (displayedLength - accumLength) / l;
                  quadraticSubdivide(xi, x1, x2, t, tmpOutX);
                  quadraticSubdivide(yi, y1, y2, t, tmpOutY);
                  ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]);
                  break lo;
                }

                accumLength += l;
              }

              ctx.quadraticCurveTo(x1, y1, x2, y2);
              xi = x2;
              yi = y2;
              break;
            }

          case CMD.A:
            var cx = d[i++];
            var cy = d[i++];
            var rx = d[i++];
            var ry = d[i++];
            var startAngle = d[i++];
            var delta = d[i++];
            var psi = d[i++];
            var anticlockwise = !d[i++];
            var r = rx > ry ? rx : ry;
            var isEllipse = mathAbs(rx - ry) > 1e-3;
            var endAngle = startAngle + delta;
            var breakBuild = false;

            if (drawPart) {
              var l = pathSegLen[segCount++];

              if (accumLength + l > displayedLength) {
                endAngle = startAngle + delta * (displayedLength - accumLength) / l;
                breakBuild = true;
              }

              accumLength += l;
            }

            if (isEllipse && ctx.ellipse) {
              ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise);
            } else {
              ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
            }

            if (breakBuild) {
              break lo;
            }

            if (isFirst) {
              x0 = mathCos$1(startAngle) * rx + cx;
              y0 = mathSin$1(startAngle) * ry + cy;
            }

            xi = mathCos$1(endAngle) * rx + cx;
            yi = mathSin$1(endAngle) * ry + cy;
            break;

          case CMD.R:
            x0 = xi = d[i];
            y0 = yi = d[i + 1];
            x = d[i++];
            y = d[i++];
            var width = d[i++];
            var height = d[i++];

            if (drawPart) {
              var l = pathSegLen[segCount++];

              if (accumLength + l > displayedLength) {
                var d_1 = displayedLength - accumLength;
                ctx.moveTo(x, y);
                ctx.lineTo(x + mathMin$2(d_1, width), y);
                d_1 -= width;

                if (d_1 > 0) {
                  ctx.lineTo(x + width, y + mathMin$2(d_1, height));
                }

                d_1 -= height;

                if (d_1 > 0) {
                  ctx.lineTo(x + mathMax$2(width - d_1, 0), y + height);
                }

                d_1 -= width;

                if (d_1 > 0) {
                  ctx.lineTo(x, y + mathMax$2(height - d_1, 0));
                }

                break lo;
              }

              accumLength += l;
            }

            ctx.rect(x, y, width, height);
            break;

          case CMD.Z:
            if (drawPart) {
              var l = pathSegLen[segCount++];

              if (accumLength + l > displayedLength) {
                var t = (displayedLength - accumLength) / l;
                ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t);
                break lo;
              }

              accumLength += l;
            }

            ctx.closePath();
            xi = x0;
            yi = y0;
        }
      }
    };

    PathProxy.CMD = CMD;

    PathProxy.initDefaultProps = function () {
      var proto = PathProxy.prototype;
      proto._saveData = true;
      proto._needsDash = false;
      proto._dashOffset = 0;
      proto._dashIdx = 0;
      proto._dashSum = 0;
      proto._ux = 0;
      proto._uy = 0;
    }();

    return PathProxy;
  }();

  function containStroke(x0, y0, x1, y1, lineWidth, x, y) {
    if (lineWidth === 0) {
      return false;
    }

    var _l = lineWidth;
    var _a = 0;
    var _b = x0;

    if (y > y0 + _l && y > y1 + _l || y < y0 - _l && y < y1 - _l || x > x0 + _l && x > x1 + _l || x < x0 - _l && x < x1 - _l) {
      return false;
    }

    if (x0 !== x1) {
      _a = (y0 - y1) / (x0 - x1);
      _b = (x0 * y1 - x1 * y0) / (x0 - x1);
    } else {
      return Math.abs(x - x0) <= _l / 2;
    }

    var tmp = _a * x - y + _b;

    var _s = tmp * tmp / (_a * _a + 1);

    return _s <= _l / 2 * _l / 2;
  }

  function containStroke$1(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) {
    if (lineWidth === 0) {
      return false;
    }

    var _l = lineWidth;

    if (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l || y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l || x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l || x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l) {
      return false;
    }

    var d = cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, null);
    return d <= _l / 2;
  }

  function containStroke$2(x0, y0, x1, y1, x2, y2, lineWidth, x, y) {
    if (lineWidth === 0) {
      return false;
    }

    var _l = lineWidth;

    if (y > y0 + _l && y > y1 + _l && y > y2 + _l || y < y0 - _l && y < y1 - _l && y < y2 - _l || x > x0 + _l && x > x1 + _l && x > x2 + _l || x < x0 - _l && x < x1 - _l && x < x2 - _l) {
      return false;
    }

    var d = quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, null);
    return d <= _l / 2;
  }

  var PI2$2 = Math.PI * 2;

  function normalizeRadian(angle) {
    angle %= PI2$2;

    if (angle < 0) {
      angle += PI2$2;
    }

    return angle;
  }

  var PI2$3 = Math.PI * 2;

  function containStroke$3(cx, cy, r, startAngle, endAngle, anticlockwise, lineWidth, x, y) {
    if (lineWidth === 0) {
      return false;
    }

    var _l = lineWidth;
    x -= cx;
    y -= cy;
    var d = Math.sqrt(x * x + y * y);

    if (d - _l > r || d + _l < r) {
      return false;
    }

    if (Math.abs(startAngle - endAngle) % PI2$3 < 1e-4) {
      return true;
    }

    if (anticlockwise) {
      var tmp = startAngle;
      startAngle = normalizeRadian(endAngle);
      endAngle = normalizeRadian(tmp);
    } else {
      startAngle = normalizeRadian(startAngle);
      endAngle = normalizeRadian(endAngle);
    }

    if (startAngle > endAngle) {
      endAngle += PI2$3;
    }

    var angle = Math.atan2(y, x);

    if (angle < 0) {
      angle += PI2$3;
    }

    return angle >= startAngle && angle <= endAngle || angle + PI2$3 >= startAngle && angle + PI2$3 <= endAngle;
  }

  function windingLine(x0, y0, x1, y1, x, y) {
    if (y > y0 && y > y1 || y < y0 && y < y1) {
      return 0;
    }

    if (y1 === y0) {
      return 0;
    }

    var t = (y - y0) / (y1 - y0);
    var dir = y1 < y0 ? 1 : -1;

    if (t === 1 || t === 0) {
      dir = y1 < y0 ? 0.5 : -0.5;
    }

    var x_ = t * (x1 - x0) + x0;
    return x_ === x ? Infinity : x_ > x ? dir : 0;
  }

  var CMD$1 = PathProxy.CMD;
  var PI2$4 = Math.PI * 2;
  var EPSILON$2 = 1e-4;

  function isAroundEqual(a, b) {
    return Math.abs(a - b) < EPSILON$2;
  }

  var roots = [-1, -1, -1];
  var extrema = [-1, -1];

  function swapExtrema() {
    var tmp = extrema[0];
    extrema[0] = extrema[1];
    extrema[1] = tmp;
  }

  function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) {
    if (y > y0 && y > y1 && y > y2 && y > y3 || y < y0 && y < y1 && y < y2 && y < y3) {
      return 0;
    }

    var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots);

    if (nRoots === 0) {
      return 0;
    } else {
      var w = 0;
      var nExtrema = -1;
      var y0_ = void 0;
      var y1_ = void 0;

      for (var i = 0; i < nRoots; i++) {
        var t = roots[i];
        var unit = t === 0 || t === 1 ? 0.5 : 1;
        var x_ = cubicAt(x0, x1, x2, x3, t);

        if (x_ < x) {
          continue;
        }

        if (nExtrema < 0) {
          nExtrema = cubicExtrema(y0, y1, y2, y3, extrema);

          if (extrema[1] < extrema[0] && nExtrema > 1) {
            swapExtrema();
          }

          y0_ = cubicAt(y0, y1, y2, y3, extrema[0]);

          if (nExtrema > 1) {
            y1_ = cubicAt(y0, y1, y2, y3, extrema[1]);
          }
        }

        if (nExtrema === 2) {
          if (t < extrema[0]) {
            w += y0_ < y0 ? unit : -unit;
          } else if (t < extrema[1]) {
            w += y1_ < y0_ ? unit : -unit;
          } else {
            w += y3 < y1_ ? unit : -unit;
          }
        } else {
          if (t < extrema[0]) {
            w += y0_ < y0 ? unit : -unit;
          } else {
            w += y3 < y0_ ? unit : -unit;
          }
        }
      }

      return w;
    }
  }

  function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) {
    if (y > y0 && y > y1 && y > y2 || y < y0 && y < y1 && y < y2) {
      return 0;
    }

    var nRoots = quadraticRootAt(y0, y1, y2, y, roots);

    if (nRoots === 0) {
      return 0;
    } else {
      var t = quadraticExtremum(y0, y1, y2);

      if (t >= 0 && t <= 1) {
        var w = 0;
        var y_ = quadraticAt(y0, y1, y2, t);

        for (var i = 0; i < nRoots; i++) {
          var unit = roots[i] === 0 || roots[i] === 1 ? 0.5 : 1;
          var x_ = quadraticAt(x0, x1, x2, roots[i]);

          if (x_ < x) {
            continue;
          }

          if (roots[i] < t) {
            w += y_ < y0 ? unit : -unit;
          } else {
            w += y2 < y_ ? unit : -unit;
          }
        }

        return w;
      } else {
        var unit = roots[0] === 0 || roots[0] === 1 ? 0.5 : 1;
        var x_ = quadraticAt(x0, x1, x2, roots[0]);

        if (x_ < x) {
          return 0;
        }

        return y2 < y0 ? unit : -unit;
      }
    }
  }

  function windingArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y) {
    y -= cy;

    if (y > r || y < -r) {
      return 0;
    }

    var tmp = Math.sqrt(r * r - y * y);
    roots[0] = -tmp;
    roots[1] = tmp;
    var dTheta = Math.abs(startAngle - endAngle);

    if (dTheta < 1e-4) {
      return 0;
    }

    if (dTheta >= PI2$4 - 1e-4) {
      startAngle = 0;
      endAngle = PI2$4;
      var dir = anticlockwise ? 1 : -1;

      if (x >= roots[0] + cx && x <= roots[1] + cx) {
        return dir;
      } else {
        return 0;
      }
    }

    if (startAngle > endAngle) {
      var tmp_1 = startAngle;
      startAngle = endAngle;
      endAngle = tmp_1;
    }

    if (startAngle < 0) {
      startAngle += PI2$4;
      endAngle += PI2$4;
    }

    var w = 0;

    for (var i = 0; i < 2; i++) {
      var x_ = roots[i];

      if (x_ + cx > x) {
        var angle = Math.atan2(y, x_);
        var dir = anticlockwise ? 1 : -1;

        if (angle < 0) {
          angle = PI2$4 + angle;
        }

        if (angle >= startAngle && angle <= endAngle || angle + PI2$4 >= startAngle && angle + PI2$4 <= endAngle) {
          if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
            dir = -dir;
          }

          w += dir;
        }
      }
    }

    return w;
  }

  function containPath(path, lineWidth, isStroke, x, y) {
    var data = path.data;
    var len = path.len();
    var w = 0;
    var xi = 0;
    var yi = 0;
    var x0 = 0;
    var y0 = 0;
    var x1;
    var y1;

    for (var i = 0; i < len;) {
      var cmd = data[i++];
      var isFirst = i === 1;

      if (cmd === CMD$1.M && i > 1) {
        if (!isStroke) {
          w += windingLine(xi, yi, x0, y0, x, y);
        }
      }

      if (isFirst) {
        xi = data[i];
        yi = data[i + 1];
        x0 = xi;
        y0 = yi;
      }

      switch (cmd) {
        case CMD$1.M:
          x0 = data[i++];
          y0 = data[i++];
          xi = x0;
          yi = y0;
          break;

        case CMD$1.L:
          if (isStroke) {
            if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) {
              return true;
            }
          } else {
            w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0;
          }

          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$1.C:
          if (isStroke) {
            if (containStroke$1(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) {
              return true;
            }
          } else {
            w += windingCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y) || 0;
          }

          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$1.Q:
          if (isStroke) {
            if (containStroke$2(xi, yi, data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) {
              return true;
            }
          } else {
            w += windingQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y) || 0;
          }

          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$1.A:
          var cx = data[i++];
          var cy = data[i++];
          var rx = data[i++];
          var ry = data[i++];
          var theta = data[i++];
          var dTheta = data[i++];
          i += 1;
          var anticlockwise = !!(1 - data[i++]);
          x1 = Math.cos(theta) * rx + cx;
          y1 = Math.sin(theta) * ry + cy;

          if (!isFirst) {
            w += windingLine(xi, yi, x1, y1, x, y);
          } else {
            x0 = x1;
            y0 = y1;
          }

          var _x = (x - cx) * ry / rx + cx;

          if (isStroke) {
            if (containStroke$3(cx, cy, ry, theta, theta + dTheta, anticlockwise, lineWidth, _x, y)) {
              return true;
            }
          } else {
            w += windingArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y);
          }

          xi = Math.cos(theta + dTheta) * rx + cx;
          yi = Math.sin(theta + dTheta) * ry + cy;
          break;

        case CMD$1.R:
          x0 = xi = data[i++];
          y0 = yi = data[i++];
          var width = data[i++];
          var height = data[i++];
          x1 = x0 + width;
          y1 = y0 + height;

          if (isStroke) {
            if (containStroke(x0, y0, x1, y0, lineWidth, x, y) || containStroke(x1, y0, x1, y1, lineWidth, x, y) || containStroke(x1, y1, x0, y1, lineWidth, x, y) || containStroke(x0, y1, x0, y0, lineWidth, x, y)) {
              return true;
            }
          } else {
            w += windingLine(x1, y0, x1, y1, x, y);
            w += windingLine(x0, y1, x0, y0, x, y);
          }

          break;

        case CMD$1.Z:
          if (isStroke) {
            if (containStroke(xi, yi, x0, y0, lineWidth, x, y)) {
              return true;
            }
          } else {
            w += windingLine(xi, yi, x0, y0, x, y);
          }

          xi = x0;
          yi = y0;
          break;
      }
    }

    if (!isStroke && !isAroundEqual(yi, y0)) {
      w += windingLine(xi, yi, x0, y0, x, y) || 0;
    }

    return w !== 0;
  }

  function contain(pathProxy, x, y) {
    return containPath(pathProxy, 0, false, x, y);
  }

  function containStroke$4(pathProxy, lineWidth, x, y) {
    return containPath(pathProxy, lineWidth, true, x, y);
  }

  var DEFAULT_PATH_STYLE = defaults({
    fill: '#000',
    stroke: null,
    strokePercent: 1,
    fillOpacity: 1,
    strokeOpacity: 1,
    lineDashOffset: 0,
    lineWidth: 1,
    lineCap: 'butt',
    miterLimit: 10,
    strokeNoScale: false,
    strokeFirst: false
  }, DEFAULT_COMMON_STYLE);
  var DEFAULT_PATH_ANIMATION_PROPS = {
    style: defaults({
      fill: true,
      stroke: true,
      strokePercent: true,
      fillOpacity: true,
      strokeOpacity: true,
      lineDashOffset: true,
      lineWidth: true,
      miterLimit: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
  };
  var pathCopyParams = ['x', 'y', 'rotation', 'scaleX', 'scaleY', 'originX', 'originY', 'invisible', 'culling', 'z', 'z2', 'zlevel', 'parent'];

  var Path = function (_super) {
    __extends(Path, _super);

    function Path(opts) {
      return _super.call(this, opts) || this;
    }

    Path.prototype.update = function () {
      var _this = this;

      _super.prototype.update.call(this);

      var style = this.style;

      if (style.decal) {
        var decalEl = this._decalEl = this._decalEl || new Path();

        if (decalEl.buildPath === Path.prototype.buildPath) {
          decalEl.buildPath = function (ctx) {
            _this.buildPath(ctx, _this.shape);
          };
        }

        decalEl.silent = true;
        var decalElStyle = decalEl.style;

        for (var key in style) {
          if (decalElStyle[key] !== style[key]) {
            decalElStyle[key] = style[key];
          }
        }

        decalElStyle.fill = style.fill ? style.decal : null;
        decalElStyle.decal = null;
        decalElStyle.shadowColor = null;
        style.strokeFirst && (decalElStyle.stroke = null);

        for (var i = 0; i < pathCopyParams.length; ++i) {
          decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
        }

        decalEl.__dirty |= Element.REDARAW_BIT;
      } else if (this._decalEl) {
        this._decalEl = null;
      }
    };

    Path.prototype.getDecalElement = function () {
      return this._decalEl;
    };

    Path.prototype._init = function (props) {
      var keysArr = keys(props);
      this.shape = this.getDefaultShape();
      var defaultStyle = this.getDefaultStyle();

      if (defaultStyle) {
        this.useStyle(defaultStyle);
      }

      for (var i = 0; i < keysArr.length; i++) {
        var key = keysArr[i];
        var value = props[key];

        if (key === 'style') {
          if (!this.style) {
            this.useStyle(value);
          } else {
            extend(this.style, value);
          }
        } else if (key === 'shape') {
          extend(this.shape, value);
        } else {
          _super.prototype.attrKV.call(this, key, value);
        }
      }

      if (!this.style) {
        this.useStyle({});
      }
    };

    Path.prototype.getDefaultStyle = function () {
      return null;
    };

    Path.prototype.getDefaultShape = function () {
      return {};
    };

    Path.prototype.canBeInsideText = function () {
      return this.hasFill();
    };

    Path.prototype.getInsideTextFill = function () {
      var pathFill = this.style.fill;

      if (pathFill !== 'none') {
        if (isString(pathFill)) {
          var fillLum = lum(pathFill, 0);

          if (fillLum > 0.5) {
            return DARK_LABEL_COLOR;
          } else if (fillLum > 0.2) {
            return LIGHTER_LABEL_COLOR;
          }

          return LIGHT_LABEL_COLOR;
        } else if (pathFill) {
          return LIGHT_LABEL_COLOR;
        }
      }

      return DARK_LABEL_COLOR;
    };

    Path.prototype.getInsideTextStroke = function (textFill) {
      var pathFill = this.style.fill;

      if (isString(pathFill)) {
        var zr = this.__zr;
        var isDarkMode = !!(zr && zr.isDarkMode());
        var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD;

        if (isDarkMode === isDarkLabel) {
          return pathFill;
        }
      }
    };

    Path.prototype.buildPath = function (ctx, shapeCfg, inBundle) {};

    Path.prototype.pathUpdated = function () {
      this.__dirty &= ~Path.SHAPE_CHANGED_BIT;
    };

    Path.prototype.createPathProxy = function () {
      this.path = new PathProxy(false);
    };

    Path.prototype.hasStroke = function () {
      var style = this.style;
      var stroke = style.stroke;
      return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
    };

    Path.prototype.hasFill = function () {
      var style = this.style;
      var fill = style.fill;
      return fill != null && fill !== 'none';
    };

    Path.prototype.getBoundingRect = function () {
      var rect = this._rect;
      var style = this.style;
      var needsUpdateRect = !rect;

      if (needsUpdateRect) {
        var firstInvoke = false;

        if (!this.path) {
          firstInvoke = true;
          this.createPathProxy();
        }

        var path = this.path;

        if (firstInvoke || this.__dirty & Path.SHAPE_CHANGED_BIT) {
          path.beginPath();
          this.buildPath(path, this.shape, false);
          this.pathUpdated();
        }

        rect = path.getBoundingRect();
      }

      this._rect = rect;

      if (this.hasStroke() && this.path && this.path.len() > 0) {
        var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone());

        if (this.__dirty || needsUpdateRect) {
          rectWithStroke.copy(rect);
          var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
          var w = style.lineWidth;

          if (!this.hasFill()) {
            var strokeContainThreshold = this.strokeContainThreshold;
            w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold);
          }

          if (lineScale > 1e-10) {
            rectWithStroke.width += w / lineScale;
            rectWithStroke.height += w / lineScale;
            rectWithStroke.x -= w / lineScale / 2;
            rectWithStroke.y -= w / lineScale / 2;
          }
        }

        return rectWithStroke;
      }

      return rect;
    };

    Path.prototype.contain = function (x, y) {
      var localPos = this.transformCoordToLocal(x, y);
      var rect = this.getBoundingRect();
      var style = this.style;
      x = localPos[0];
      y = localPos[1];

      if (rect.contain(x, y)) {
        var pathProxy = this.path;

        if (this.hasStroke()) {
          var lineWidth = style.lineWidth;
          var lineScale = style.strokeNoScale ? this.getLineScale() : 1;

          if (lineScale > 1e-10) {
            if (!this.hasFill()) {
              lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
            }

            if (containStroke$4(pathProxy, lineWidth / lineScale, x, y)) {
              return true;
            }
          }
        }

        if (this.hasFill()) {
          return contain(pathProxy, x, y);
        }
      }

      return false;
    };

    Path.prototype.dirtyShape = function () {
      this.__dirty |= Path.SHAPE_CHANGED_BIT;

      if (this._rect) {
        this._rect = null;
      }

      if (this._decalEl) {
        this._decalEl.dirtyShape();
      }

      this.markRedraw();
    };

    Path.prototype.dirty = function () {
      this.dirtyStyle();
      this.dirtyShape();
    };

    Path.prototype.animateShape = function (loop) {
      return this.animate('shape', loop);
    };

    Path.prototype.updateDuringAnimation = function (targetKey) {
      if (targetKey === 'style') {
        this.dirtyStyle();
      } else if (targetKey === 'shape') {
        this.dirtyShape();
      } else {
        this.markRedraw();
      }
    };

    Path.prototype.attrKV = function (key, value) {
      if (key === 'shape') {
        this.setShape(value);
      } else {
        _super.prototype.attrKV.call(this, key, value);
      }
    };

    Path.prototype.setShape = function (keyOrObj, value) {
      var shape = this.shape;

      if (!shape) {
        shape = this.shape = {};
      }

      if (typeof keyOrObj === 'string') {
        shape[keyOrObj] = value;
      } else {
        extend(shape, keyOrObj);
      }

      this.dirtyShape();
      return this;
    };

    Path.prototype.shapeChanged = function () {
      return !!(this.__dirty & Path.SHAPE_CHANGED_BIT);
    };

    Path.prototype.createStyle = function (obj) {
      return createObject(DEFAULT_PATH_STYLE, obj);
    };

    Path.prototype._innerSaveToNormal = function (toState) {
      _super.prototype._innerSaveToNormal.call(this, toState);

      var normalState = this._normalState;

      if (toState.shape && !normalState.shape) {
        normalState.shape = extend({}, this.shape);
      }
    };

    Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
      _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);

      var needsRestoreToNormal = !(state && keepCurrentStates);
      var targetShape;

      if (state && state.shape) {
        if (transition) {
          if (keepCurrentStates) {
            targetShape = state.shape;
          } else {
            targetShape = extend({}, normalState.shape);
            extend(targetShape, state.shape);
          }
        } else {
          targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape);
          extend(targetShape, state.shape);
        }
      } else if (needsRestoreToNormal) {
        targetShape = normalState.shape;
      }

      if (targetShape) {
        if (transition) {
          this.shape = extend({}, this.shape);
          var targetShapePrimaryProps = {};
          var shapeKeys = keys(targetShape);

          for (var i = 0; i < shapeKeys.length; i++) {
            var key = shapeKeys[i];

            if (typeof targetShape[key] === 'object') {
              this.shape[key] = targetShape[key];
            } else {
              targetShapePrimaryProps[key] = targetShape[key];
            }
          }

          this._transitionState(stateName, {
            shape: targetShapePrimaryProps
          }, animationCfg);
        } else {
          this.shape = targetShape;
          this.dirtyShape();
        }
      }
    };

    Path.prototype._mergeStates = function (states) {
      var mergedState = _super.prototype._mergeStates.call(this, states);

      var mergedShape;

      for (var i = 0; i < states.length; i++) {
        var state = states[i];

        if (state.shape) {
          mergedShape = mergedShape || {};

          this._mergeStyle(mergedShape, state.shape);
        }
      }

      if (mergedShape) {
        mergedState.shape = mergedShape;
      }

      return mergedState;
    };

    Path.prototype.getAnimationStyleProps = function () {
      return DEFAULT_PATH_ANIMATION_PROPS;
    };

    Path.prototype.isZeroArea = function () {
      return false;
    };

    Path.extend = function (defaultProps) {
      var Sub = function (_super) {
        __extends(Sub, _super);

        function Sub(opts) {
          var _this = _super.call(this, opts) || this;

          defaultProps.init && defaultProps.init.call(_this, opts);
          return _this;
        }

        Sub.prototype.getDefaultStyle = function () {
          return clone(defaultProps.style);
        };

        Sub.prototype.getDefaultShape = function () {
          return clone(defaultProps.shape);
        };

        return Sub;
      }(Path);

      for (var key in defaultProps) {
        if (typeof defaultProps[key] === 'function') {
          Sub.prototype[key] = defaultProps[key];
        }
      }

      return Sub;
    };

    Path.SHAPE_CHANGED_BIT = 4;

    Path.initDefaultProps = function () {
      var pathProto = Path.prototype;
      pathProto.type = 'path';
      pathProto.strokeContainThreshold = 5;
      pathProto.segmentIgnoreThreshold = 0;
      pathProto.subPixelOptimize = false;
      pathProto.autoBatch = false;
      pathProto.__dirty = Element.REDARAW_BIT | Displayable.STYLE_CHANGED_BIT | Path.SHAPE_CHANGED_BIT;
    }();

    return Path;
  }(Displayable);

  var CMD$2 = PathProxy.CMD;
  var points = [[], [], []];
  var mathSqrt$2 = Math.sqrt;
  var mathAtan2 = Math.atan2;

  function transformPath(path, m) {
    var data = path.data;
    var len = path.len();
    var cmd;
    var nPoint;
    var i;
    var j;
    var k;
    var p;
    var M = CMD$2.M;
    var C = CMD$2.C;
    var L = CMD$2.L;
    var R = CMD$2.R;
    var A = CMD$2.A;
    var Q = CMD$2.Q;

    for (i = 0, j = 0; i < len;) {
      cmd = data[i++];
      j = i;
      nPoint = 0;

      switch (cmd) {
        case M:
          nPoint = 1;
          break;

        case L:
          nPoint = 1;
          break;

        case C:
          nPoint = 3;
          break;

        case Q:
          nPoint = 2;
          break;

        case A:
          var x = m[4];
          var y = m[5];
          var sx = mathSqrt$2(m[0] * m[0] + m[1] * m[1]);
          var sy = mathSqrt$2(m[2] * m[2] + m[3] * m[3]);
          var angle = mathAtan2(-m[1] / sy, m[0] / sx);
          data[i] *= sx;
          data[i++] += x;
          data[i] *= sy;
          data[i++] += y;
          data[i++] *= sx;
          data[i++] *= sy;
          data[i++] += angle;
          data[i++] += angle;
          i += 2;
          j = i;
          break;

        case R:
          p[0] = data[i++];
          p[1] = data[i++];
          applyTransform(p, p, m);
          data[j++] = p[0];
          data[j++] = p[1];
          p[0] += data[i++];
          p[1] += data[i++];
          applyTransform(p, p, m);
          data[j++] = p[0];
          data[j++] = p[1];
      }

      for (k = 0; k < nPoint; k++) {
        var p_1 = points[k];
        p_1[0] = data[i++];
        p_1[1] = data[i++];
        applyTransform(p_1, p_1, m);
        data[j++] = p_1[0];
        data[j++] = p_1[1];
      }
    }

    path.increaseVersion();
  }

  var mathSqrt$3 = Math.sqrt;
  var mathSin$2 = Math.sin;
  var mathCos$2 = Math.cos;
  var PI$1 = Math.PI;

  function vMag(v) {
    return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
  }

  function vRatio(u, v) {
    return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
  }

  function vAngle(u, v) {
    return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v));
  }

  function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
    var psi = psiDeg * (PI$1 / 180.0);
    var xp = mathCos$2(psi) * (x1 - x2) / 2.0 + mathSin$2(psi) * (y1 - y2) / 2.0;
    var yp = -1 * mathSin$2(psi) * (x1 - x2) / 2.0 + mathCos$2(psi) * (y1 - y2) / 2.0;
    var lambda = xp * xp / (rx * rx) + yp * yp / (ry * ry);

    if (lambda > 1) {
      rx *= mathSqrt$3(lambda);
      ry *= mathSqrt$3(lambda);
    }

    var f = (fa === fs ? -1 : 1) * mathSqrt$3((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (yp * yp) + ry * ry * (xp * xp))) || 0;
    var cxp = f * rx * yp / ry;
    var cyp = f * -ry * xp / rx;
    var cx = (x1 + x2) / 2.0 + mathCos$2(psi) * cxp - mathSin$2(psi) * cyp;
    var cy = (y1 + y2) / 2.0 + mathSin$2(psi) * cxp + mathCos$2(psi) * cyp;
    var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]);
    var u = [(xp - cxp) / rx, (yp - cyp) / ry];
    var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
    var dTheta = vAngle(u, v);

    if (vRatio(u, v) <= -1) {
      dTheta = PI$1;
    }

    if (vRatio(u, v) >= 1) {
      dTheta = 0;
    }

    if (dTheta < 0) {
      var n = Math.round(dTheta / PI$1 * 1e6) / 1e6;
      dTheta = PI$1 * 2 + n % 2 * PI$1;
    }

    path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
  }

  var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;
  var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;

  function createPathProxyFromString(data) {
    if (!data) {
      return new PathProxy();
    }

    var cpx = 0;
    var cpy = 0;
    var subpathX = cpx;
    var subpathY = cpy;
    var prevCmd;
    var path = new PathProxy();
    var CMD = PathProxy.CMD;
    var cmdList = data.match(commandReg);

    for (var l = 0; l < cmdList.length; l++) {
      var cmdText = cmdList[l];
      var cmdStr = cmdText.charAt(0);
      var cmd = void 0;
      var p = cmdText.match(numberReg) || [];
      var pLen = p.length;

      for (var i = 0; i < pLen; i++) {
        p[i] = parseFloat(p[i]);
      }

      var off = 0;

      while (off < pLen) {
        var ctlPtx = void 0;
        var ctlPty = void 0;
        var rx = void 0;
        var ry = void 0;
        var psi = void 0;
        var fa = void 0;
        var fs = void 0;
        var x1 = cpx;
        var y1 = cpy;
        var len = void 0;
        var pathData = void 0;

        switch (cmdStr) {
          case 'l':
            cpx += p[off++];
            cpy += p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'L':
            cpx = p[off++];
            cpy = p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'm':
            cpx += p[off++];
            cpy += p[off++];
            cmd = CMD.M;
            path.addData(cmd, cpx, cpy);
            subpathX = cpx;
            subpathY = cpy;
            cmdStr = 'l';
            break;

          case 'M':
            cpx = p[off++];
            cpy = p[off++];
            cmd = CMD.M;
            path.addData(cmd, cpx, cpy);
            subpathX = cpx;
            subpathY = cpy;
            cmdStr = 'L';
            break;

          case 'h':
            cpx += p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'H':
            cpx = p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'v':
            cpy += p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'V':
            cpy = p[off++];
            cmd = CMD.L;
            path.addData(cmd, cpx, cpy);
            break;

          case 'C':
            cmd = CMD.C;
            path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]);
            cpx = p[off - 2];
            cpy = p[off - 1];
            break;

          case 'c':
            cmd = CMD.C;
            path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy);
            cpx += p[off - 2];
            cpy += p[off - 1];
            break;

          case 'S':
            ctlPtx = cpx;
            ctlPty = cpy;
            len = path.len();
            pathData = path.data;

            if (prevCmd === CMD.C) {
              ctlPtx += cpx - pathData[len - 4];
              ctlPty += cpy - pathData[len - 3];
            }

            cmd = CMD.C;
            x1 = p[off++];
            y1 = p[off++];
            cpx = p[off++];
            cpy = p[off++];
            path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
            break;

          case 's':
            ctlPtx = cpx;
            ctlPty = cpy;
            len = path.len();
            pathData = path.data;

            if (prevCmd === CMD.C) {
              ctlPtx += cpx - pathData[len - 4];
              ctlPty += cpy - pathData[len - 3];
            }

            cmd = CMD.C;
            x1 = cpx + p[off++];
            y1 = cpy + p[off++];
            cpx += p[off++];
            cpy += p[off++];
            path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
            break;

          case 'Q':
            x1 = p[off++];
            y1 = p[off++];
            cpx = p[off++];
            cpy = p[off++];
            cmd = CMD.Q;
            path.addData(cmd, x1, y1, cpx, cpy);
            break;

          case 'q':
            x1 = p[off++] + cpx;
            y1 = p[off++] + cpy;
            cpx += p[off++];
            cpy += p[off++];
            cmd = CMD.Q;
            path.addData(cmd, x1, y1, cpx, cpy);
            break;

          case 'T':
            ctlPtx = cpx;
            ctlPty = cpy;
            len = path.len();
            pathData = path.data;

            if (prevCmd === CMD.Q) {
              ctlPtx += cpx - pathData[len - 4];
              ctlPty += cpy - pathData[len - 3];
            }

            cpx = p[off++];
            cpy = p[off++];
            cmd = CMD.Q;
            path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
            break;

          case 't':
            ctlPtx = cpx;
            ctlPty = cpy;
            len = path.len();
            pathData = path.data;

            if (prevCmd === CMD.Q) {
              ctlPtx += cpx - pathData[len - 4];
              ctlPty += cpy - pathData[len - 3];
            }

            cpx += p[off++];
            cpy += p[off++];
            cmd = CMD.Q;
            path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
            break;

          case 'A':
            rx = p[off++];
            ry = p[off++];
            psi = p[off++];
            fa = p[off++];
            fs = p[off++];
            x1 = cpx, y1 = cpy;
            cpx = p[off++];
            cpy = p[off++];
            cmd = CMD.A;
            processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
            break;

          case 'a':
            rx = p[off++];
            ry = p[off++];
            psi = p[off++];
            fa = p[off++];
            fs = p[off++];
            x1 = cpx, y1 = cpy;
            cpx += p[off++];
            cpy += p[off++];
            cmd = CMD.A;
            processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
            break;
        }
      }

      if (cmdStr === 'z' || cmdStr === 'Z') {
        cmd = CMD.Z;
        path.addData(cmd);
        cpx = subpathX;
        cpy = subpathY;
      }

      prevCmd = cmd;
    }

    path.toStatic();
    return path;
  }

  var SVGPath = function (_super) {
    __extends(SVGPath, _super);

    function SVGPath() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    SVGPath.prototype.applyTransform = function (m) {};

    return SVGPath;
  }(Path);

  function isPathProxy(path) {
    return path.setData != null;
  }

  function createPathOptions(str, opts) {
    var pathProxy = createPathProxyFromString(str);
    var innerOpts = extend({}, opts);

    innerOpts.buildPath = function (path) {
      if (isPathProxy(path)) {
        path.setData(pathProxy.data);
        var ctx = path.getContext();

        if (ctx) {
          path.rebuildPath(ctx, 1);
        }
      } else {
        var ctx = path;
        pathProxy.rebuildPath(ctx, 1);
      }
    };

    innerOpts.applyTransform = function (m) {
      transformPath(pathProxy, m);
      this.dirtyShape();
    };

    return innerOpts;
  }

  function createFromString(str, opts) {
    return new SVGPath(createPathOptions(str, opts));
  }

  function extendFromString(str, defaultOpts) {
    var innerOpts = createPathOptions(str, defaultOpts);

    var Sub = function (_super) {
      __extends(Sub, _super);

      function Sub(opts) {
        var _this = _super.call(this, opts) || this;

        _this.applyTransform = innerOpts.applyTransform;
        _this.buildPath = innerOpts.buildPath;
        return _this;
      }

      return Sub;
    }(SVGPath);

    return Sub;
  }

  function mergePath(pathEls, opts) {
    var pathList = [];
    var len = pathEls.length;

    for (var i = 0; i < len; i++) {
      var pathEl = pathEls[i];

      if (!pathEl.path) {
        pathEl.createPathProxy();
      }

      if (pathEl.shapeChanged()) {
        pathEl.buildPath(pathEl.path, pathEl.shape, true);
      }

      pathList.push(pathEl.path);
    }

    var pathBundle = new Path(opts);
    pathBundle.createPathProxy();

    pathBundle.buildPath = function (path) {
      if (isPathProxy(path)) {
        path.appendPath(pathList);
        var ctx = path.getContext();

        if (ctx) {
          path.rebuildPath(ctx, 1);
        }
      }
    };

    return pathBundle;
  }

  var Group = function (_super) {
    __extends(Group, _super);

    function Group(opts) {
      var _this = _super.call(this) || this;

      _this.isGroup = true;
      _this._children = [];

      _this.attr(opts);

      return _this;
    }

    Group.prototype.childrenRef = function () {
      return this._children;
    };

    Group.prototype.children = function () {
      return this._children.slice();
    };

    Group.prototype.childAt = function (idx) {
      return this._children[idx];
    };

    Group.prototype.childOfName = function (name) {
      var children = this._children;

      for (var i = 0; i < children.length; i++) {
        if (children[i].name === name) {
          return children[i];
        }
      }
    };

    Group.prototype.childCount = function () {
      return this._children.length;
    };

    Group.prototype.add = function (child) {
      if (child) {
        if (child !== this && child.parent !== this) {
          this._children.push(child);

          this._doAdd(child);
        }

        if (child.__hostTarget) {
          throw 'This elemenet has been used as an attachment';
        }
      }

      return this;
    };

    Group.prototype.addBefore = function (child, nextSibling) {
      if (child && child !== this && child.parent !== this && nextSibling && nextSibling.parent === this) {
        var children = this._children;
        var idx = children.indexOf(nextSibling);

        if (idx >= 0) {
          children.splice(idx, 0, child);

          this._doAdd(child);
        }
      }

      return this;
    };

    Group.prototype.replaceAt = function (child, index) {
      var children = this._children;
      var old = children[index];

      if (child && child !== this && child.parent !== this && child !== old) {
        children[index] = child;
        old.parent = null;
        var zr = this.__zr;

        if (zr) {
          old.removeSelfFromZr(zr);
        }

        this._doAdd(child);
      }

      return this;
    };

    Group.prototype._doAdd = function (child) {
      if (child.parent) {
        child.parent.remove(child);
      }

      child.parent = this;
      var zr = this.__zr;

      if (zr && zr !== child.__zr) {
        child.addSelfToZr(zr);
      }

      zr && zr.refresh();
    };

    Group.prototype.remove = function (child) {
      var zr = this.__zr;
      var children = this._children;
      var idx = indexOf(children, child);

      if (idx < 0) {
        return this;
      }

      children.splice(idx, 1);
      child.parent = null;

      if (zr) {
        child.removeSelfFromZr(zr);
      }

      zr && zr.refresh();
      return this;
    };

    Group.prototype.removeAll = function () {
      var children = this._children;
      var zr = this.__zr;

      for (var i = 0; i < children.length; i++) {
        var child = children[i];

        if (zr) {
          child.removeSelfFromZr(zr);
        }

        child.parent = null;
      }

      children.length = 0;
      return this;
    };

    Group.prototype.eachChild = function (cb, context) {
      var children = this._children;

      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        cb.call(context, child, i);
      }

      return this;
    };

    Group.prototype.traverse = function (cb, context) {
      for (var i = 0; i < this._children.length; i++) {
        var child = this._children[i];
        var stopped = cb.call(context, child);

        if (child.isGroup && !stopped) {
          child.traverse(cb, context);
        }
      }

      return this;
    };

    Group.prototype.addSelfToZr = function (zr) {
      _super.prototype.addSelfToZr.call(this, zr);

      for (var i = 0; i < this._children.length; i++) {
        var child = this._children[i];
        child.addSelfToZr(zr);
      }
    };

    Group.prototype.removeSelfFromZr = function (zr) {
      _super.prototype.removeSelfFromZr.call(this, zr);

      for (var i = 0; i < this._children.length; i++) {
        var child = this._children[i];
        child.removeSelfFromZr(zr);
      }
    };

    Group.prototype.getBoundingRect = function (includeChildren) {
      var tmpRect = new BoundingRect(0, 0, 0, 0);
      var children = includeChildren || this._children;
      var tmpMat = [];
      var rect = null;

      for (var i = 0; i < children.length; i++) {
        var child = children[i];

        if (child.ignore || child.invisible) {
          continue;
        }

        var childRect = child.getBoundingRect();
        var transform = child.getLocalTransform(tmpMat);

        if (transform) {
          BoundingRect.applyTransform(tmpRect, childRect, transform);
          rect = rect || tmpRect.clone();
          rect.union(tmpRect);
        } else {
          rect = rect || childRect.clone();
          rect.union(childRect);
        }
      }

      return rect || tmpRect;
    };

    return Group;
  }(Element);

  Group.prototype.type = 'group';
  var DEFAULT_IMAGE_STYLE = defaults({
    x: 0,
    y: 0
  }, DEFAULT_COMMON_STYLE);
  var DEFAULT_IMAGE_ANIMATION_PROPS = {
    style: defaults({
      x: true,
      y: true,
      width: true,
      height: true,
      sx: true,
      sy: true,
      sWidth: true,
      sHeight: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
  };

  function isImageLike(source) {
    return !!(source && typeof source !== 'string' && source.width && source.height);
  }

  var ZRImage = function (_super) {
    __extends(ZRImage, _super);

    function ZRImage() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    ZRImage.prototype.createStyle = function (obj) {
      return createObject(DEFAULT_IMAGE_STYLE, obj);
    };

    ZRImage.prototype._getSize = function (dim) {
      var style = this.style;
      var size = style[dim];

      if (size != null) {
        return size;
      }

      var imageSource = isImageLike(style.image) ? style.image : this.__image;

      if (!imageSource) {
        return 0;
      }

      var otherDim = dim === 'width' ? 'height' : 'width';
      var otherDimSize = style[otherDim];

      if (otherDimSize == null) {
        return imageSource[dim];
      } else {
        return imageSource[dim] / imageSource[otherDim] * otherDimSize;
      }
    };

    ZRImage.prototype.getWidth = function () {
      return this._getSize('width');
    };

    ZRImage.prototype.getHeight = function () {
      return this._getSize('height');
    };

    ZRImage.prototype.getAnimationStyleProps = function () {
      return DEFAULT_IMAGE_ANIMATION_PROPS;
    };

    ZRImage.prototype.getBoundingRect = function () {
      var style = this.style;

      if (!this._rect) {
        this._rect = new BoundingRect(style.x || 0, style.y || 0, this.getWidth(), this.getHeight());
      }

      return this._rect;
    };

    return ZRImage;
  }(Displayable);

  ZRImage.prototype.type = 'image';

  var CircleShape = function () {
    function CircleShape() {
      this.cx = 0;
      this.cy = 0;
      this.r = 0;
    }

    return CircleShape;
  }();

  var Circle = function (_super) {
    __extends(Circle, _super);

    function Circle(opts) {
      return _super.call(this, opts) || this;
    }

    Circle.prototype.getDefaultShape = function () {
      return new CircleShape();
    };

    Circle.prototype.buildPath = function (ctx, shape, inBundle) {
      if (inBundle) {
        ctx.moveTo(shape.cx + shape.r, shape.cy);
      }

      ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);
    };

    return Circle;
  }(Path);

  Circle.prototype.type = 'circle';

  function buildPath(ctx, shape) {
    var x = shape.x;
    var y = shape.y;
    var width = shape.width;
    var height = shape.height;
    var r = shape.r;
    var r1;
    var r2;
    var r3;
    var r4;

    if (width < 0) {
      x = x + width;
      width = -width;
    }

    if (height < 0) {
      y = y + height;
      height = -height;
    }

    if (typeof r === 'number') {
      r1 = r2 = r3 = r4 = r;
    } else if (r instanceof Array) {
      if (r.length === 1) {
        r1 = r2 = r3 = r4 = r[0];
      } else if (r.length === 2) {
        r1 = r3 = r[0];
        r2 = r4 = r[1];
      } else if (r.length === 3) {
        r1 = r[0];
        r2 = r4 = r[1];
        r3 = r[2];
      } else {
        r1 = r[0];
        r2 = r[1];
        r3 = r[2];
        r4 = r[3];
      }
    } else {
      r1 = r2 = r3 = r4 = 0;
    }

    var total;

    if (r1 + r2 > width) {
      total = r1 + r2;
      r1 *= width / total;
      r2 *= width / total;
    }

    if (r3 + r4 > width) {
      total = r3 + r4;
      r3 *= width / total;
      r4 *= width / total;
    }

    if (r2 + r3 > height) {
      total = r2 + r3;
      r2 *= height / total;
      r3 *= height / total;
    }

    if (r1 + r4 > height) {
      total = r1 + r4;
      r1 *= height / total;
      r4 *= height / total;
    }

    ctx.moveTo(x + r1, y);
    ctx.lineTo(x + width - r2, y);
    r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r3);
    r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2);
    ctx.lineTo(x + r4, y + height);
    r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r1);
    r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5);
  }

  var round = Math.round;

  function subPixelOptimizeLine(outputShape, inputShape, style) {
    if (!inputShape) {
      return;
    }

    var x1 = inputShape.x1;
    var x2 = inputShape.x2;
    var y1 = inputShape.y1;
    var y2 = inputShape.y2;
    outputShape.x1 = x1;
    outputShape.x2 = x2;
    outputShape.y1 = y1;
    outputShape.y2 = y2;
    var lineWidth = style && style.lineWidth;

    if (!lineWidth) {
      return outputShape;
    }

    if (round(x1 * 2) === round(x2 * 2)) {
      outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true);
    }

    if (round(y1 * 2) === round(y2 * 2)) {
      outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true);
    }

    return outputShape;
  }

  function subPixelOptimizeRect(outputShape, inputShape, style) {
    if (!inputShape) {
      return;
    }

    var originX = inputShape.x;
    var originY = inputShape.y;
    var originWidth = inputShape.width;
    var originHeight = inputShape.height;
    outputShape.x = originX;
    outputShape.y = originY;
    outputShape.width = originWidth;
    outputShape.height = originHeight;
    var lineWidth = style && style.lineWidth;

    if (!lineWidth) {
      return outputShape;
    }

    outputShape.x = subPixelOptimize(originX, lineWidth, true);
    outputShape.y = subPixelOptimize(originY, lineWidth, true);
    outputShape.width = Math.max(subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1);
    outputShape.height = Math.max(subPixelOptimize(originY + originHeight, lineWidth, false) - outputShape.y, originHeight === 0 ? 0 : 1);
    return outputShape;
  }

  function subPixelOptimize(position, lineWidth, positiveOrNegative) {
    if (!lineWidth) {
      return position;
    }

    var doubledPosition = round(position * 2);
    return (doubledPosition + round(lineWidth)) % 2 === 0 ? doubledPosition / 2 : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
  }

  var RectShape = function () {
    function RectShape() {
      this.x = 0;
      this.y = 0;
      this.width = 0;
      this.height = 0;
    }

    return RectShape;
  }();

  var subPixelOptimizeOutputShape = {};

  var Rect = function (_super) {
    __extends(Rect, _super);

    function Rect(opts) {
      return _super.call(this, opts) || this;
    }

    Rect.prototype.getDefaultShape = function () {
      return new RectShape();
    };

    Rect.prototype.buildPath = function (ctx, shape) {
      var x;
      var y;
      var width;
      var height;

      if (this.subPixelOptimize) {
        var optimizedShape = subPixelOptimizeRect(subPixelOptimizeOutputShape, shape, this.style);
        x = optimizedShape.x;
        y = optimizedShape.y;
        width = optimizedShape.width;
        height = optimizedShape.height;
        optimizedShape.r = shape.r;
        shape = optimizedShape;
      } else {
        x = shape.x;
        y = shape.y;
        width = shape.width;
        height = shape.height;
      }

      if (!shape.r) {
        ctx.rect(x, y, width, height);
      } else {
        buildPath(ctx, shape);
      }
    };

    Rect.prototype.isZeroArea = function () {
      return !this.shape.width || !this.shape.height;
    };

    return Rect;
  }(Path);

  Rect.prototype.type = 'rect';

  var EllipseShape = function () {
    function EllipseShape() {
      this.cx = 0;
      this.cy = 0;
      this.rx = 0;
      this.ry = 0;
    }

    return EllipseShape;
  }();

  var Ellipse = function (_super) {
    __extends(Ellipse, _super);

    function Ellipse(opts) {
      return _super.call(this, opts) || this;
    }

    Ellipse.prototype.getDefaultShape = function () {
      return new EllipseShape();
    };

    Ellipse.prototype.buildPath = function (ctx, shape) {
      var k = 0.5522848;
      var x = shape.cx;
      var y = shape.cy;
      var a = shape.rx;
      var b = shape.ry;
      var ox = a * k;
      var oy = b * k;
      ctx.moveTo(x - a, y);
      ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
      ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
      ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
      ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
      ctx.closePath();
    };

    return Ellipse;
  }(Path);

  Ellipse.prototype.type = 'ellipse';
  var subPixelOptimizeOutputShape$1 = {};

  var LineShape = function () {
    function LineShape() {
      this.x1 = 0;
      this.y1 = 0;
      this.x2 = 0;
      this.y2 = 0;
      this.percent = 1;
    }

    return LineShape;
  }();

  var Line = function (_super) {
    __extends(Line, _super);

    function Line(opts) {
      return _super.call(this, opts) || this;
    }

    Line.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    Line.prototype.getDefaultShape = function () {
      return new LineShape();
    };

    Line.prototype.buildPath = function (ctx, shape) {
      var x1;
      var y1;
      var x2;
      var y2;

      if (this.subPixelOptimize) {
        var optimizedShape = subPixelOptimizeLine(subPixelOptimizeOutputShape$1, shape, this.style);
        x1 = optimizedShape.x1;
        y1 = optimizedShape.y1;
        x2 = optimizedShape.x2;
        y2 = optimizedShape.y2;
      } else {
        x1 = shape.x1;
        y1 = shape.y1;
        x2 = shape.x2;
        y2 = shape.y2;
      }

      var percent = shape.percent;

      if (percent === 0) {
        return;
      }

      ctx.moveTo(x1, y1);

      if (percent < 1) {
        x2 = x1 * (1 - percent) + x2 * percent;
        y2 = y1 * (1 - percent) + y2 * percent;
      }

      ctx.lineTo(x2, y2);
    };

    Line.prototype.pointAt = function (p) {
      var shape = this.shape;
      return [shape.x1 * (1 - p) + shape.x2 * p, shape.y1 * (1 - p) + shape.y2 * p];
    };

    return Line;
  }(Path);

  Line.prototype.type = 'line';

  function interpolate(p0, p1, p2, p3, t, t2, t3) {
    var v0 = (p2 - p0) * 0.5;
    var v1 = (p3 - p1) * 0.5;
    return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1;
  }

  function smoothSpline(points, isLoop) {
    var len = points.length;
    var ret = [];
    var distance$1 = 0;

    for (var i = 1; i < len; i++) {
      distance$1 += distance(points[i - 1], points[i]);
    }

    var segs = distance$1 / 2;
    segs = segs < len ? len : segs;

    for (var i = 0; i < segs; i++) {
      var pos = i / (segs - 1) * (isLoop ? len : len - 1);
      var idx = Math.floor(pos);
      var w = pos - idx;
      var p0 = void 0;
      var p1 = points[idx % len];
      var p2 = void 0;
      var p3 = void 0;

      if (!isLoop) {
        p0 = points[idx === 0 ? idx : idx - 1];
        p2 = points[idx > len - 2 ? len - 1 : idx + 1];
        p3 = points[idx > len - 3 ? len - 1 : idx + 2];
      } else {
        p0 = points[(idx - 1 + len) % len];
        p2 = points[(idx + 1) % len];
        p3 = points[(idx + 2) % len];
      }

      var w2 = w * w;
      var w3 = w * w2;
      ret.push([interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3), interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3)]);
    }

    return ret;
  }

  function smoothBezier(points, smooth, isLoop, constraint) {
    var cps = [];
    var v = [];
    var v1 = [];
    var v2 = [];
    var prevPoint;
    var nextPoint;
    var min$1;
    var max$1;

    if (constraint) {
      min$1 = [Infinity, Infinity];
      max$1 = [-Infinity, -Infinity];

      for (var i = 0, len = points.length; i < len; i++) {
        min(min$1, min$1, points[i]);
        max(max$1, max$1, points[i]);
      }

      min(min$1, min$1, constraint[0]);
      max(max$1, max$1, constraint[1]);
    }

    for (var i = 0, len = points.length; i < len; i++) {
      var point = points[i];

      if (isLoop) {
        prevPoint = points[i ? i - 1 : len - 1];
        nextPoint = points[(i + 1) % len];
      } else {
        if (i === 0 || i === len - 1) {
          cps.push(clone$1(points[i]));
          continue;
        } else {
          prevPoint = points[i - 1];
          nextPoint = points[i + 1];
        }
      }

      sub(v, nextPoint, prevPoint);
      scale(v, v, smooth);
      var d0 = distance(point, prevPoint);
      var d1 = distance(point, nextPoint);
      var sum = d0 + d1;

      if (sum !== 0) {
        d0 /= sum;
        d1 /= sum;
      }

      scale(v1, v, -d0);
      scale(v2, v, d1);
      var cp0 = add([], point, v1);
      var cp1 = add([], point, v2);

      if (constraint) {
        max(cp0, cp0, min$1);
        min(cp0, cp0, max$1);
        max(cp1, cp1, min$1);
        min(cp1, cp1, max$1);
      }

      cps.push(cp0);
      cps.push(cp1);
    }

    if (isLoop) {
      cps.push(cps.shift());
    }

    return cps;
  }

  function buildPath$1(ctx, shape, closePath) {
    var smooth = shape.smooth;
    var points = shape.points;

    if (points && points.length >= 2) {
      if (smooth && smooth !== 'spline') {
        var controlPoints = smoothBezier(points, smooth, closePath, shape.smoothConstraint);
        ctx.moveTo(points[0][0], points[0][1]);
        var len = points.length;

        for (var i = 0; i < (closePath ? len : len - 1); i++) {
          var cp1 = controlPoints[i * 2];
          var cp2 = controlPoints[i * 2 + 1];
          var p = points[(i + 1) % len];
          ctx.bezierCurveTo(cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]);
        }
      } else {
        if (smooth === 'spline') {
          points = smoothSpline(points, closePath);
        }

        ctx.moveTo(points[0][0], points[0][1]);

        for (var i = 1, l = points.length; i < l; i++) {
          ctx.lineTo(points[i][0], points[i][1]);
        }
      }

      closePath && ctx.closePath();
    }
  }

  var PolygonShape = function () {
    function PolygonShape() {
      this.points = null;
      this.smooth = 0;
      this.smoothConstraint = null;
    }

    return PolygonShape;
  }();

  var Polygon = function (_super) {
    __extends(Polygon, _super);

    function Polygon(opts) {
      return _super.call(this, opts) || this;
    }

    Polygon.prototype.getDefaultShape = function () {
      return new PolygonShape();
    };

    Polygon.prototype.buildPath = function (ctx, shape) {
      buildPath$1(ctx, shape, true);
    };

    return Polygon;
  }(Path);

  Polygon.prototype.type = 'polygon';

  var PolylineShape = function () {
    function PolylineShape() {
      this.points = null;
      this.percent = 1;
      this.smooth = 0;
      this.smoothConstraint = null;
    }

    return PolylineShape;
  }();

  var Polyline = function (_super) {
    __extends(Polyline, _super);

    function Polyline(opts) {
      return _super.call(this, opts) || this;
    }

    Polyline.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    Polyline.prototype.getDefaultShape = function () {
      return new PolylineShape();
    };

    Polyline.prototype.buildPath = function (ctx, shape) {
      buildPath$1(ctx, shape, false);
    };

    return Polyline;
  }(Path);

  Polyline.prototype.type = 'polyline';

  var Gradient = function () {
    function Gradient(colorStops) {
      this.colorStops = colorStops || [];
    }

    Gradient.prototype.addColorStop = function (offset, color) {
      this.colorStops.push({
        offset: offset,
        color: color
      });
    };

    return Gradient;
  }();

  var LinearGradient = function (_super) {
    __extends(LinearGradient, _super);

    function LinearGradient(x, y, x2, y2, colorStops, globalCoord) {
      var _this = _super.call(this, colorStops) || this;

      _this.x = x == null ? 0 : x;
      _this.y = y == null ? 0 : y;
      _this.x2 = x2 == null ? 1 : x2;
      _this.y2 = y2 == null ? 0 : y2;
      _this.type = 'linear';
      _this.global = globalCoord || false;
      return _this;
    }

    return LinearGradient;
  }(Gradient);

  var DEFAULT_TSPAN_STYLE = defaults({
    strokeFirst: true,
    font: DEFAULT_FONT,
    x: 0,
    y: 0,
    textAlign: 'left',
    textBaseline: 'top',
    miterLimit: 2
  }, DEFAULT_PATH_STYLE);

  var TSpan = function (_super) {
    __extends(TSpan, _super);

    function TSpan() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    TSpan.prototype.hasStroke = function () {
      var style = this.style;
      var stroke = style.stroke;
      return stroke != null && stroke !== 'none' && style.lineWidth > 0;
    };

    TSpan.prototype.hasFill = function () {
      var style = this.style;
      var fill = style.fill;
      return fill != null && fill !== 'none';
    };

    TSpan.prototype.createStyle = function (obj) {
      return createObject(DEFAULT_TSPAN_STYLE, obj);
    };

    TSpan.prototype.setBoundingRect = function (rect) {
      this._rect = rect;
    };

    TSpan.prototype.getBoundingRect = function () {
      var style = this.style;

      if (!this._rect) {
        var text = style.text;
        text != null ? text += '' : text = '';
        var rect = getBoundingRect(text, style.font, style.textAlign, style.textBaseline);
        rect.x += style.x || 0;
        rect.y += style.y || 0;

        if (this.hasStroke()) {
          var w = style.lineWidth;
          rect.x -= w / 2;
          rect.y -= w / 2;
          rect.width += w;
          rect.height += w;
        }

        this._rect = rect;
      }

      return this._rect;
    };

    TSpan.initDefaultProps = function () {
      var tspanProto = TSpan.prototype;
      tspanProto.dirtyRectTolerance = 10;
    }();

    return TSpan;
  }(Displayable);

  TSpan.prototype.type = 'tspan';
  var DILIMITER_REG = /[\s,]+/;

  function parseXML(svg) {
    if (isString(svg)) {
      var parser = new DOMParser();
      svg = parser.parseFromString(svg, 'text/xml');
    }

    var svgNode = svg;

    if (svgNode.nodeType === 9) {
      svgNode = svgNode.firstChild;
    }

    while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
      svgNode = svgNode.nextSibling;
    }

    return svgNode;
  }

  var nodeParsers;

  var SVGParser = function () {
    function SVGParser() {
      this._defs = {};
      this._root = null;
      this._isDefine = false;
      this._isText = false;
    }

    SVGParser.prototype.parse = function (xml, opt) {
      opt = opt || {};
      var svg = parseXML(xml);

      if (!svg) {
        throw new Error('Illegal svg');
      }

      var root = new Group();
      this._root = root;
      var viewBox = svg.getAttribute('viewBox') || '';
      var width = parseFloat(svg.getAttribute('width') || opt.width);
      var height = parseFloat(svg.getAttribute('height') || opt.height);
      isNaN(width) && (width = null);
      isNaN(height) && (height = null);
      parseAttributes(svg, root, null, true);
      var child = svg.firstChild;

      while (child) {
        this._parseNode(child, root);

        child = child.nextSibling;
      }

      var viewBoxRect;
      var viewBoxTransform;

      if (viewBox) {
        var viewBoxArr = trim(viewBox).split(DILIMITER_REG);

        if (viewBoxArr.length >= 4) {
          viewBoxRect = {
            x: parseFloat(viewBoxArr[0] || 0),
            y: parseFloat(viewBoxArr[1] || 0),
            width: parseFloat(viewBoxArr[2]),
            height: parseFloat(viewBoxArr[3])
          };
        }
      }

      if (viewBoxRect && width != null && height != null) {
        viewBoxTransform = makeViewBoxTransform(viewBoxRect, width, height);

        if (!opt.ignoreViewBox) {
          var elRoot = root;
          root = new Group();
          root.add(elRoot);
          elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
          elRoot.x = viewBoxTransform.x;
          elRoot.y = viewBoxTransform.y;
        }
      }

      if (!opt.ignoreRootClip && width != null && height != null) {
        root.setClipPath(new Rect({
          shape: {
            x: 0,
            y: 0,
            width: width,
            height: height
          }
        }));
      }

      return {
        root: root,
        width: width,
        height: height,
        viewBoxRect: viewBoxRect,
        viewBoxTransform: viewBoxTransform
      };
    };

    SVGParser.prototype._parseNode = function (xmlNode, parentGroup) {
      var nodeName = xmlNode.nodeName.toLowerCase();

      if (nodeName === 'defs') {
        this._isDefine = true;
      } else if (nodeName === 'text') {
        this._isText = true;
      }

      var el;

      if (this._isDefine) {
        var parser = defineParsers[nodeName];

        if (parser) {
          var def = parser.call(this, xmlNode);
          var id = xmlNode.getAttribute('id');

          if (id) {
            this._defs[id] = def;
          }
        }
      } else {
        var parser = nodeParsers[nodeName];

        if (parser) {
          el = parser.call(this, xmlNode, parentGroup);
          parentGroup.add(el);
        }
      }

      if (el) {
        var child = xmlNode.firstChild;

        while (child) {
          if (child.nodeType === 1) {
            this._parseNode(child, el);
          }

          if (child.nodeType === 3 && this._isText) {
            this._parseText(child, el);
          }

          child = child.nextSibling;
        }
      }

      if (nodeName === 'defs') {
        this._isDefine = false;
      } else if (nodeName === 'text') {
        this._isText = false;
      }
    };

    SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
      if (xmlNode.nodeType === 1) {
        var dx = xmlNode.getAttribute('dx') || 0;
        var dy = xmlNode.getAttribute('dy') || 0;
        this._textX += parseFloat(dx);
        this._textY += parseFloat(dy);
      }

      var text = new TSpan({
        style: {
          text: xmlNode.textContent
        },
        x: this._textX || 0,
        y: this._textY || 0
      });
      inheritStyle(parentGroup, text);
      parseAttributes(xmlNode, text, this._defs);
      var textStyle = text.style;
      var fontSize = textStyle.fontSize;

      if (fontSize && fontSize < 9) {
        textStyle.fontSize = 9;
        text.scaleX *= fontSize / 9;
        text.scaleY *= fontSize / 9;
      }

      var font = (textStyle.fontSize || textStyle.fontFamily) && [textStyle.fontStyle, textStyle.fontWeight, (textStyle.fontSize || 12) + 'px', textStyle.fontFamily || 'sans-serif'].join(' ');
      textStyle.font = font;
      var rect = text.getBoundingRect();
      this._textX += rect.width;
      parentGroup.add(text);
      return text;
    };

    SVGParser.internalField = function () {
      nodeParsers = {
        'g': function (xmlNode, parentGroup) {
          var g = new Group();
          inheritStyle(parentGroup, g);
          parseAttributes(xmlNode, g, this._defs);
          return g;
        },
        'rect': function (xmlNode, parentGroup) {
          var rect = new Rect();
          inheritStyle(parentGroup, rect);
          parseAttributes(xmlNode, rect, this._defs);
          rect.setShape({
            x: parseFloat(xmlNode.getAttribute('x') || '0'),
            y: parseFloat(xmlNode.getAttribute('y') || '0'),
            width: parseFloat(xmlNode.getAttribute('width') || '0'),
            height: parseFloat(xmlNode.getAttribute('height') || '0')
          });
          return rect;
        },
        'circle': function (xmlNode, parentGroup) {
          var circle = new Circle();
          inheritStyle(parentGroup, circle);
          parseAttributes(xmlNode, circle, this._defs);
          circle.setShape({
            cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
            cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
            r: parseFloat(xmlNode.getAttribute('r') || '0')
          });
          return circle;
        },
        'line': function (xmlNode, parentGroup) {
          var line = new Line();
          inheritStyle(parentGroup, line);
          parseAttributes(xmlNode, line, this._defs);
          line.setShape({
            x1: parseFloat(xmlNode.getAttribute('x1') || '0'),
            y1: parseFloat(xmlNode.getAttribute('y1') || '0'),
            x2: parseFloat(xmlNode.getAttribute('x2') || '0'),
            y2: parseFloat(xmlNode.getAttribute('y2') || '0')
          });
          return line;
        },
        'ellipse': function (xmlNode, parentGroup) {
          var ellipse = new Ellipse();
          inheritStyle(parentGroup, ellipse);
          parseAttributes(xmlNode, ellipse, this._defs);
          ellipse.setShape({
            cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
            cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
            rx: parseFloat(xmlNode.getAttribute('rx') || '0'),
            ry: parseFloat(xmlNode.getAttribute('ry') || '0')
          });
          return ellipse;
        },
        'polygon': function (xmlNode, parentGroup) {
          var pointsStr = xmlNode.getAttribute('points');
          var pointsArr;

          if (pointsStr) {
            pointsArr = parsePoints(pointsStr);
          }

          var polygon = new Polygon({
            shape: {
              points: pointsArr || []
            }
          });
          inheritStyle(parentGroup, polygon);
          parseAttributes(xmlNode, polygon, this._defs);
          return polygon;
        },
        'polyline': function (xmlNode, parentGroup) {
          var path = new Path();
          inheritStyle(parentGroup, path);
          parseAttributes(xmlNode, path, this._defs);
          var pointsStr = xmlNode.getAttribute('points');
          var pointsArr;

          if (pointsStr) {
            pointsArr = parsePoints(pointsStr);
          }

          var polyline = new Polyline({
            shape: {
              points: pointsArr || []
            }
          });
          return polyline;
        },
        'image': function (xmlNode, parentGroup) {
          var img = new ZRImage();
          inheritStyle(parentGroup, img);
          parseAttributes(xmlNode, img, this._defs);
          img.setStyle({
            image: xmlNode.getAttribute('xlink:href'),
            x: +xmlNode.getAttribute('x'),
            y: +xmlNode.getAttribute('y'),
            width: +xmlNode.getAttribute('width'),
            height: +xmlNode.getAttribute('height')
          });
          return img;
        },
        'text': function (xmlNode, parentGroup) {
          var x = xmlNode.getAttribute('x') || '0';
          var y = xmlNode.getAttribute('y') || '0';
          var dx = xmlNode.getAttribute('dx') || '0';
          var dy = xmlNode.getAttribute('dy') || '0';
          this._textX = parseFloat(x) + parseFloat(dx);
          this._textY = parseFloat(y) + parseFloat(dy);
          var g = new Group();
          inheritStyle(parentGroup, g);
          parseAttributes(xmlNode, g, this._defs);
          return g;
        },
        'tspan': function (xmlNode, parentGroup) {
          var x = xmlNode.getAttribute('x');
          var y = xmlNode.getAttribute('y');

          if (x != null) {
            this._textX = parseFloat(x);
          }

          if (y != null) {
            this._textY = parseFloat(y);
          }

          var dx = xmlNode.getAttribute('dx') || 0;
          var dy = xmlNode.getAttribute('dy') || 0;
          var g = new Group();
          inheritStyle(parentGroup, g);
          parseAttributes(xmlNode, g, this._defs);
          this._textX += dx;
          this._textY += dy;
          return g;
        },
        'path': function (xmlNode, parentGroup) {
          var d = xmlNode.getAttribute('d') || '';
          var path = createFromString(d);
          inheritStyle(parentGroup, path);
          parseAttributes(xmlNode, path, this._defs);
          return path;
        }
      };
    }();

    return SVGParser;
  }();

  var defineParsers = {
    'lineargradient': function (xmlNode) {
      var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10);
      var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10);
      var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10);
      var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10);
      var gradient = new LinearGradient(x1, y1, x2, y2);

      _parseGradientColorStops(xmlNode, gradient);

      return gradient;
    }
  };

  function _parseGradientColorStops(xmlNode, gradient) {
    var stop = xmlNode.firstChild;

    while (stop) {
      if (stop.nodeType === 1) {
        var offsetStr = stop.getAttribute('offset');
        var offset = void 0;

        if (offsetStr.indexOf('%') > 0) {
          offset = parseInt(offsetStr, 10) / 100;
        } else if (offsetStr) {
          offset = parseFloat(offsetStr);
        } else {
          offset = 0;
        }

        var stopColor = stop.getAttribute('stop-color') || '#000000';
        gradient.colorStops.push({
          offset: offset,
          color: stopColor
        });
      }

      stop = stop.nextSibling;
    }
  }

  function inheritStyle(parent, child) {
    if (parent && parent.__inheritedStyle) {
      if (!child.__inheritedStyle) {
        child.__inheritedStyle = {};
      }

      defaults(child.__inheritedStyle, parent.__inheritedStyle);
    }
  }

  function parsePoints(pointsString) {
    var list = trim(pointsString).split(DILIMITER_REG);
    var points = [];

    for (var i = 0; i < list.length; i += 2) {
      var x = parseFloat(list[i]);
      var y = parseFloat(list[i + 1]);
      points.push([x, y]);
    }

    return points;
  }

  var attributesMap = {
    'fill': 'fill',
    'stroke': 'stroke',
    'stroke-width': 'lineWidth',
    'opacity': 'opacity',
    'fill-opacity': 'fillOpacity',
    'stroke-opacity': 'strokeOpacity',
    'stroke-dasharray': 'lineDash',
    'stroke-dashoffset': 'lineDashOffset',
    'stroke-linecap': 'lineCap',
    'stroke-linejoin': 'lineJoin',
    'stroke-miterlimit': 'miterLimit',
    'font-family': 'fontFamily',
    'font-size': 'fontSize',
    'font-style': 'fontStyle',
    'font-weight': 'fontWeight',
    'text-align': 'textAlign',
    'alignment-baseline': 'textBaseline'
  };

  function parseAttributes(xmlNode, el, defs, onlyInlineStyle) {
    var disp = el;
    var zrStyle = disp.__inheritedStyle || {};

    if (xmlNode.nodeType === 1) {
      parseTransformAttribute(xmlNode, el);
      extend(zrStyle, parseStyleAttribute(xmlNode));

      if (!onlyInlineStyle) {
        for (var svgAttrName in attributesMap) {
          if (attributesMap.hasOwnProperty(svgAttrName)) {
            var attrValue = xmlNode.getAttribute(svgAttrName);

            if (attrValue != null) {
              zrStyle[attributesMap[svgAttrName]] = attrValue;
            }
          }
        }
      }
    }

    disp.style = disp.style || {};
    zrStyle.fill != null && (disp.style.fill = getPaint(zrStyle.fill, defs));
    zrStyle.stroke != null && (disp.style.stroke = getPaint(zrStyle.stroke, defs));
    each(['lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'], function (propName) {
      zrStyle[propName] != null && (disp.style[propName] = parseFloat(zrStyle[propName]));
    });

    if (!zrStyle.textBaseline || zrStyle.textBaseline === 'auto') {
      zrStyle.textBaseline = 'alphabetic';
    }

    if (zrStyle.textBaseline === 'alphabetic') {
      zrStyle.textBaseline = 'bottom';
    }

    if (zrStyle.textAlign === 'start') {
      zrStyle.textAlign = 'left';
    }

    if (zrStyle.textAlign === 'end') {
      zrStyle.textAlign = 'right';
    }

    each(['lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign', 'textBaseline'], function (propName) {
      zrStyle[propName] != null && (disp.style[propName] = zrStyle[propName]);
    });

    if (zrStyle.lineDash) {
      disp.style.lineDash = map(trim(zrStyle.lineDash).split(DILIMITER_REG), function (str) {
        return parseFloat(str);
      });
    }

    disp.__inheritedStyle = zrStyle;
  }

  var urlRegex = /url\(\s*#(.*?)\)/;

  function getPaint(str, defs) {
    var urlMatch = defs && str && str.match(urlRegex);

    if (urlMatch) {
      var url = trim(urlMatch[1]);
      var def = defs[url];
      return def;
    }

    return str;
  }

  var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g;

  function parseTransformAttribute(xmlNode, node) {
    var transform = xmlNode.getAttribute('transform');

    if (transform) {
      transform = transform.replace(/,/g, ' ');
      var transformOps_1 = [];
      var m = null;
      transform.replace(transformRegex, function (str, type, value) {
        transformOps_1.push(type, value);
        return '';
      });

      for (var i = transformOps_1.length - 1; i > 0; i -= 2) {
        var value = transformOps_1[i];
        var type = transformOps_1[i - 1];
        var valueArr = void 0;
        m = m || create$1();

        switch (type) {
          case 'translate':
            valueArr = trim(value).split(DILIMITER_REG);
            translate(m, m, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]);
            break;

          case 'scale':
            valueArr = trim(value).split(DILIMITER_REG);
            scale$1(m, m, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]);
            break;

          case 'rotate':
            valueArr = trim(value).split(DILIMITER_REG);
            rotate(m, m, parseFloat(valueArr[0]));
            break;

          case 'skew':
            valueArr = trim(value).split(DILIMITER_REG);
            console.warn('Skew transform is not supported yet');
            break;

          case 'matrix':
            valueArr = trim(value).split(DILIMITER_REG);
            m[0] = parseFloat(valueArr[0]);
            m[1] = parseFloat(valueArr[1]);
            m[2] = parseFloat(valueArr[2]);
            m[3] = parseFloat(valueArr[3]);
            m[4] = parseFloat(valueArr[4]);
            m[5] = parseFloat(valueArr[5]);
            break;
        }
      }

      node.setLocalTransform(m);
    }
  }

  var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;

  function parseStyleAttribute(xmlNode) {
    var style = xmlNode.getAttribute('style');
    var result = {};

    if (!style) {
      return result;
    }

    var styleList = {};
    styleRegex.lastIndex = 0;
    var styleRegResult;

    while ((styleRegResult = styleRegex.exec(style)) != null) {
      styleList[styleRegResult[1]] = styleRegResult[2];
    }

    for (var svgAttrName in attributesMap) {
      if (attributesMap.hasOwnProperty(svgAttrName) && styleList[svgAttrName] != null) {
        result[attributesMap[svgAttrName]] = styleList[svgAttrName];
      }
    }

    return result;
  }

  function makeViewBoxTransform(viewBoxRect, width, height) {
    var scaleX = width / viewBoxRect.width;
    var scaleY = height / viewBoxRect.height;
    var scale = Math.min(scaleX, scaleY);
    return {
      scale: scale,
      x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + width / 2,
      y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + height / 2
    };
  }

  function parseSVG(xml, opt) {
    var parser = new SVGParser();
    return parser.parse(xml, opt);
  }

  var PI$2 = Math.PI;
  var PI2$5 = PI$2 * 2;
  var mathSin$3 = Math.sin;
  var mathCos$3 = Math.cos;
  var mathACos = Math.acos;
  var mathATan2 = Math.atan2;
  var mathAbs$1 = Math.abs;
  var mathSqrt$4 = Math.sqrt;
  var mathMax$3 = Math.max;
  var mathMin$3 = Math.min;
  var e = 1e-4;

  function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
    var x10 = x1 - x0;
    var y10 = y1 - y0;
    var x32 = x3 - x2;
    var y32 = y3 - y2;
    var t = y32 * x10 - x32 * y10;

    if (t * t < e) {
      return;
    }

    t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;
    return [x0 + t * x10, y0 + t * y10];
  }

  function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) {
    var x01 = x0 - x1;
    var y01 = y0 - y1;
    var lo = (clockwise ? cr : -cr) / mathSqrt$4(x01 * x01 + y01 * y01);
    var ox = lo * y01;
    var oy = -lo * x01;
    var x11 = x0 + ox;
    var y11 = y0 + oy;
    var x10 = x1 + ox;
    var y10 = y1 + oy;
    var x00 = (x11 + x10) / 2;
    var y00 = (y11 + y10) / 2;
    var dx = x10 - x11;
    var dy = y10 - y11;
    var d2 = dx * dx + dy * dy;
    var r = radius - cr;
    var s = x11 * y10 - x10 * y11;
    var d = (dy < 0 ? -1 : 1) * mathSqrt$4(mathMax$3(0, r * r * d2 - s * s));
    var cx0 = (s * dy - dx * d) / d2;
    var cy0 = (-s * dx - dy * d) / d2;
    var cx1 = (s * dy + dx * d) / d2;
    var cy1 = (-s * dx + dy * d) / d2;
    var dx0 = cx0 - x00;
    var dy0 = cy0 - y00;
    var dx1 = cx1 - x00;
    var dy1 = cy1 - y00;

    if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) {
      cx0 = cx1;
      cy0 = cy1;
    }

    return {
      cx: cx0,
      cy: cy0,
      x01: -ox,
      y01: -oy,
      x11: cx0 * (radius / r - 1),
      y11: cy0 * (radius / r - 1)
    };
  }

  function buildPath$2(ctx, shape) {
    var radius = mathMax$3(shape.r, 0);
    var innerRadius = mathMax$3(shape.r0 || 0, 0);
    var hasRadius = radius > 0;
    var hasInnerRadius = innerRadius > 0;

    if (!hasRadius && !hasInnerRadius) {
      return;
    }

    if (!hasRadius) {
      radius = innerRadius;
      innerRadius = 0;
    }

    if (innerRadius > radius) {
      var tmp = radius;
      radius = innerRadius;
      innerRadius = tmp;
    }

    var clockwise = !!shape.clockwise;
    var startAngle = shape.startAngle;
    var endAngle = shape.endAngle;
    var tmpAngles = [startAngle, endAngle];
    normalizeArcAngles(tmpAngles, !clockwise);
    var arc = mathAbs$1(tmpAngles[0] - tmpAngles[1]);
    var x = shape.cx;
    var y = shape.cy;
    var cornerRadius = shape.cornerRadius || 0;
    var innerCornerRadius = shape.innerCornerRadius || 0;

    if (!(radius > e)) {
      ctx.moveTo(x, y);
    } else if (arc > PI2$5 - e) {
      ctx.moveTo(x + radius * mathCos$3(startAngle), y + radius * mathSin$3(startAngle));
      ctx.arc(x, y, radius, startAngle, endAngle, !clockwise);

      if (innerRadius > e) {
        ctx.moveTo(x + innerRadius * mathCos$3(endAngle), y + innerRadius * mathSin$3(endAngle));
        ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise);
      }
    } else {
      var halfRd = mathAbs$1(radius - innerRadius) / 2;
      var cr = mathMin$3(halfRd, cornerRadius);
      var icr = mathMin$3(halfRd, innerCornerRadius);
      var cr0 = icr;
      var cr1 = cr;
      var xrs = radius * mathCos$3(startAngle);
      var yrs = radius * mathSin$3(startAngle);
      var xire = innerRadius * mathCos$3(endAngle);
      var yire = innerRadius * mathSin$3(endAngle);
      var xre = void 0;
      var yre = void 0;
      var xirs = void 0;
      var yirs = void 0;

      if (cr > e || icr > e) {
        xre = radius * mathCos$3(endAngle);
        yre = radius * mathSin$3(endAngle);
        xirs = innerRadius * mathCos$3(startAngle);
        yirs = innerRadius * mathSin$3(startAngle);

        if (arc < PI$2) {
          var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire);

          if (it_1) {
            var x0 = xrs - it_1[0];
            var y0 = yrs - it_1[1];
            var x1 = xre - it_1[0];
            var y1 = yre - it_1[1];
            var a = 1 / mathSin$3(mathACos((x0 * x1 + y0 * y1) / (mathSqrt$4(x0 * x0 + y0 * y0) * mathSqrt$4(x1 * x1 + y1 * y1))) / 2);
            var b = mathSqrt$4(it_1[0] * it_1[0] + it_1[1] * it_1[1]);
            cr0 = mathMin$3(icr, (innerRadius - b) / (a - 1));
            cr1 = mathMin$3(cr, (radius - b) / (a + 1));
          }
        }
      }

      if (!(arc > e)) {
        ctx.moveTo(x + xrs, y + yrs);
      } else if (cr1 > e) {
        var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, cr1, clockwise);
        var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, cr1, clockwise);
        ctx.moveTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01);

        if (cr1 < cr) {
          ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise);
        } else {
          ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise);
          ctx.arc(x, y, radius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), !clockwise);
          ctx.arc(x + ct1.cx, y + ct1.cy, cr1, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise);
        }
      } else {
        ctx.moveTo(x + xrs, y + yrs);
        ctx.arc(x, y, radius, startAngle, endAngle, !clockwise);
      }

      if (!(innerRadius > e) || !(arc > e)) {
        ctx.lineTo(x + xire, y + yire);
      } else if (cr0 > e) {
        var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -cr0, clockwise);
        var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -cr0, clockwise);
        ctx.lineTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01);

        if (cr0 < icr) {
          ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise);
        } else {
          ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise);
          ctx.arc(x, y, innerRadius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), clockwise);
          ctx.arc(x + ct1.cx, y + ct1.cy, cr0, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise);
        }
      } else {
        ctx.lineTo(x + xire, y + yire);
        ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise);
      }
    }

    ctx.closePath();
  }

  var SectorShape = function () {
    function SectorShape() {
      this.cx = 0;
      this.cy = 0;
      this.r0 = 0;
      this.r = 0;
      this.startAngle = 0;
      this.endAngle = Math.PI * 2;
      this.clockwise = true;
      this.cornerRadius = 0;
      this.innerCornerRadius = 0;
    }

    return SectorShape;
  }();

  var Sector = function (_super) {
    __extends(Sector, _super);

    function Sector(opts) {
      return _super.call(this, opts) || this;
    }

    Sector.prototype.getDefaultShape = function () {
      return new SectorShape();
    };

    Sector.prototype.buildPath = function (ctx, shape) {
      buildPath$2(ctx, shape);
    };

    Sector.prototype.isZeroArea = function () {
      return this.shape.startAngle === this.shape.endAngle || this.shape.r === this.shape.r0;
    };

    return Sector;
  }(Path);

  Sector.prototype.type = 'sector';
  var CMD$3 = PathProxy.CMD;
  var PI2$6 = Math.PI * 2;
  var PROP_XY = ['x', 'y'];
  var PROP_WH = ['width', 'height'];
  var tmpArr = [];

  function aroundEqual(a, b) {
    return Math.abs(a - b) < 1e-5;
  }

  function pathToBezierCurves(path) {
    var data = path.data;
    var len = path.len();
    var bezierArray = [];
    var currentSubpath;
    var xi = 0;
    var yi = 0;
    var x0 = 0;
    var y0 = 0;

    function createNewSubpath(x, y) {
      if (currentSubpath && currentSubpath.length > 2) {
        bezierArray.push(currentSubpath);
      }

      currentSubpath = [x, y];
    }

    function addLine(x0, y0, x1, y1) {
      if (!(aroundEqual(x0, x1) && aroundEqual(y0, y1))) {
        currentSubpath.push(x0, y0, x1, y1, x1, y1);
      }
    }

    function addArc(startAngle, endAngle, cx, cy, rx, ry) {
      var delta = Math.abs(endAngle - startAngle);
      var len = Math.tan(delta / 4) * 4 / 3;
      var dir = endAngle < startAngle ? -1 : 1;
      var c1 = Math.cos(startAngle);
      var s1 = Math.sin(startAngle);
      var c2 = Math.cos(endAngle);
      var s2 = Math.sin(endAngle);
      var x1 = c1 * rx + cx;
      var y1 = s1 * ry + cy;
      var x4 = c2 * rx + cx;
      var y4 = s2 * ry + cy;
      var hx = rx * len * dir;
      var hy = ry * len * dir;
      currentSubpath.push(x1 - hx * s1, y1 + hy * c1, x4 + hx * s2, y4 - hy * c2, x4, y4);
    }

    var x1;
    var y1;
    var x2;
    var y2;

    for (var i = 0; i < len;) {
      var cmd = data[i++];
      var isFirst = i === 1;

      if (isFirst) {
        xi = data[i];
        yi = data[i + 1];
        x0 = xi;
        y0 = yi;

        if (cmd === CMD$3.L || cmd === CMD$3.C || cmd === CMD$3.Q) {
          currentSubpath = [x0, y0];
        }
      }

      switch (cmd) {
        case CMD$3.M:
          xi = x0 = data[i++];
          yi = y0 = data[i++];
          createNewSubpath(x0, y0);
          break;

        case CMD$3.L:
          x1 = data[i++];
          y1 = data[i++];
          addLine(xi, yi, x1, y1);
          xi = x1;
          yi = y1;
          break;

        case CMD$3.C:
          currentSubpath.push(data[i++], data[i++], data[i++], data[i++], xi = data[i++], yi = data[i++]);
          break;

        case CMD$3.Q:
          x1 = data[i++];
          y1 = data[i++];
          x2 = data[i++];
          y2 = data[i++];
          currentSubpath.push(xi + 2 / 3 * (x1 - xi), yi + 2 / 3 * (y1 - yi), x2 + 2 / 3 * (x1 - x2), y2 + 2 / 3 * (y1 - y2), x2, y2);
          xi = x2;
          yi = y2;
          break;

        case CMD$3.A:
          var cx = data[i++];
          var cy = data[i++];
          var rx = data[i++];
          var ry = data[i++];
          var startAngle = data[i++];
          var endAngle = data[i++] + startAngle;
          i += 1;
          var anticlockwise = !data[i++];
          x1 = Math.cos(startAngle) * rx + cx;
          y1 = Math.sin(startAngle) * ry + cy;

          if (isFirst) {
            x0 = x1;
            y0 = y1;
            createNewSubpath(x0, y0);
          } else {
            addLine(xi, yi, x1, y1);
          }

          xi = Math.cos(endAngle) * rx + cx;
          yi = Math.sin(endAngle) * ry + cy;
          var step = (anticlockwise ? -1 : 1) * Math.PI / 2;

          for (var angle = startAngle; anticlockwise ? angle > endAngle : angle < endAngle; angle += step) {
            var nextAngle = anticlockwise ? Math.max(angle + step, endAngle) : Math.min(angle + step, endAngle);
            addArc(angle, nextAngle, cx, cy, rx, ry);
          }

          break;

        case CMD$3.R:
          x0 = xi = data[i++];
          y0 = yi = data[i++];
          x1 = x0 + data[i++];
          y1 = y0 + data[i++];
          createNewSubpath(x1, y0);
          addLine(x1, y0, x1, y1);
          addLine(x1, y1, x0, y1);
          addLine(x0, y1, x0, y0);
          addLine(x0, y0, x1, y0);
          break;

        case CMD$3.Z:
          currentSubpath && addLine(xi, yi, x0, y0);
          xi = x0;
          yi = y0;
          break;
      }
    }

    if (currentSubpath && currentSubpath.length > 2) {
      bezierArray.push(currentSubpath);
    }

    return bezierArray;
  }

  function alignSubpath(subpath1, subpath2) {
    var len1 = subpath1.length;
    var len2 = subpath2.length;

    if (len1 === len2) {
      return [subpath1, subpath2];
    }

    var shorterPath = len1 < len2 ? subpath1 : subpath2;
    var shorterLen = Math.min(len1, len2);
    var diff = Math.abs(len2 - len1) / 6;
    var shorterBezierCount = (shorterLen - 2) / 6;
    var eachCurveSubDivCount = Math.ceil(diff / shorterBezierCount) + 1;
    var newSubpath = [shorterPath[0], shorterPath[1]];
    var remained = diff;
    var tmpSegX = [];
    var tmpSegY = [];

    for (var i = 2; i < shorterLen;) {
      var x0 = shorterPath[i - 2];
      var y0 = shorterPath[i - 1];
      var x1 = shorterPath[i++];
      var y1 = shorterPath[i++];
      var x2 = shorterPath[i++];
      var y2 = shorterPath[i++];
      var x3 = shorterPath[i++];
      var y3 = shorterPath[i++];

      if (remained <= 0) {
        newSubpath.push(x1, y1, x2, y2, x3, y3);
        continue;
      }

      var actualSubDivCount = Math.min(remained, eachCurveSubDivCount - 1) + 1;

      for (var k = 1; k <= actualSubDivCount; k++) {
        var p = k / actualSubDivCount;
        cubicSubdivide(x0, x1, x2, x3, p, tmpSegX);
        cubicSubdivide(y0, y1, y2, y3, p, tmpSegY);
        x0 = tmpSegX[3];
        y0 = tmpSegY[3];
        newSubpath.push(tmpSegX[1], tmpSegY[1], tmpSegX[2], tmpSegY[2], x0, y0);
        x1 = tmpSegX[5];
        y1 = tmpSegY[5];
        x2 = tmpSegX[6];
        y2 = tmpSegY[6];
      }

      remained -= actualSubDivCount - 1;
    }

    return shorterPath === subpath1 ? [newSubpath, subpath2] : [subpath1, newSubpath];
  }

  function createSubpath(lastSubpathSubpath, otherSubpath) {
    var len = lastSubpathSubpath.length;
    var lastX = lastSubpathSubpath[len - 2];
    var lastY = lastSubpathSubpath[len - 1];
    var newSubpath = [];

    for (var i = 0; i < otherSubpath.length;) {
      newSubpath[i++] = lastX;
      newSubpath[i++] = lastY;
    }

    return newSubpath;
  }

  function alignBezierCurves(array1, array2) {
    var _a;

    var lastSubpath1;
    var lastSubpath2;
    var newArray1 = [];
    var newArray2 = [];

    for (var i = 0; i < Math.max(array1.length, array2.length); i++) {
      var subpath1 = array1[i];
      var subpath2 = array2[i];
      var newSubpath1 = void 0;
      var newSubpath2 = void 0;

      if (!subpath1) {
        newSubpath1 = createSubpath(lastSubpath1 || subpath2, subpath2);
        newSubpath2 = subpath2;
      } else if (!subpath2) {
        newSubpath2 = createSubpath(lastSubpath2 || subpath1, subpath1);
        newSubpath1 = subpath1;
      } else {
        _a = alignSubpath(subpath1, subpath2), newSubpath1 = _a[0], newSubpath2 = _a[1];
        lastSubpath1 = newSubpath1;
        lastSubpath2 = newSubpath2;
      }

      newArray1.push(newSubpath1);
      newArray2.push(newSubpath2);
    }

    return [newArray1, newArray2];
  }

  function centroid(array) {
    var signedArea = 0;
    var cx = 0;
    var cy = 0;
    var len = array.length;

    for (var i = 0, j = len - 2; i < len; j = i, i += 2) {
      var x0 = array[j];
      var y0 = array[j + 1];
      var x1 = array[i];
      var y1 = array[i + 1];
      var a = x0 * y1 - x1 * y0;
      signedArea += a;
      cx += (x0 + x1) * a;
      cy += (y0 + y1) * a;
    }

    if (signedArea === 0) {
      return [array[0] || 0, array[1] || 0];
    }

    return [cx / signedArea / 3, cy / signedArea / 3, signedArea];
  }

  function findBestRingOffset(fromSubBeziers, toSubBeziers, fromCp, toCp) {
    var bezierCount = (fromSubBeziers.length - 2) / 6;
    var bestScore = Infinity;
    var bestOffset = 0;
    var len = fromSubBeziers.length;
    var len2 = len - 2;

    for (var offset = 0; offset < bezierCount; offset++) {
      var cursorOffset = offset * 6;
      var score = 0;

      for (var k = 0; k < len; k += 2) {
        var idx = k === 0 ? cursorOffset : (cursorOffset + k - 2) % len2 + 2;
        var x0 = fromSubBeziers[idx] - fromCp[0];
        var y0 = fromSubBeziers[idx + 1] - fromCp[1];
        var x1 = toSubBeziers[k] - toCp[0];
        var y1 = toSubBeziers[k + 1] - toCp[1];
        var dx = x1 - x0;
        var dy = y1 - y0;
        score += dx * dx + dy * dy;
      }

      if (score < bestScore) {
        bestScore = score;
        bestOffset = offset;
      }
    }

    return bestOffset;
  }

  function reverse(array) {
    var newArr = [];
    var len = array.length;

    for (var i = 0; i < len; i += 2) {
      newArr[i] = array[len - i - 2];
      newArr[i + 1] = array[len - i - 1];
    }

    return newArr;
  }

  function findBestMorphingRotation(fromArr, toArr, searchAngleIteration, searchAngleRange) {
    var result = [];
    var fromNeedsReverse;

    for (var i = 0; i < fromArr.length; i++) {
      var fromSubpathBezier = fromArr[i];
      var toSubpathBezier = toArr[i];
      var fromCp = centroid(fromSubpathBezier);
      var toCp = centroid(toSubpathBezier);

      if (fromNeedsReverse == null) {
        fromNeedsReverse = fromCp[2] < 0 !== toCp[2] < 0;
      }

      var newFromSubpathBezier = [];
      var newToSubpathBezier = [];
      var bestAngle = 0;
      var bestScore = Infinity;
      var tmpArr_1 = [];
      var len = fromSubpathBezier.length;

      if (fromNeedsReverse) {
        fromSubpathBezier = reverse(fromSubpathBezier);
      }

      var offset = findBestRingOffset(fromSubpathBezier, toSubpathBezier, fromCp, toCp) * 6;
      var len2 = len - 2;

      for (var k = 0; k < len2; k += 2) {
        var idx = (offset + k) % len2 + 2;
        newFromSubpathBezier[k + 2] = fromSubpathBezier[idx] - fromCp[0];
        newFromSubpathBezier[k + 3] = fromSubpathBezier[idx + 1] - fromCp[1];
      }

      newFromSubpathBezier[0] = fromSubpathBezier[offset] - fromCp[0];
      newFromSubpathBezier[1] = fromSubpathBezier[offset + 1] - fromCp[1];

      if (searchAngleIteration > 0) {
        var step = searchAngleRange / searchAngleIteration;

        for (var angle = -searchAngleRange / 2; angle <= searchAngleRange / 2; angle += step) {
          var sa = Math.sin(angle);
          var ca = Math.cos(angle);
          var score = 0;

          for (var k = 0; k < fromSubpathBezier.length; k += 2) {
            var x0 = newFromSubpathBezier[k];
            var y0 = newFromSubpathBezier[k + 1];
            var x1 = toSubpathBezier[k] - toCp[0];
            var y1 = toSubpathBezier[k + 1] - toCp[1];
            var newX1 = x1 * ca - y1 * sa;
            var newY1 = x1 * sa + y1 * ca;
            tmpArr_1[k] = newX1;
            tmpArr_1[k + 1] = newY1;
            var dx = newX1 - x0;
            var dy = newY1 - y0;
            score += dx * dx + dy * dy;
          }

          if (score < bestScore) {
            bestScore = score;
            bestAngle = angle;

            for (var m = 0; m < tmpArr_1.length; m++) {
              newToSubpathBezier[m] = tmpArr_1[m];
            }
          }
        }
      } else {
        for (var i_1 = 0; i_1 < len; i_1 += 2) {
          newToSubpathBezier[i_1] = toSubpathBezier[i_1] - toCp[0];
          newToSubpathBezier[i_1 + 1] = toSubpathBezier[i_1 + 1] - toCp[1];
        }
      }

      result.push({
        from: newFromSubpathBezier,
        to: newToSubpathBezier,
        fromCp: fromCp,
        toCp: toCp,
        rotation: -bestAngle
      });
    }

    return result;
  }

  function morphPath(fromPath, toPath, animationOpts) {
    var fromPathProxy;
    var toPathProxy;

    if (!fromPath || !toPath) {
      return toPath;
    }

    !fromPath.path && fromPath.createPathProxy();
    fromPathProxy = fromPath.path;
    fromPathProxy.beginPath();
    fromPath.buildPath(fromPathProxy, fromPath.shape);
    !toPath.path && toPath.createPathProxy();
    toPathProxy = toPath.path;
    toPathProxy === fromPathProxy && (toPathProxy = new PathProxy(false));
    toPathProxy.beginPath();

    if (isIndividualMorphingPath(toPath)) {
      toPath.__oldBuildPath(toPathProxy, toPath.shape);
    } else {
      toPath.buildPath(toPathProxy, toPath.shape);
    }

    var _a = alignBezierCurves(pathToBezierCurves(fromPathProxy), pathToBezierCurves(toPathProxy)),
        fromBezierCurves = _a[0],
        toBezierCurves = _a[1];

    var morphingData = findBestMorphingRotation(fromBezierCurves, toBezierCurves, 10, Math.PI);
    becomeIndividualMorphingPath(toPath, morphingData, 0);
    var oldDone = animationOpts && animationOpts.done;
    var oldAborted = animationOpts && animationOpts.aborted;
    var oldDuring = animationOpts && animationOpts.during;
    toPath.animateTo({
      __morphT: 1
    }, defaults({
      during: function (p) {
        toPath.dirtyShape();
        oldDuring && oldDuring(p);
      },
      done: function () {
        restoreIndividualMorphingPath(toPath);
        toPath.createPathProxy();
        toPath.dirtyShape();
        oldDone && oldDone();
      },
      aborted: function () {
        oldAborted && oldAborted();
      }
    }, animationOpts));
    return toPath;
  }

  function morphingPathBuildPath(path) {
    var morphingData = this.__morphingData;
    var t = this.__morphT;
    var onet = 1 - t;
    var newCp = [];

    for (var i = 0; i < morphingData.length; i++) {
      var item = morphingData[i];
      var from = item.from;
      var to = item.to;
      var angle = item.rotation * t;
      var fromCp = item.fromCp;
      var toCp = item.toCp;
      var sa = Math.sin(angle);
      var ca = Math.cos(angle);
      lerp(newCp, fromCp, toCp, t);

      for (var m = 0; m < from.length; m += 2) {
        var x0 = from[m];
        var y0 = from[m + 1];
        var x1 = to[m];
        var y1 = to[m + 1];
        var x = x0 * onet + x1 * t;
        var y = y0 * onet + y1 * t;
        tmpArr[m] = x * ca - y * sa + newCp[0];
        tmpArr[m + 1] = x * sa + y * ca + newCp[1];
      }

      for (var m = 0; m < from.length;) {
        if (m === 0) {
          path.moveTo(tmpArr[m++], tmpArr[m++]);
        }

        path.bezierCurveTo(tmpArr[m++], tmpArr[m++], tmpArr[m++], tmpArr[m++], tmpArr[m++], tmpArr[m++]);
      }
    }
  }

  function becomeIndividualMorphingPath(path, morphingData, morphT) {
    if (isIndividualMorphingPath(path)) {
      updateIndividualMorphingPath(path, morphingData, morphT);
      return;
    }

    var morphingPath = path;
    morphingPath.__oldBuildPath = morphingPath.buildPath;
    morphingPath.buildPath = morphingPathBuildPath;
    updateIndividualMorphingPath(morphingPath, morphingData, morphT);
  }

  function updateIndividualMorphingPath(morphingPath, morphingData, morphT) {
    morphingPath.__morphingData = morphingData;
    morphingPath.__morphT = morphT;
  }

  function restoreIndividualMorphingPath(path) {
    if (isIndividualMorphingPath(path)) {
      path.buildPath = path.__oldBuildPath;
      path.__oldBuildPath = path.__morphingData = null;
    }
  }

  function isIndividualMorphingPath(path) {
    return path.__oldBuildPath != null;
  }

  function isCombiningPath(path) {
    return !!path.__combiningSubList;
  }

  function isInAnyMorphing(path) {
    return isIndividualMorphingPath(path) || isCombiningPath(path);
  }

  function combine(fromPathList, toPath, animationOpts, copyPropsIfDivided) {
    var fromIndividuals = [];
    var separateCount = 0;

    for (var i = 0; i < fromPathList.length; i++) {
      var fromPath = fromPathList[i];

      if (isCombiningPath(fromPath)) {
        var fromCombiningSubList = fromPath.__combiningSubList;

        for (var j = 0; j < fromCombiningSubList.length; j++) {
          fromIndividuals.push(fromCombiningSubList[j]);
        }

        separateCount += fromCombiningSubList.length;
      } else {
        fromIndividuals.push(fromPath);
        separateCount++;
      }
    }

    if (!separateCount) {
      return;
    }

    var dividingMethod = animationOpts ? animationOpts.dividingMethod : null;
    var toPathSplittedList = divideShape(toPath, separateCount, dividingMethod);
    assert(toPathSplittedList.length === separateCount);
    var oldDone = animationOpts && animationOpts.done;
    var oldAborted = animationOpts && animationOpts.aborted;
    var oldDuring = animationOpts && animationOpts.during;
    var doneCount = 0;
    var abortedCalled = false;
    var morphAnimationOpts = defaults({
      during: function (p) {
        oldDuring && oldDuring(p);
      },
      done: function () {
        doneCount++;

        if (doneCount === toPathSplittedList.length) {
          restoreCombiningPath(toPath);
          oldDone && oldDone();
        }
      },
      aborted: function () {
        if (!abortedCalled) {
          abortedCalled = true;
          oldAborted && oldAborted();
        }
      }
    }, animationOpts);

    for (var i = 0; i < separateCount; i++) {
      var from = fromIndividuals[i];
      var to = toPathSplittedList[i];
      copyPropsIfDivided && copyPropsIfDivided(toPath, to, true);
      morphPath(from, to, morphAnimationOpts);
    }

    becomeCombiningPath(toPath, toPathSplittedList);
    return {
      fromIndividuals: fromIndividuals,
      toIndividuals: toPathSplittedList,
      count: separateCount
    };
  }

  function becomeCombiningPath(path, combiningSubList) {
    if (isCombiningPath(path)) {
      updateCombiningPathSubList(path, combiningSubList);
      return;
    }

    var combiningPath = path;
    updateCombiningPathSubList(combiningPath, combiningSubList);
    combiningPath.__oldAddSelfToZr = path.addSelfToZr;
    combiningPath.__oldRemoveSelfFromZr = path.removeSelfFromZr;
    combiningPath.addSelfToZr = combiningAddSelfToZr;
    combiningPath.removeSelfFromZr = combiningRemoveSelfFromZr;
    combiningPath.__oldBuildPath = combiningPath.buildPath;
    combiningPath.buildPath = noop;
    combiningPath.childrenRef = combiningChildrenRef;
  }

  function restoreCombiningPath(path) {
    if (!isCombiningPath(path)) {
      return;
    }

    var combiningPath = path;
    updateCombiningPathSubList(combiningPath, null);
    combiningPath.addSelfToZr = combiningPath.__oldAddSelfToZr;
    combiningPath.removeSelfFromZr = combiningPath.__oldRemoveSelfFromZr;
    combiningPath.buildPath = combiningPath.__oldBuildPath;
    combiningPath.childrenRef = combiningPath.__combiningSubList = combiningPath.__oldAddSelfToZr = combiningPath.__oldRemoveSelfFromZr = combiningPath.__oldBuildPath = null;
  }

  function updateCombiningPathSubList(combiningPath, combiningSubList) {
    if (combiningPath.__combiningSubList !== combiningSubList) {
      combiningPathSubListAddRemoveWithZr(combiningPath, 'removeSelfFromZr');
      combiningPath.__combiningSubList = combiningSubList;

      if (combiningSubList) {
        for (var i = 0; i < combiningSubList.length; i++) {
          combiningSubList[i].parent = combiningPath;
        }
      }

      combiningPathSubListAddRemoveWithZr(combiningPath, 'addSelfToZr');
    }
  }

  function combiningAddSelfToZr(zr) {
    this.__oldAddSelfToZr(zr);

    combiningPathSubListAddRemoveWithZr(this, 'addSelfToZr');
  }

  function combiningPathSubListAddRemoveWithZr(path, method) {
    var combiningSubList = path.__combiningSubList;
    var zr = path.__zr;

    if (combiningSubList && zr) {
      for (var i = 0; i < combiningSubList.length; i++) {
        var child = combiningSubList[i];
        child[method](zr);
      }
    }
  }

  function combiningRemoveSelfFromZr(zr) {
    this.__oldRemoveSelfFromZr(zr);

    var combiningSubList = this.__combiningSubList;

    for (var i = 0; i < combiningSubList.length; i++) {
      var child = combiningSubList[i];
      child.removeSelfFromZr(zr);
    }
  }

  function combiningChildrenRef() {
    return this.__combiningSubList;
  }

  function separate(fromPath, toPathList, animationOpts, copyPropsIfDivided) {
    var toPathListLen = toPathList.length;
    var fromPathList;
    var dividingMethod = animationOpts ? animationOpts.dividingMethod : null;
    var copyProps = false;

    if (isCombiningPath(fromPath)) {
      var fromCombiningSubList = fromPath.__combiningSubList;

      if (fromCombiningSubList.length === toPathListLen) {
        fromPathList = fromCombiningSubList;
      } else {
        fromPathList = divideShape(fromPath, toPathListLen, dividingMethod);
        copyProps = true;
      }
    } else {
      fromPathList = divideShape(fromPath, toPathListLen, dividingMethod);
      copyProps = true;
    }

    assert(fromPathList.length === toPathListLen);

    for (var i = 0; i < toPathListLen; i++) {
      if (copyProps && copyPropsIfDivided) {
        copyPropsIfDivided(fromPath, fromPathList[i], false);
      }

      morphPath(fromPathList[i], toPathList[i], animationOpts);
    }

    return {
      fromIndividuals: fromPathList,
      toIndividuals: toPathList,
      count: toPathListLen
    };
  }

  function divideShape(path, separateCount, dividingMethod) {
    return dividingMethod === 'duplicate' ? duplicateShape(path, separateCount) : splitShape(path, separateCount);
  }

  function splitShape(path, separateCount) {
    var resultPaths = [];

    if (separateCount <= 0) {
      return resultPaths;
    }

    if (separateCount === 1) {
      return duplicateShape(path, separateCount);
    }

    if (path instanceof Rect) {
      var toPathShape = path.shape;
      var splitPropIdx = toPathShape.height > toPathShape.width ? 1 : 0;
      var propWH = PROP_WH[splitPropIdx];
      var propXY = PROP_XY[splitPropIdx];
      var subWH = toPathShape[propWH] / separateCount;
      var xyCurr = toPathShape[propXY];

      for (var i = 0; i < separateCount; i++, xyCurr += subWH) {
        var subShape = {
          x: toPathShape.x,
          y: toPathShape.y,
          width: toPathShape.width,
          height: toPathShape.height
        };
        subShape[propXY] = xyCurr;
        subShape[propWH] = i < separateCount - 1 ? subWH : toPathShape[propXY] + toPathShape[propWH] - xyCurr;
        var splitted = new Rect({
          shape: subShape
        });
        resultPaths.push(splitted);
      }
    } else if (path instanceof Sector) {
      var toPathShape = path.shape;
      var clockwise = toPathShape.clockwise;
      var startAngle = toPathShape.startAngle;
      var endAngle = toPathShape.endAngle;
      var endAngleNormalized = normalizeRadian$1(startAngle, toPathShape.endAngle, clockwise);
      var step = (endAngleNormalized - startAngle) / separateCount;
      var angleCurr = startAngle;

      for (var i = 0; i < separateCount; i++, angleCurr += step) {
        var splitted = new Sector({
          shape: {
            cx: toPathShape.cx,
            cy: toPathShape.cy,
            r: toPathShape.r,
            r0: toPathShape.r0,
            clockwise: clockwise,
            startAngle: angleCurr,
            endAngle: i === separateCount - 1 ? endAngle : angleCurr + step
          }
        });
        resultPaths.push(splitted);
      }
    } else {
      return duplicateShape(path, separateCount);
    }

    return resultPaths;
  }

  function duplicateShape(path, separateCount) {
    var resultPaths = [];

    if (separateCount <= 0) {
      return resultPaths;
    }

    var ctor = path.constructor;

    for (var i = 0; i < separateCount; i++) {
      var sub = new ctor({
        shape: clone(path.shape)
      });
      resultPaths.push(sub);
    }

    return resultPaths;
  }

  function normalizeRadian$1(start, end, clockwise) {
    return end + PI2$6 * Math[clockwise ? 'ceil' : 'floor']((start - end) / PI2$6);
  }

  var CompoundPath = function (_super) {
    __extends(CompoundPath, _super);

    function CompoundPath() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'compound';
      return _this;
    }

    CompoundPath.prototype._updatePathDirty = function () {
      var paths = this.shape.paths;
      var dirtyPath = this.shapeChanged();

      for (var i = 0; i < paths.length; i++) {
        dirtyPath = dirtyPath || paths[i].shapeChanged();
      }

      if (dirtyPath) {
        this.dirtyShape();
      }
    };

    CompoundPath.prototype.beforeBrush = function () {
      this._updatePathDirty();

      var paths = this.shape.paths || [];
      var scale = this.getGlobalScale();

      for (var i = 0; i < paths.length; i++) {
        if (!paths[i].path) {
          paths[i].createPathProxy();
        }

        paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold);
      }
    };

    CompoundPath.prototype.buildPath = function (ctx, shape) {
      var paths = shape.paths || [];

      for (var i = 0; i < paths.length; i++) {
        paths[i].buildPath(ctx, paths[i].shape, true);
      }
    };

    CompoundPath.prototype.afterBrush = function () {
      var paths = this.shape.paths || [];

      for (var i = 0; i < paths.length; i++) {
        paths[i].pathUpdated();
      }
    };

    CompoundPath.prototype.getBoundingRect = function () {
      this._updatePathDirty.call(this);

      return Path.prototype.getBoundingRect.call(this);
    };

    return CompoundPath;
  }(Path);

  var m = [];

  var IncrementalDisplayble = function (_super) {
    __extends(IncrementalDisplayble, _super);

    function IncrementalDisplayble() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.notClear = true;
      _this.incremental = true;
      _this._displayables = [];
      _this._temporaryDisplayables = [];
      _this._cursor = 0;
      return _this;
    }

    IncrementalDisplayble.prototype.traverse = function (cb, context) {
      cb.call(context, this);
    };

    IncrementalDisplayble.prototype.useStyle = function () {
      this.style = {};
    };

    IncrementalDisplayble.prototype.getCursor = function () {
      return this._cursor;
    };

    IncrementalDisplayble.prototype.innerAfterBrush = function () {
      this._cursor = this._displayables.length;
    };

    IncrementalDisplayble.prototype.clearDisplaybles = function () {
      this._displayables = [];
      this._temporaryDisplayables = [];
      this._cursor = 0;
      this.markRedraw();
      this.notClear = false;
    };

    IncrementalDisplayble.prototype.clearTemporalDisplayables = function () {
      this._temporaryDisplayables = [];
    };

    IncrementalDisplayble.prototype.addDisplayable = function (displayable, notPersistent) {
      if (notPersistent) {
        this._temporaryDisplayables.push(displayable);
      } else {
        this._displayables.push(displayable);
      }

      this.markRedraw();
    };

    IncrementalDisplayble.prototype.addDisplayables = function (displayables, notPersistent) {
      notPersistent = notPersistent || false;

      for (var i = 0; i < displayables.length; i++) {
        this.addDisplayable(displayables[i], notPersistent);
      }
    };

    IncrementalDisplayble.prototype.getDisplayables = function () {
      return this._displayables;
    };

    IncrementalDisplayble.prototype.getTemporalDisplayables = function () {
      return this._temporaryDisplayables;
    };

    IncrementalDisplayble.prototype.eachPendingDisplayable = function (cb) {
      for (var i = this._cursor; i < this._displayables.length; i++) {
        cb && cb(this._displayables[i]);
      }

      for (var i = 0; i < this._temporaryDisplayables.length; i++) {
        cb && cb(this._temporaryDisplayables[i]);
      }
    };

    IncrementalDisplayble.prototype.update = function () {
      this.updateTransform();

      for (var i = this._cursor; i < this._displayables.length; i++) {
        var displayable = this._displayables[i];
        displayable.parent = this;
        displayable.update();
        displayable.parent = null;
      }

      for (var i = 0; i < this._temporaryDisplayables.length; i++) {
        var displayable = this._temporaryDisplayables[i];
        displayable.parent = this;
        displayable.update();
        displayable.parent = null;
      }
    };

    IncrementalDisplayble.prototype.getBoundingRect = function () {
      if (!this._rect) {
        var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity);

        for (var i = 0; i < this._displayables.length; i++) {
          var displayable = this._displayables[i];
          var childRect = displayable.getBoundingRect().clone();

          if (displayable.needLocalTransform()) {
            childRect.applyTransform(displayable.getLocalTransform(m));
          }

          rect.union(childRect);
        }

        this._rect = rect;
      }

      return this._rect;
    };

    IncrementalDisplayble.prototype.contain = function (x, y) {
      var localPos = this.transformCoordToLocal(x, y);
      var rect = this.getBoundingRect();

      if (rect.contain(localPos[0], localPos[1])) {
        for (var i = 0; i < this._displayables.length; i++) {
          var displayable = this._displayables[i];

          if (displayable.contain(x, y)) {
            return true;
          }
        }
      }

      return false;
    };

    return IncrementalDisplayble;
  }(Displayable);

  var globalImageCache = new LRU(50);

  function findExistImage(newImageOrSrc) {
    if (typeof newImageOrSrc === 'string') {
      var cachedImgObj = globalImageCache.get(newImageOrSrc);
      return cachedImgObj && cachedImgObj.image;
    } else {
      return newImageOrSrc;
    }
  }

  function createOrUpdateImage(newImageOrSrc, image, hostEl, onload, cbPayload) {
    if (!newImageOrSrc) {
      return image;
    } else if (typeof newImageOrSrc === 'string') {
      if (image && image.__zrImageSrc === newImageOrSrc || !hostEl) {
        return image;
      }

      var cachedImgObj = globalImageCache.get(newImageOrSrc);
      var pendingWrap = {
        hostEl: hostEl,
        cb: onload,
        cbPayload: cbPayload
      };

      if (cachedImgObj) {
        image = cachedImgObj.image;
        !isImageReady(image) && cachedImgObj.pending.push(pendingWrap);
      } else {
        image = new Image();
        image.onload = image.onerror = imageOnLoad;
        globalImageCache.put(newImageOrSrc, image.__cachedImgObj = {
          image: image,
          pending: [pendingWrap]
        });
        image.src = image.__zrImageSrc = newImageOrSrc;
      }

      return image;
    } else {
      return newImageOrSrc;
    }
  }

  function imageOnLoad() {
    var cachedImgObj = this.__cachedImgObj;
    this.onload = this.onerror = this.__cachedImgObj = null;

    for (var i = 0; i < cachedImgObj.pending.length; i++) {
      var pendingWrap = cachedImgObj.pending[i];
      var cb = pendingWrap.cb;
      cb && cb(this, pendingWrap.cbPayload);
      pendingWrap.hostEl.dirty();
    }

    cachedImgObj.pending.length = 0;
  }

  function isImageReady(image) {
    return image && image.width && image.height;
  }

  var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g;

  function truncateText(text, containerWidth, font, ellipsis, options) {
    if (!containerWidth) {
      return '';
    }

    var textLines = (text + '').split('\n');
    options = prepareTruncateOptions(containerWidth, font, ellipsis, options);

    for (var i = 0, len = textLines.length; i < len; i++) {
      textLines[i] = truncateSingleLine(textLines[i], options);
    }

    return textLines.join('\n');
  }

  function prepareTruncateOptions(containerWidth, font, ellipsis, options) {
    options = options || {};
    var preparedOpts = extend({}, options);
    preparedOpts.font = font;
    ellipsis = retrieve2(ellipsis, '...');
    preparedOpts.maxIterations = retrieve2(options.maxIterations, 2);
    var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0);
    preparedOpts.cnCharWidth = getWidth('国', font);
    var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font);
    preparedOpts.placeholder = retrieve2(options.placeholder, '');
    var contentWidth = containerWidth = Math.max(0, containerWidth - 1);

    for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
      contentWidth -= ascCharWidth;
    }

    var ellipsisWidth = getWidth(ellipsis, font);

    if (ellipsisWidth > contentWidth) {
      ellipsis = '';
      ellipsisWidth = 0;
    }

    contentWidth = containerWidth - ellipsisWidth;
    preparedOpts.ellipsis = ellipsis;
    preparedOpts.ellipsisWidth = ellipsisWidth;
    preparedOpts.contentWidth = contentWidth;
    preparedOpts.containerWidth = containerWidth;
    return preparedOpts;
  }

  function truncateSingleLine(textLine, options) {
    var containerWidth = options.containerWidth;
    var font = options.font;
    var contentWidth = options.contentWidth;

    if (!containerWidth) {
      return '';
    }

    var lineWidth = getWidth(textLine, font);

    if (lineWidth <= containerWidth) {
      return textLine;
    }

    for (var j = 0;; j++) {
      if (lineWidth <= contentWidth || j >= options.maxIterations) {
        textLine += options.ellipsis;
        break;
      }

      var subLength = j === 0 ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) : lineWidth > 0 ? Math.floor(textLine.length * contentWidth / lineWidth) : 0;
      textLine = textLine.substr(0, subLength);
      lineWidth = getWidth(textLine, font);
    }

    if (textLine === '') {
      textLine = options.placeholder;
    }

    return textLine;
  }

  function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
    var width = 0;
    var i = 0;

    for (var len = text.length; i < len && width < contentWidth; i++) {
      var charCode = text.charCodeAt(i);
      width += 0 <= charCode && charCode <= 127 ? ascCharWidth : cnCharWidth;
    }

    return i;
  }

  function parsePlainText(text, style) {
    text != null && (text += '');
    var overflow = style.overflow;
    var padding = style.padding;
    var font = style.font;
    var truncate = overflow === 'truncate';
    var calculatedLineHeight = getLineHeight(font);
    var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight);
    var truncateLineOverflow = style.lineOverflow === 'truncate';
    var width = style.width;
    var lines;

    if (width != null && overflow === 'break' || overflow === 'breakAll') {
      lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : [];
    } else {
      lines = text ? text.split('\n') : [];
    }

    var contentHeight = lines.length * lineHeight;
    var height = retrieve2(style.height, contentHeight);

    if (contentHeight > height && truncateLineOverflow) {
      var lineCount = Math.floor(height / lineHeight);
      lines = lines.slice(0, lineCount);
    }

    var outerHeight = height;
    var outerWidth = width;

    if (padding) {
      outerHeight += padding[0] + padding[2];

      if (outerWidth != null) {
        outerWidth += padding[1] + padding[3];
      }
    }

    if (text && truncate && outerWidth != null) {
      var options = prepareTruncateOptions(width, font, style.ellipsis, {
        minChar: style.truncateMinChar,
        placeholder: style.placeholder
      });

      for (var i = 0; i < lines.length; i++) {
        lines[i] = truncateSingleLine(lines[i], options);
      }
    }

    if (width == null) {
      var maxWidth = 0;

      for (var i = 0; i < lines.length; i++) {
        maxWidth = Math.max(getWidth(lines[i], font), maxWidth);
      }

      width = maxWidth;
    }

    return {
      lines: lines,
      height: height,
      outerHeight: outerHeight,
      lineHeight: lineHeight,
      calculatedLineHeight: calculatedLineHeight,
      contentHeight: contentHeight,
      width: width
    };
  }

  var RichTextToken = function () {
    function RichTextToken() {}

    return RichTextToken;
  }();

  var RichTextLine = function () {
    function RichTextLine(tokens) {
      this.tokens = [];

      if (tokens) {
        this.tokens = tokens;
      }
    }

    return RichTextLine;
  }();

  var RichTextContentBlock = function () {
    function RichTextContentBlock() {
      this.width = 0;
      this.height = 0;
      this.contentWidth = 0;
      this.contentHeight = 0;
      this.outerWidth = 0;
      this.outerHeight = 0;
      this.lines = [];
    }

    return RichTextContentBlock;
  }();

  function parseRichText(text, style) {
    var contentBlock = new RichTextContentBlock();
    text != null && (text += '');

    if (!text) {
      return contentBlock;
    }

    var topWidth = style.width;
    var topHeight = style.height;
    var overflow = style.overflow;
    var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null ? {
      width: topWidth,
      accumWidth: 0,
      breakAll: overflow === 'breakAll'
    } : null;
    var lastIndex = STYLE_REG.lastIndex = 0;
    var result;

    while ((result = STYLE_REG.exec(text)) != null) {
      var matchedIndex = result.index;

      if (matchedIndex > lastIndex) {
        pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo);
      }

      pushTokens(contentBlock, result[2], style, wrapInfo, result[1]);
      lastIndex = STYLE_REG.lastIndex;
    }

    if (lastIndex < text.length) {
      pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo);
    }

    var pendingList = [];
    var calculatedHeight = 0;
    var calculatedWidth = 0;
    var stlPadding = style.padding;
    var truncate = overflow === 'truncate';
    var truncateLine = style.lineOverflow === 'truncate';

    function finishLine(line, lineWidth, lineHeight) {
      line.width = lineWidth;
      line.lineHeight = lineHeight;
      calculatedHeight += lineHeight;
      calculatedWidth = Math.max(calculatedWidth, lineWidth);
    }

    outer: for (var i = 0; i < contentBlock.lines.length; i++) {
      var line = contentBlock.lines[i];
      var lineHeight = 0;
      var lineWidth = 0;

      for (var j = 0; j < line.tokens.length; j++) {
        var token = line.tokens[j];
        var tokenStyle = token.styleName && style.rich[token.styleName] || {};
        var textPadding = token.textPadding = tokenStyle.padding;
        var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0;
        var font = token.font = tokenStyle.font || style.font;
        token.contentHeight = getLineHeight(font);
        var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight);
        token.innerHeight = tokenHeight;
        textPadding && (tokenHeight += textPadding[0] + textPadding[2]);
        token.height = tokenHeight;
        token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight);
        token.align = tokenStyle && tokenStyle.align || style.align;
        token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle';

        if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) {
          if (j > 0) {
            line.tokens = line.tokens.slice(0, j);
            finishLine(line, lineWidth, lineHeight);
            contentBlock.lines = contentBlock.lines.slice(0, i + 1);
          } else {
            contentBlock.lines = contentBlock.lines.slice(0, i);
          }

          break outer;
        }

        var styleTokenWidth = tokenStyle.width;
        var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto';

        if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') {
          token.percentWidth = styleTokenWidth;
          pendingList.push(token);
          token.contentWidth = getWidth(token.text, font);
        } else {
          if (tokenWidthNotSpecified) {
            var textBackgroundColor = tokenStyle.backgroundColor;
            var bgImg = textBackgroundColor && textBackgroundColor.image;

            if (bgImg) {
              bgImg = findExistImage(bgImg);

              if (isImageReady(bgImg)) {
                token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height);
              }
            }
          }

          var remainTruncWidth = truncate && topWidth != null ? topWidth - lineWidth : null;

          if (remainTruncWidth != null && remainTruncWidth < token.width) {
            if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) {
              token.text = '';
              token.width = token.contentWidth = 0;
            } else {
              token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, {
                minChar: style.truncateMinChar
              });
              token.width = token.contentWidth = getWidth(token.text, font);
            }
          } else {
            token.contentWidth = getWidth(token.text, font);
          }
        }

        token.width += paddingH;
        lineWidth += token.width;
        tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight));
      }

      finishLine(line, lineWidth, lineHeight);
    }

    contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth);
    contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight);
    contentBlock.contentHeight = calculatedHeight;
    contentBlock.contentWidth = calculatedWidth;

    if (stlPadding) {
      contentBlock.outerWidth += stlPadding[1] + stlPadding[3];
      contentBlock.outerHeight += stlPadding[0] + stlPadding[2];
    }

    for (var i = 0; i < pendingList.length; i++) {
      var token = pendingList[i];
      var percentWidth = token.percentWidth;
      token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width;
    }

    return contentBlock;
  }

  function pushTokens(block, str, style, wrapInfo, styleName) {
    var isEmptyStr = str === '';
    var tokenStyle = styleName && style.rich[styleName] || {};
    var lines = block.lines;
    var font = tokenStyle.font || style.font;
    var newLine = false;
    var strLines;
    var linesWidths;

    if (wrapInfo) {
      var tokenPadding = tokenStyle.padding;
      var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0;

      if (tokenStyle.width != null && tokenStyle.width !== 'auto') {
        var outerWidth_1 = parsePercent$1(tokenStyle.width, wrapInfo.width) + tokenPaddingH;

        if (lines.length > 0) {
          if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) {
            strLines = str.split('\n');
            newLine = true;
          }
        }

        wrapInfo.accumWidth = outerWidth_1;
      } else {
        var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth);
        wrapInfo.accumWidth = res.accumWidth + tokenPaddingH;
        linesWidths = res.linesWidths;
        strLines = res.lines;
      }
    } else {
      strLines = str.split('\n');
    }

    for (var i = 0; i < strLines.length; i++) {
      var text = strLines[i];
      var token = new RichTextToken();
      token.styleName = styleName;
      token.text = text;
      token.isLineHolder = !text && !isEmptyStr;

      if (typeof tokenStyle.width === 'number') {
        token.width = tokenStyle.width;
      } else {
        token.width = linesWidths ? linesWidths[i] : getWidth(text, font);
      }

      if (!i && !newLine) {
        var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens;
        var tokensLen = tokens.length;
        tokensLen === 1 && tokens[0].isLineHolder ? tokens[0] = token : (text || !tokensLen || isEmptyStr) && tokens.push(token);
      } else {
        lines.push(new RichTextLine([token]));
      }
    }
  }

  function isLatin(ch) {
    var code = ch.charCodeAt(0);
    return code >= 0x21 && code <= 0xFF;
  }

  var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) {
    obj[ch] = true;
    return obj;
  }, {});

  function isWordBreakChar(ch) {
    if (isLatin(ch)) {
      if (breakCharMap[ch]) {
        return true;
      }

      return false;
    }

    return true;
  }

  function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) {
    var lines = [];
    var linesWidths = [];
    var line = '';
    var currentWord = '';
    var currentWordWidth = 0;
    var accumWidth = 0;

    for (var i = 0; i < text.length; i++) {
      var ch = text.charAt(i);

      if (ch === '\n') {
        if (currentWord) {
          line += currentWord;
          accumWidth += currentWordWidth;
        }

        lines.push(line);
        linesWidths.push(accumWidth);
        line = '';
        currentWord = '';
        currentWordWidth = 0;
        accumWidth = 0;
        continue;
      }

      var chWidth = getWidth(ch, font);
      var inWord = isBreakAll ? false : !isWordBreakChar(ch);

      if (!lines.length ? lastAccumWidth + accumWidth + chWidth > lineWidth : accumWidth + chWidth > lineWidth) {
        if (!accumWidth) {
          if (inWord) {
            lines.push(currentWord);
            linesWidths.push(currentWordWidth);
            currentWord = ch;
            currentWordWidth = chWidth;
          } else {
            lines.push(ch);
            linesWidths.push(chWidth);
          }
        } else if (line || currentWord) {
          if (inWord) {
            if (!line) {
              line = currentWord;
              currentWord = '';
              currentWordWidth = 0;
              accumWidth = currentWordWidth;
            }

            lines.push(line);
            linesWidths.push(accumWidth - currentWordWidth);
            currentWord += ch;
            currentWordWidth += chWidth;
            line = '';
            accumWidth = currentWordWidth;
          } else {
            if (currentWord) {
              line += currentWord;
              accumWidth += currentWordWidth;
              currentWord = '';
              currentWordWidth = 0;
            }

            lines.push(line);
            linesWidths.push(accumWidth);
            line = ch;
            accumWidth = chWidth;
          }
        }

        continue;
      }

      accumWidth += chWidth;

      if (inWord) {
        currentWord += ch;
        currentWordWidth += chWidth;
      } else {
        if (currentWord) {
          line += currentWord;
          currentWord = '';
          currentWordWidth = 0;
        }

        line += ch;
      }
    }

    if (!lines.length && !line) {
      line = text;
      currentWord = '';
      currentWordWidth = 0;
    }

    if (currentWord) {
      line += currentWord;
    }

    if (line) {
      lines.push(line);
      linesWidths.push(accumWidth);
    }

    if (lines.length === 1) {
      accumWidth += lastAccumWidth;
    }

    return {
      accumWidth: accumWidth,
      lines: lines,
      linesWidths: linesWidths
    };
  }

  function parsePercent$1(value, maxValue) {
    if (typeof value === 'string') {
      if (value.lastIndexOf('%') >= 0) {
        return parseFloat(value) / 100 * maxValue;
      }

      return parseFloat(value);
    }

    return value;
  }

  var DEFAULT_RICH_TEXT_COLOR = {
    fill: '#000'
  };
  var DEFAULT_STROKE_LINE_WIDTH = 2;
  var DEFAULT_TEXT_ANIMATION_PROPS = {
    style: defaults({
      fill: true,
      stroke: true,
      fillOpacity: true,
      strokeOpacity: true,
      lineWidth: true,
      fontSize: true,
      lineHeight: true,
      width: true,
      height: true,
      textShadowColor: true,
      textShadowBlur: true,
      textShadowOffsetX: true,
      textShadowOffsetY: true,
      backgroundColor: true,
      padding: true,
      borderColor: true,
      borderWidth: true,
      borderRadius: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
  };

  var ZRText = function (_super) {
    __extends(ZRText, _super);

    function ZRText(opts) {
      var _this = _super.call(this) || this;

      _this.type = 'text';
      _this._children = [];
      _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR;

      _this.attr(opts);

      return _this;
    }

    ZRText.prototype.childrenRef = function () {
      return this._children;
    };

    ZRText.prototype.update = function () {
      if (this.styleChanged()) {
        this._updateSubTexts();
      }

      for (var i = 0; i < this._children.length; i++) {
        var child = this._children[i];
        child.zlevel = this.zlevel;
        child.z = this.z;
        child.z2 = this.z2;
        child.culling = this.culling;
        child.cursor = this.cursor;
        child.invisible = this.invisible;
      }

      var attachedTransform = this.attachedTransform;

      if (attachedTransform) {
        attachedTransform.updateTransform();
        var m = attachedTransform.transform;

        if (m) {
          this.transform = this.transform || [];
          copy$1(this.transform, m);
        } else {
          this.transform = null;
        }
      } else {
        _super.prototype.update.call(this);
      }
    };

    ZRText.prototype.getComputedTransform = function () {
      if (this.__hostTarget) {
        this.__hostTarget.getComputedTransform();

        this.__hostTarget.updateInnerText(true);
      }

      return this.attachedTransform ? this.attachedTransform.getComputedTransform() : _super.prototype.getComputedTransform.call(this);
    };

    ZRText.prototype._updateSubTexts = function () {
      this._childCursor = 0;
      normalizeTextStyle(this.style);
      this.style.rich ? this._updateRichTexts() : this._updatePlainTexts();
      this._children.length = this._childCursor;
      this.styleUpdated();
    };

    ZRText.prototype.addSelfToZr = function (zr) {
      _super.prototype.addSelfToZr.call(this, zr);

      for (var i = 0; i < this._children.length; i++) {
        this._children[i].__zr = zr;
      }
    };

    ZRText.prototype.removeSelfFromZr = function (zr) {
      _super.prototype.removeSelfFromZr.call(this, zr);

      for (var i = 0; i < this._children.length; i++) {
        this._children[i].__zr = null;
      }
    };

    ZRText.prototype.getBoundingRect = function () {
      if (this.styleChanged()) {
        this._updateSubTexts();
      }

      if (!this._rect) {
        var tmpRect = new BoundingRect(0, 0, 0, 0);
        var children = this._children;
        var tmpMat = [];
        var rect = null;

        for (var i = 0; i < children.length; i++) {
          var child = children[i];
          var childRect = child.getBoundingRect();
          var transform = child.getLocalTransform(tmpMat);

          if (transform) {
            tmpRect.copy(childRect);
            tmpRect.applyTransform(transform);
            rect = rect || tmpRect.clone();
            rect.union(tmpRect);
          } else {
            rect = rect || childRect.clone();
            rect.union(childRect);
          }
        }

        this._rect = rect || tmpRect;
      }

      return this._rect;
    };

    ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) {
      this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR;
    };

    ZRText.prototype.setTextContent = function (textContent) {
      throw new Error('Can\'t attach text on another text');
    };

    ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) {
      if (!sourceStyle) {
        return targetStyle;
      }

      var sourceRich = sourceStyle.rich;
      var targetRich = targetStyle.rich || sourceRich && {};
      extend(targetStyle, sourceStyle);

      if (sourceRich && targetRich) {
        this._mergeRich(targetRich, sourceRich);

        targetStyle.rich = targetRich;
      } else if (targetRich) {
        targetStyle.rich = targetRich;
      }

      return targetStyle;
    };

    ZRText.prototype._mergeRich = function (targetRich, sourceRich) {
      var richNames = keys(sourceRich);

      for (var i = 0; i < richNames.length; i++) {
        var richName = richNames[i];
        targetRich[richName] = targetRich[richName] || {};
        extend(targetRich[richName], sourceRich[richName]);
      }
    };

    ZRText.prototype.getAnimationStyleProps = function () {
      return DEFAULT_TEXT_ANIMATION_PROPS;
    };

    ZRText.prototype._getOrCreateChild = function (Ctor) {
      var child = this._children[this._childCursor];

      if (!child || !(child instanceof Ctor)) {
        child = new Ctor();
      }

      this._children[this._childCursor++] = child;
      child.__zr = this.__zr;
      child.parent = this;
      return child;
    };

    ZRText.prototype._updatePlainTexts = function () {
      var style = this.style;
      var textFont = style.font || DEFAULT_FONT;
      var textPadding = style.padding;
      var text = getStyleText(style);
      var contentBlock = parsePlainText(text, style);
      var needDrawBg = needDrawBackground(style);
      var bgColorDrawn = !!style.backgroundColor;
      var outerHeight = contentBlock.outerHeight;
      var textLines = contentBlock.lines;
      var lineHeight = contentBlock.lineHeight;
      var defaultStyle = this._defaultStyle;
      var baseX = style.x || 0;
      var baseY = style.y || 0;
      var textAlign = style.align || defaultStyle.align || 'left';
      var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top';
      var textX = baseX;
      var textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign);

      if (needDrawBg || textPadding) {
        var outerWidth_1 = contentBlock.width;
        textPadding && (outerWidth_1 += textPadding[1] + textPadding[3]);
        var boxX = adjustTextX(baseX, outerWidth_1, textAlign);
        var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
        needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth_1, outerHeight);
      }

      textY += lineHeight / 2;

      if (textPadding) {
        textX = getTextXForPadding(baseX, textAlign, textPadding);

        if (verticalAlign === 'top') {
          textY += textPadding[0];
        } else if (verticalAlign === 'bottom') {
          textY -= textPadding[2];
        }
      }

      var defaultLineWidth = 0;
      var useDefaultFill = false;
      var textFill = getFill('fill' in style ? style.fill : (useDefaultFill = true, defaultStyle.fill));
      var textStroke = getStroke('stroke' in style ? style.stroke : !bgColorDrawn && (!defaultStyle.autoStroke || useDefaultFill) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) : null);
      var hasShadow = style.textShadowBlur > 0;
      var fixedBoundingRect = style.width != null && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll');
      var calculatedLineHeight = contentBlock.calculatedLineHeight;

      for (var i = 0; i < textLines.length; i++) {
        var el = this._getOrCreateChild(TSpan);

        var subElStyle = el.createStyle();
        el.useStyle(subElStyle);
        subElStyle.text = textLines[i];
        subElStyle.x = textX;
        subElStyle.y = textY;

        if (textAlign) {
          subElStyle.textAlign = textAlign;
        }

        subElStyle.textBaseline = 'middle';
        subElStyle.opacity = style.opacity;
        subElStyle.strokeFirst = true;

        if (hasShadow) {
          subElStyle.shadowBlur = style.textShadowBlur || 0;
          subElStyle.shadowColor = style.textShadowColor || 'transparent';
          subElStyle.shadowOffsetX = style.textShadowOffsetX || 0;
          subElStyle.shadowOffsetY = style.textShadowOffsetY || 0;
        }

        if (textStroke) {
          subElStyle.stroke = textStroke;
          subElStyle.lineWidth = style.lineWidth || defaultLineWidth;
          subElStyle.lineDash = style.lineDash;
          subElStyle.lineDashOffset = style.lineDashOffset || 0;
        }

        if (textFill) {
          subElStyle.fill = textFill;
        }

        subElStyle.font = textFont;
        textY += lineHeight;

        if (fixedBoundingRect) {
          el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), style.width, calculatedLineHeight));
        }
      }
    };

    ZRText.prototype._updateRichTexts = function () {
      var style = this.style;
      var text = getStyleText(style);
      var contentBlock = parseRichText(text, style);
      var contentWidth = contentBlock.width;
      var outerWidth = contentBlock.outerWidth;
      var outerHeight = contentBlock.outerHeight;
      var textPadding = style.padding;
      var baseX = style.x || 0;
      var baseY = style.y || 0;
      var defaultStyle = this._defaultStyle;
      var textAlign = style.align || defaultStyle.align;
      var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign;
      var boxX = adjustTextX(baseX, outerWidth, textAlign);
      var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
      var xLeft = boxX;
      var lineTop = boxY;

      if (textPadding) {
        xLeft += textPadding[3];
        lineTop += textPadding[0];
      }

      var xRight = xLeft + contentWidth;

      if (needDrawBackground(style)) {
        this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight);
      }

      var bgColorDrawn = !!style.backgroundColor;

      for (var i = 0; i < contentBlock.lines.length; i++) {
        var line = contentBlock.lines[i];
        var tokens = line.tokens;
        var tokenCount = tokens.length;
        var lineHeight = line.lineHeight;
        var remainedWidth = line.width;
        var leftIndex = 0;
        var lineXLeft = xLeft;
        var lineXRight = xRight;
        var rightIndex = tokenCount - 1;
        var token = void 0;

        while (leftIndex < tokenCount && (token = tokens[leftIndex], !token.align || token.align === 'left')) {
          this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn);

          remainedWidth -= token.width;
          lineXLeft += token.width;
          leftIndex++;
        }

        while (rightIndex >= 0 && (token = tokens[rightIndex], token.align === 'right')) {
          this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn);

          remainedWidth -= token.width;
          lineXRight -= token.width;
          rightIndex--;
        }

        lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2;

        while (leftIndex <= rightIndex) {
          token = tokens[leftIndex];

          this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn);

          lineXLeft += token.width;
          leftIndex++;
        }

        lineTop += lineHeight;
      }
    };

    ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) {
      var tokenStyle = style.rich[token.styleName] || {};
      tokenStyle.text = token.text;
      var verticalAlign = token.verticalAlign;
      var y = lineTop + lineHeight / 2;

      if (verticalAlign === 'top') {
        y = lineTop + token.height / 2;
      } else if (verticalAlign === 'bottom') {
        y = lineTop + lineHeight - token.height / 2;
      }

      var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle);
      needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right' ? x - token.width : textAlign === 'center' ? x - token.width / 2 : x, y - token.height / 2, token.width, token.height);
      var bgColorDrawn = !!tokenStyle.backgroundColor;
      var textPadding = token.textPadding;

      if (textPadding) {
        x = getTextXForPadding(x, textAlign, textPadding);
        y -= token.height / 2 - textPadding[0] - token.innerHeight / 2;
      }

      var el = this._getOrCreateChild(TSpan);

      var subElStyle = el.createStyle();
      el.useStyle(subElStyle);
      var defaultStyle = this._defaultStyle;
      var useDefaultFill = false;
      var defaultLineWidth = 0;
      var textFill = getStroke('fill' in tokenStyle ? tokenStyle.fill : 'fill' in style ? style.fill : (useDefaultFill = true, defaultStyle.fill));
      var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke : 'stroke' in style ? style.stroke : !bgColorDrawn && !parentBgColorDrawn && (!defaultStyle.autoStroke || useDefaultFill) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) : null);
      var hasShadow = tokenStyle.textShadowBlur > 0 || style.textShadowBlur > 0;
      subElStyle.text = token.text;
      subElStyle.x = x;
      subElStyle.y = y;

      if (hasShadow) {
        subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0;
        subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent';
        subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0;
        subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0;
      }

      subElStyle.textAlign = textAlign;
      subElStyle.textBaseline = 'middle';
      subElStyle.font = token.font || DEFAULT_FONT;
      subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1);

      if (textStroke) {
        subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth);
        subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash);
        subElStyle.lineDashOffset = style.lineDashOffset || 0;
        subElStyle.stroke = textStroke;
      }

      if (textFill) {
        subElStyle.fill = textFill;
      }

      var textWidth = token.contentWidth;
      var textHeight = token.contentHeight;
      el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight));
    };

    ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) {
      var textBackgroundColor = style.backgroundColor;
      var textBorderWidth = style.borderWidth;
      var textBorderColor = style.borderColor;
      var isPlainBg = isString(textBackgroundColor);
      var textBorderRadius = style.borderRadius;
      var self = this;
      var rectEl;
      var imgEl;

      if (isPlainBg || textBorderWidth && textBorderColor) {
        rectEl = this._getOrCreateChild(Rect);
        rectEl.useStyle(rectEl.createStyle());
        rectEl.style.fill = null;
        var rectShape = rectEl.shape;
        rectShape.x = x;
        rectShape.y = y;
        rectShape.width = width;
        rectShape.height = height;
        rectShape.r = textBorderRadius;
        rectEl.dirtyShape();
      }

      if (isPlainBg) {
        var rectStyle = rectEl.style;
        rectStyle.fill = textBackgroundColor || null;
        rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1);
      } else if (textBackgroundColor && textBackgroundColor.image) {
        imgEl = this._getOrCreateChild(ZRImage);

        imgEl.onload = function () {
          self.dirtyStyle();
        };

        var imgStyle = imgEl.style;
        imgStyle.image = textBackgroundColor.image;
        imgStyle.x = x;
        imgStyle.y = y;
        imgStyle.width = width;
        imgStyle.height = height;
      }

      if (textBorderWidth && textBorderColor) {
        var rectStyle = rectEl.style;
        rectStyle.lineWidth = textBorderWidth;
        rectStyle.stroke = textBorderColor;
        rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1);
        rectStyle.lineDash = style.borderDash;
        rectStyle.lineDashOffset = style.borderDashOffset || 0;
        rectEl.strokeContainThreshold = 0;

        if (rectEl.hasFill() && rectEl.hasStroke()) {
          rectStyle.strokeFirst = true;
          rectStyle.lineWidth *= 2;
        }
      }

      var commonStyle = (rectEl || imgEl).style;
      commonStyle.shadowBlur = style.shadowBlur || 0;
      commonStyle.shadowColor = style.shadowColor || 'transparent';
      commonStyle.shadowOffsetX = style.shadowOffsetX || 0;
      commonStyle.shadowOffsetY = style.shadowOffsetY || 0;
      commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1);
    };

    ZRText.makeFont = function (style) {
      var font = '';

      if (style.fontSize || style.fontFamily || style.fontWeight) {
        var fontSize = '';

        if (typeof style.fontSize === 'string' && (style.fontSize.indexOf('px') !== -1 || style.fontSize.indexOf('rem') !== -1 || style.fontSize.indexOf('em') !== -1)) {
          fontSize = style.fontSize;
        } else if (!isNaN(+style.fontSize)) {
          fontSize = style.fontSize + 'px';
        } else {
          fontSize = '12px';
        }

        font = [style.fontStyle, style.fontWeight, fontSize, style.fontFamily || 'sans-serif'].join(' ');
      }

      return font && trim(font) || style.textFont || style.font;
    };

    return ZRText;
  }(Displayable);

  var VALID_TEXT_ALIGN = {
    left: true,
    right: 1,
    center: 1
  };
  var VALID_TEXT_VERTICAL_ALIGN = {
    top: 1,
    bottom: 1,
    middle: 1
  };

  function normalizeTextStyle(style) {
    normalizeStyle(style);
    each(style.rich, normalizeStyle);
    return style;
  }

  function normalizeStyle(style) {
    if (style) {
      style.font = ZRText.makeFont(style);
      var textAlign = style.align;
      textAlign === 'middle' && (textAlign = 'center');
      style.align = textAlign == null || VALID_TEXT_ALIGN[textAlign] ? textAlign : 'left';
      var verticalAlign = style.verticalAlign;
      verticalAlign === 'center' && (verticalAlign = 'middle');
      style.verticalAlign = verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign] ? verticalAlign : 'top';
      var textPadding = style.padding;

      if (textPadding) {
        style.padding = normalizeCssArray(style.padding);
      }
    }
  }

  function getStroke(stroke, lineWidth) {
    return stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none' ? null : stroke.image || stroke.colorStops ? '#000' : stroke;
  }

  function getFill(fill) {
    return fill == null || fill === 'none' ? null : fill.image || fill.colorStops ? '#000' : fill;
  }

  function getTextXForPadding(x, textAlign, textPadding) {
    return textAlign === 'right' ? x - textPadding[1] : textAlign === 'center' ? x + textPadding[3] / 2 - textPadding[1] / 2 : x + textPadding[3];
  }

  function getStyleText(style) {
    var text = style.text;
    text != null && (text += '');
    return text;
  }

  function needDrawBackground(style) {
    return !!(style.backgroundColor || style.borderWidth && style.borderColor);
  }

  var ArcShape = function () {
    function ArcShape() {
      this.cx = 0;
      this.cy = 0;
      this.r = 0;
      this.startAngle = 0;
      this.endAngle = Math.PI * 2;
      this.clockwise = true;
    }

    return ArcShape;
  }();

  var Arc = function (_super) {
    __extends(Arc, _super);

    function Arc(opts) {
      return _super.call(this, opts) || this;
    }

    Arc.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    Arc.prototype.getDefaultShape = function () {
      return new ArcShape();
    };

    Arc.prototype.buildPath = function (ctx, shape) {
      var x = shape.cx;
      var y = shape.cy;
      var r = Math.max(shape.r, 0);
      var startAngle = shape.startAngle;
      var endAngle = shape.endAngle;
      var clockwise = shape.clockwise;
      var unitX = Math.cos(startAngle);
      var unitY = Math.sin(startAngle);
      ctx.moveTo(unitX * r + x, unitY * r + y);
      ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
    };

    return Arc;
  }(Path);

  Arc.prototype.type = 'arc';
  var out = [];

  var BezierCurveShape = function () {
    function BezierCurveShape() {
      this.x1 = 0;
      this.y1 = 0;
      this.x2 = 0;
      this.y2 = 0;
      this.cpx1 = 0;
      this.cpy1 = 0;
      this.percent = 1;
    }

    return BezierCurveShape;
  }();

  function someVectorAt(shape, t, isTangent) {
    var cpx2 = shape.cpx2;
    var cpy2 = shape.cpy2;

    if (cpx2 === null || cpy2 === null) {
      return [(isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)];
    } else {
      return [(isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)];
    }
  }

  var BezierCurve = function (_super) {
    __extends(BezierCurve, _super);

    function BezierCurve(opts) {
      return _super.call(this, opts) || this;
    }

    BezierCurve.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    BezierCurve.prototype.getDefaultShape = function () {
      return new BezierCurveShape();
    };

    BezierCurve.prototype.buildPath = function (ctx, shape) {
      var x1 = shape.x1;
      var y1 = shape.y1;
      var x2 = shape.x2;
      var y2 = shape.y2;
      var cpx1 = shape.cpx1;
      var cpy1 = shape.cpy1;
      var cpx2 = shape.cpx2;
      var cpy2 = shape.cpy2;
      var percent = shape.percent;

      if (percent === 0) {
        return;
      }

      ctx.moveTo(x1, y1);

      if (cpx2 == null || cpy2 == null) {
        if (percent < 1) {
          quadraticSubdivide(x1, cpx1, x2, percent, out);
          cpx1 = out[1];
          x2 = out[2];
          quadraticSubdivide(y1, cpy1, y2, percent, out);
          cpy1 = out[1];
          y2 = out[2];
        }

        ctx.quadraticCurveTo(cpx1, cpy1, x2, y2);
      } else {
        if (percent < 1) {
          cubicSubdivide(x1, cpx1, cpx2, x2, percent, out);
          cpx1 = out[1];
          cpx2 = out[2];
          x2 = out[3];
          cubicSubdivide(y1, cpy1, cpy2, y2, percent, out);
          cpy1 = out[1];
          cpy2 = out[2];
          y2 = out[3];
        }

        ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2);
      }
    };

    BezierCurve.prototype.pointAt = function (t) {
      return someVectorAt(this.shape, t, false);
    };

    BezierCurve.prototype.tangentAt = function (t) {
      var p = someVectorAt(this.shape, t, true);
      return normalize(p, p);
    };

    return BezierCurve;
  }(Path);

  BezierCurve.prototype.type = 'bezier-curve';

  var DropletShape = function () {
    function DropletShape() {
      this.cx = 0;
      this.cy = 0;
      this.width = 0;
      this.height = 0;
    }

    return DropletShape;
  }();

  var Droplet = function (_super) {
    __extends(Droplet, _super);

    function Droplet(opts) {
      return _super.call(this, opts) || this;
    }

    Droplet.prototype.getDefaultShape = function () {
      return new DropletShape();
    };

    Droplet.prototype.buildPath = function (ctx, shape) {
      var x = shape.cx;
      var y = shape.cy;
      var a = shape.width;
      var b = shape.height;
      ctx.moveTo(x, y + a);
      ctx.bezierCurveTo(x + a, y + a, x + a * 3 / 2, y - a / 3, x, y - b);
      ctx.bezierCurveTo(x - a * 3 / 2, y - a / 3, x - a, y + a, x, y + a);
      ctx.closePath();
    };

    return Droplet;
  }(Path);

  Droplet.prototype.type = 'droplet';

  var HeartShape = function () {
    function HeartShape() {
      this.cx = 0;
      this.cy = 0;
      this.width = 0;
      this.height = 0;
    }

    return HeartShape;
  }();

  var Heart = function (_super) {
    __extends(Heart, _super);

    function Heart(opts) {
      return _super.call(this, opts) || this;
    }

    Heart.prototype.getDefaultShape = function () {
      return new HeartShape();
    };

    Heart.prototype.buildPath = function (ctx, shape) {
      var x = shape.cx;
      var y = shape.cy;
      var a = shape.width;
      var b = shape.height;
      ctx.moveTo(x, y);
      ctx.bezierCurveTo(x + a / 2, y - b * 2 / 3, x + a * 2, y + b / 3, x, y + b);
      ctx.bezierCurveTo(x - a * 2, y + b / 3, x - a / 2, y - b * 2 / 3, x, y);
    };

    return Heart;
  }(Path);

  Heart.prototype.type = 'heart';
  var PI$3 = Math.PI;
  var sin = Math.sin;
  var cos = Math.cos;

  var IsogonShape = function () {
    function IsogonShape() {
      this.x = 0;
      this.y = 0;
      this.r = 0;
      this.n = 0;
    }

    return IsogonShape;
  }();

  var Isogon = function (_super) {
    __extends(Isogon, _super);

    function Isogon(opts) {
      return _super.call(this, opts) || this;
    }

    Isogon.prototype.getDefaultShape = function () {
      return new IsogonShape();
    };

    Isogon.prototype.buildPath = function (ctx, shape) {
      var n = shape.n;

      if (!n || n < 2) {
        return;
      }

      var x = shape.x;
      var y = shape.y;
      var r = shape.r;
      var dStep = 2 * PI$3 / n;
      var deg = -PI$3 / 2;
      ctx.moveTo(x + r * cos(deg), y + r * sin(deg));

      for (var i = 0, end = n - 1; i < end; i++) {
        deg += dStep;
        ctx.lineTo(x + r * cos(deg), y + r * sin(deg));
      }

      ctx.closePath();
      return;
    };

    return Isogon;
  }(Path);

  Isogon.prototype.type = 'isogon';

  var RingShape = function () {
    function RingShape() {
      this.cx = 0;
      this.cy = 0;
      this.r = 0;
      this.r0 = 0;
    }

    return RingShape;
  }();

  var Ring = function (_super) {
    __extends(Ring, _super);

    function Ring(opts) {
      return _super.call(this, opts) || this;
    }

    Ring.prototype.getDefaultShape = function () {
      return new RingShape();
    };

    Ring.prototype.buildPath = function (ctx, shape) {
      var x = shape.cx;
      var y = shape.cy;
      var PI2 = Math.PI * 2;
      ctx.moveTo(x + shape.r, y);
      ctx.arc(x, y, shape.r, 0, PI2, false);
      ctx.moveTo(x + shape.r0, y);
      ctx.arc(x, y, shape.r0, 0, PI2, true);
    };

    return Ring;
  }(Path);

  Ring.prototype.type = 'ring';
  var sin$1 = Math.sin;
  var cos$1 = Math.cos;
  var radian = Math.PI / 180;

  var RoseShape = function () {
    function RoseShape() {
      this.cx = 0;
      this.cy = 0;
      this.r = [];
      this.k = 0;
      this.n = 1;
    }

    return RoseShape;
  }();

  var Rose = function (_super) {
    __extends(Rose, _super);

    function Rose(opts) {
      return _super.call(this, opts) || this;
    }

    Rose.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    Rose.prototype.getDefaultShape = function () {
      return new RoseShape();
    };

    Rose.prototype.buildPath = function (ctx, shape) {
      var R = shape.r;
      var k = shape.k;
      var n = shape.n;
      var x0 = shape.cx;
      var y0 = shape.cy;
      var x;
      var y;
      var r;
      ctx.moveTo(x0, y0);

      for (var i = 0, len = R.length; i < len; i++) {
        r = R[i];

        for (var j = 0; j <= 360 * n; j++) {
          x = r * sin$1(k / n * j % 360 * radian) * cos$1(j * radian) + x0;
          y = r * sin$1(k / n * j % 360 * radian) * sin$1(j * radian) + y0;
          ctx.lineTo(x, y);
        }
      }
    };

    return Rose;
  }(Path);

  Rose.prototype.type = 'rose';
  var PI$4 = Math.PI;
  var cos$2 = Math.cos;
  var sin$2 = Math.sin;

  var StarShape = function () {
    function StarShape() {
      this.cx = 0;
      this.cy = 0;
      this.n = 3;
      this.r = 0;
    }

    return StarShape;
  }();

  var Star = function (_super) {
    __extends(Star, _super);

    function Star(opts) {
      return _super.call(this, opts) || this;
    }

    Star.prototype.getDefaultShape = function () {
      return new StarShape();
    };

    Star.prototype.buildPath = function (ctx, shape) {
      var n = shape.n;

      if (!n || n < 2) {
        return;
      }

      var x = shape.cx;
      var y = shape.cy;
      var r = shape.r;
      var r0 = shape.r0;

      if (r0 == null) {
        r0 = n > 4 ? r * cos$2(2 * PI$4 / n) / cos$2(PI$4 / n) : r / 3;
      }

      var dStep = PI$4 / n;
      var deg = -PI$4 / 2;
      var xStart = x + r * cos$2(deg);
      var yStart = y + r * sin$2(deg);
      deg += dStep;
      ctx.moveTo(xStart, yStart);

      for (var i = 0, end = n * 2 - 1, ri = void 0; i < end; i++) {
        ri = i % 2 === 0 ? r0 : r;
        ctx.lineTo(x + ri * cos$2(deg), y + ri * sin$2(deg));
        deg += dStep;
      }

      ctx.closePath();
    };

    return Star;
  }(Path);

  Star.prototype.type = 'star';
  var cos$3 = Math.cos;
  var sin$3 = Math.sin;

  var TrochoidShape = function () {
    function TrochoidShape() {
      this.cx = 0;
      this.cy = 0;
      this.r = 0;
      this.r0 = 0;
      this.d = 0;
      this.location = 'out';
    }

    return TrochoidShape;
  }();

  var Trochoid = function (_super) {
    __extends(Trochoid, _super);

    function Trochoid(opts) {
      return _super.call(this, opts) || this;
    }

    Trochoid.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    Trochoid.prototype.getDefaultShape = function () {
      return new TrochoidShape();
    };

    Trochoid.prototype.buildPath = function (ctx, shape) {
      var R = shape.r;
      var r = shape.r0;
      var d = shape.d;
      var offsetX = shape.cx;
      var offsetY = shape.cy;
      var delta = shape.location === 'out' ? 1 : -1;
      var x1;
      var y1;
      var x2;
      var y2;

      if (shape.location && R <= r) {
        return;
      }

      var num = 0;
      var i = 1;
      var theta;
      x1 = (R + delta * r) * cos$3(0) - delta * d * cos$3(0) + offsetX;
      y1 = (R + delta * r) * sin$3(0) - d * sin$3(0) + offsetY;
      ctx.moveTo(x1, y1);

      do {
        num++;
      } while (r * num % (R + delta * r) !== 0);

      do {
        theta = Math.PI / 180 * i;
        x2 = (R + delta * r) * cos$3(theta) - delta * d * cos$3((R / r + delta) * theta) + offsetX;
        y2 = (R + delta * r) * sin$3(theta) - d * sin$3((R / r + delta) * theta) + offsetY;
        ctx.lineTo(x2, y2);
        i++;
      } while (i <= r * num / (R + delta * r) * 360);
    };

    return Trochoid;
  }(Path);

  Trochoid.prototype.type = 'trochoid';

  var RadialGradient = function (_super) {
    __extends(RadialGradient, _super);

    function RadialGradient(x, y, r, colorStops, globalCoord) {
      var _this = _super.call(this, colorStops) || this;

      _this.x = x == null ? 0.5 : x;
      _this.y = y == null ? 0.5 : y;
      _this.r = r == null ? 0.5 : r;
      _this.type = 'radial';
      _this.global = globalCoord || false;
      return _this;
    }

    return RadialGradient;
  }(Gradient);

  var extent = [0, 0];
  var extent2 = [0, 0];
  var minTv$1 = new Point();
  var maxTv$1 = new Point();

  var OrientedBoundingRect = function () {
    function OrientedBoundingRect(rect, transform) {
      this._corners = [];
      this._axes = [];
      this._origin = [0, 0];

      for (var i = 0; i < 4; i++) {
        this._corners[i] = new Point();
      }

      for (var i = 0; i < 2; i++) {
        this._axes[i] = new Point();
      }

      if (rect) {
        this.fromBoundingRect(rect, transform);
      }
    }

    OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) {
      var corners = this._corners;
      var axes = this._axes;
      var x = rect.x;
      var y = rect.y;
      var x2 = x + rect.width;
      var y2 = y + rect.height;
      corners[0].set(x, y);
      corners[1].set(x2, y);
      corners[2].set(x2, y2);
      corners[3].set(x, y2);

      if (transform) {
        for (var i = 0; i < 4; i++) {
          corners[i].transform(transform);
        }
      }

      Point.sub(axes[0], corners[1], corners[0]);
      Point.sub(axes[1], corners[3], corners[0]);
      axes[0].normalize();
      axes[1].normalize();

      for (var i = 0; i < 2; i++) {
        this._origin[i] = axes[i].dot(corners[0]);
      }
    };

    OrientedBoundingRect.prototype.intersect = function (other, mtv) {
      var overlapped = true;
      var noMtv = !mtv;
      minTv$1.set(Infinity, Infinity);
      maxTv$1.set(0, 0);

      if (!this._intersectCheckOneSide(this, other, minTv$1, maxTv$1, noMtv, 1)) {
        overlapped = false;

        if (noMtv) {
          return overlapped;
        }
      }

      if (!this._intersectCheckOneSide(other, this, minTv$1, maxTv$1, noMtv, -1)) {
        overlapped = false;

        if (noMtv) {
          return overlapped;
        }
      }

      if (!noMtv) {
        Point.copy(mtv, overlapped ? minTv$1 : maxTv$1);
      }

      return overlapped;
    };

    OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) {
      var overlapped = true;

      for (var i = 0; i < 2; i++) {
        var axis = this._axes[i];

        this._getProjMinMaxOnAxis(i, self._corners, extent);

        this._getProjMinMaxOnAxis(i, other._corners, extent2);

        if (extent[1] < extent2[0] || extent[0] > extent2[1]) {
          overlapped = false;

          if (noMtv) {
            return overlapped;
          }

          var dist0 = Math.abs(extent2[0] - extent[1]);
          var dist1 = Math.abs(extent[0] - extent2[1]);

          if (Math.min(dist0, dist1) > maxTv.len()) {
            if (dist0 < dist1) {
              Point.scale(maxTv, axis, -dist0 * inverse);
            } else {
              Point.scale(maxTv, axis, dist1 * inverse);
            }
          }
        } else if (minTv) {
          var dist0 = Math.abs(extent2[0] - extent[1]);
          var dist1 = Math.abs(extent[0] - extent2[1]);

          if (Math.min(dist0, dist1) < minTv.len()) {
            if (dist0 < dist1) {
              Point.scale(minTv, axis, dist0 * inverse);
            } else {
              Point.scale(minTv, axis, -dist1 * inverse);
            }
          }
        }
      }

      return overlapped;
    };

    OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) {
      var axis = this._axes[dim];
      var origin = this._origin;
      var proj = corners[0].dot(axis) + origin[dim];
      var min = proj;
      var max = proj;

      for (var i = 1; i < corners.length; i++) {
        var proj_1 = corners[i].dot(axis) + origin[dim];
        min = Math.min(proj_1, min);
        max = Math.max(proj_1, max);
      }

      out[0] = min;
      out[1] = max;
    };

    return OrientedBoundingRect;
  }();
  /*!
  * ZRender, a high performance 2d drawing library.
  *
  * Copyright (c) 2013, Baidu Inc.
  * All rights reserved.
  *
  * LICENSE
  * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
  */


  var useVML = !env.canvasSupported;
  var painterCtors = {};
  var instances = {};

  function delInstance(id) {
    delete instances[id];
  }

  function isDarkMode(backgroundColor) {
    if (!backgroundColor) {
      return false;
    }

    if (typeof backgroundColor === 'string') {
      return lum(backgroundColor, 1) < DARK_MODE_THRESHOLD;
    } else if (backgroundColor.colorStops) {
      var colorStops = backgroundColor.colorStops;
      var totalLum = 0;
      var len = colorStops.length;

      for (var i = 0; i < len; i++) {
        totalLum += lum(colorStops[i].color, 1);
      }

      totalLum /= len;
      return totalLum < DARK_MODE_THRESHOLD;
    }

    return false;
  }

  var ZRender = function () {
    function ZRender(id, dom, opts) {
      var _this = this;

      this._sleepAfterStill = 10;
      this._stillFrameAccum = 0;
      this._needsRefresh = true;
      this._needsRefreshHover = true;
      this._darkMode = false;
      opts = opts || {};
      this.dom = dom;
      this.id = id;
      var storage = new Storage();
      var rendererType = opts.renderer;

      if (useVML) {
        if (!painterCtors.vml) {
          throw new Error('You need to require \'zrender/vml/vml\' to support IE8');
        }

        rendererType = 'vml';
      } else if (!rendererType) {
        rendererType = 'canvas';
      }

      if (!painterCtors[rendererType]) {
        throw new Error("Renderer '" + rendererType + "' is not imported. Please import it first.");
      }

      opts.useDirtyRect = opts.useDirtyRect == null ? false : opts.useDirtyRect;
      var painter = new painterCtors[rendererType](dom, storage, opts, id);
      this.storage = storage;
      this.painter = painter;
      var handerProxy = !env.node && !env.worker ? new HandlerDomProxy(painter.getViewportRoot(), painter.root) : null;
      this.handler = new Handler(storage, painter, handerProxy, painter.root);
      this.animation = new Animation({
        stage: {
          update: function () {
            return _this._flush(true);
          }
        }
      });
      this.animation.start();
    }

    ZRender.prototype.add = function (el) {
      if (!el) {
        return;
      }

      this.storage.addRoot(el);
      el.addSelfToZr(this);
      this.refresh();
    };

    ZRender.prototype.remove = function (el) {
      if (!el) {
        return;
      }

      this.storage.delRoot(el);
      el.removeSelfFromZr(this);
      this.refresh();
    };

    ZRender.prototype.configLayer = function (zLevel, config) {
      if (this.painter.configLayer) {
        this.painter.configLayer(zLevel, config);
      }

      this.refresh();
    };

    ZRender.prototype.setBackgroundColor = function (backgroundColor) {
      if (this.painter.setBackgroundColor) {
        this.painter.setBackgroundColor(backgroundColor);
      }

      this.refresh();
      this._backgroundColor = backgroundColor;
      this._darkMode = isDarkMode(backgroundColor);
    };

    ZRender.prototype.getBackgroundColor = function () {
      return this._backgroundColor;
    };

    ZRender.prototype.setDarkMode = function (darkMode) {
      this._darkMode = darkMode;
    };

    ZRender.prototype.isDarkMode = function () {
      return this._darkMode;
    };

    ZRender.prototype.refreshImmediately = function (fromInside) {
      if (!fromInside) {
        this.animation.update(true);
      }

      this._needsRefresh = false;
      this.painter.refresh();
      this._needsRefresh = false;
    };

    ZRender.prototype.refresh = function () {
      this._needsRefresh = true;
      this.animation.start();
    };

    ZRender.prototype.flush = function () {
      this._flush(false);
    };

    ZRender.prototype._flush = function (fromInside) {
      var triggerRendered;
      var start = new Date().getTime();

      if (this._needsRefresh) {
        triggerRendered = true;
        this.refreshImmediately(fromInside);
      }

      if (this._needsRefreshHover) {
        triggerRendered = true;
        this.refreshHoverImmediately();
      }

      var end = new Date().getTime();

      if (triggerRendered) {
        this._stillFrameAccum = 0;
        this.trigger('rendered', {
          elapsedTime: end - start
        });
      } else if (this._sleepAfterStill > 0) {
        this._stillFrameAccum++;

        if (this._stillFrameAccum > this._sleepAfterStill) {
          this.animation.stop();
        }
      }
    };

    ZRender.prototype.setSleepAfterStill = function (stillFramesCount) {
      this._sleepAfterStill = stillFramesCount;
    };

    ZRender.prototype.wakeUp = function () {
      this.animation.start();
      this._stillFrameAccum = 0;
    };

    ZRender.prototype.addHover = function (el) {};

    ZRender.prototype.removeHover = function (el) {};

    ZRender.prototype.clearHover = function () {};

    ZRender.prototype.refreshHover = function () {
      this._needsRefreshHover = true;
    };

    ZRender.prototype.refreshHoverImmediately = function () {
      this._needsRefreshHover = false;

      if (this.painter.refreshHover && this.painter.getType() === 'canvas') {
        this.painter.refreshHover();
      }
    };

    ZRender.prototype.resize = function (opts) {
      opts = opts || {};
      this.painter.resize(opts.width, opts.height);
      this.handler.resize();
    };

    ZRender.prototype.clearAnimation = function () {
      this.animation.clear();
    };

    ZRender.prototype.getWidth = function () {
      return this.painter.getWidth();
    };

    ZRender.prototype.getHeight = function () {
      return this.painter.getHeight();
    };

    ZRender.prototype.pathToImage = function (e, dpr) {
      if (this.painter.pathToImage) {
        return this.painter.pathToImage(e, dpr);
      }
    };

    ZRender.prototype.setCursorStyle = function (cursorStyle) {
      this.handler.setCursorStyle(cursorStyle);
    };

    ZRender.prototype.findHover = function (x, y) {
      return this.handler.findHover(x, y);
    };

    ZRender.prototype.on = function (eventName, eventHandler, context) {
      this.handler.on(eventName, eventHandler, context);
      return this;
    };

    ZRender.prototype.off = function (eventName, eventHandler) {
      this.handler.off(eventName, eventHandler);
    };

    ZRender.prototype.trigger = function (eventName, event) {
      this.handler.trigger(eventName, event);
    };

    ZRender.prototype.clear = function () {
      var roots = this.storage.getRoots();

      for (var i = 0; i < roots.length; i++) {
        if (roots[i] instanceof Group) {
          roots[i].removeSelfFromZr(this);
        }
      }

      this.storage.delAllRoots();
      this.painter.clear();
    };

    ZRender.prototype.dispose = function () {
      this.animation.stop();
      this.clear();
      this.storage.dispose();
      this.painter.dispose();
      this.handler.dispose();
      this.animation = this.storage = this.painter = this.handler = null;
      delInstance(this.id);
    };

    return ZRender;
  }();

  function init(dom, opts) {
    var zr = new ZRender(guid(), dom, opts);
    instances[zr.id] = zr;
    return zr;
  }

  function dispose(zr) {
    zr.dispose();
  }

  function disposeAll() {
    for (var key in instances) {
      if (instances.hasOwnProperty(key)) {
        instances[key].dispose();
      }
    }

    instances = {};
  }

  function getInstance(id) {
    return instances[id];
  }

  function registerPainter(name, Ctor) {
    painterCtors[name] = Ctor;
  }

  var version = '5.0.1';
  var zrender = /*#__PURE__*/Object.freeze({
    __proto__: null,
    init: init,
    dispose: dispose,
    disposeAll: disposeAll,
    getInstance: getInstance,
    registerPainter: registerPainter,
    version: version
  });
  var RADIAN_EPSILON = 1e-4;

  function _trim(str) {
    return str.replace(/^\s+|\s+$/g, '');
  }

  function linearMap(val, domain, range, clamp) {
    var subDomain = domain[1] - domain[0];
    var subRange = range[1] - range[0];

    if (subDomain === 0) {
      return subRange === 0 ? range[0] : (range[0] + range[1]) / 2;
    }

    if (clamp) {
      if (subDomain > 0) {
        if (val <= domain[0]) {
          return range[0];
        } else if (val >= domain[1]) {
          return range[1];
        }
      } else {
        if (val >= domain[0]) {
          return range[0];
        } else if (val <= domain[1]) {
          return range[1];
        }
      }
    } else {
      if (val === domain[0]) {
        return range[0];
      }

      if (val === domain[1]) {
        return range[1];
      }
    }

    return (val - domain[0]) / subDomain * subRange + range[0];
  }

  function parsePercent$2(percent, all) {
    switch (percent) {
      case 'center':
      case 'middle':
        percent = '50%';
        break;

      case 'left':
      case 'top':
        percent = '0%';
        break;

      case 'right':
      case 'bottom':
        percent = '100%';
        break;
    }

    if (typeof percent === 'string') {
      if (_trim(percent).match(/%$/)) {
        return parseFloat(percent) / 100 * all;
      }

      return parseFloat(percent);
    }

    return percent == null ? NaN : +percent;
  }

  function round$1(x, precision, returnStr) {
    if (precision == null) {
      precision = 10;
    }

    precision = Math.min(Math.max(0, precision), 20);
    x = (+x).toFixed(precision);
    return returnStr ? x : +x;
  }

  function asc(arr) {
    arr.sort(function (a, b) {
      return a - b;
    });
    return arr;
  }

  function getPrecision(val) {
    val = +val;

    if (isNaN(val)) {
      return 0;
    }

    var e = 1;
    var count = 0;

    while (Math.round(val * e) / e !== val) {
      e *= 10;
      count++;
    }

    return count;
  }

  function getPrecisionSafe(val) {
    var str = val.toString();
    var eIndex = str.indexOf('e');

    if (eIndex > 0) {
      var precision = +str.slice(eIndex + 1);
      return precision < 0 ? -precision : 0;
    } else {
      var dotIndex = str.indexOf('.');
      return dotIndex < 0 ? 0 : str.length - 1 - dotIndex;
    }
  }

  function getPixelPrecision(dataExtent, pixelExtent) {
    var log = Math.log;
    var LN10 = Math.LN10;
    var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
    var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10);
    var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20);
    return !isFinite(precision) ? 20 : precision;
  }

  function getPercentWithPrecision(valueList, idx, precision) {
    if (!valueList[idx]) {
      return 0;
    }

    var sum = reduce(valueList, function (acc, val) {
      return acc + (isNaN(val) ? 0 : val);
    }, 0);

    if (sum === 0) {
      return 0;
    }

    var digits = Math.pow(10, precision);
    var votesPerQuota = map(valueList, function (val) {
      return (isNaN(val) ? 0 : val) / sum * digits * 100;
    });
    var targetSeats = digits * 100;
    var seats = map(votesPerQuota, function (votes) {
      return Math.floor(votes);
    });
    var currentSum = reduce(seats, function (acc, val) {
      return acc + val;
    }, 0);
    var remainder = map(votesPerQuota, function (votes, idx) {
      return votes - seats[idx];
    });

    while (currentSum < targetSeats) {
      var max = Number.NEGATIVE_INFINITY;
      var maxId = null;

      for (var i = 0, len = remainder.length; i < len; ++i) {
        if (remainder[i] > max) {
          max = remainder[i];
          maxId = i;
        }
      }

      ++seats[maxId];
      remainder[maxId] = 0;
      ++currentSum;
    }

    return seats[idx] / digits;
  }

  var MAX_SAFE_INTEGER = 9007199254740991;

  function remRadian(radian) {
    var pi2 = Math.PI * 2;
    return (radian % pi2 + pi2) % pi2;
  }

  function isRadianAroundZero(val) {
    return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
  }

  var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/;

  function parseDate(value) {
    if (value instanceof Date) {
      return value;
    } else if (typeof value === 'string') {
      var match = TIME_REG.exec(value);

      if (!match) {
        return new Date(NaN);
      }

      if (!match[8]) {
        return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, +match[7] || 0);
      } else {
        var hour = +match[4] || 0;

        if (match[8].toUpperCase() !== 'Z') {
          hour -= +match[8].slice(0, 3);
        }

        return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, +match[7] || 0));
      }
    } else if (value == null) {
      return new Date(NaN);
    }

    return new Date(Math.round(value));
  }

  function quantity(val) {
    return Math.pow(10, quantityExponent(val));
  }

  function quantityExponent(val) {
    if (val === 0) {
      return 0;
    }

    var exp = Math.floor(Math.log(val) / Math.LN10);

    if (val / Math.pow(10, exp) >= 10) {
      exp++;
    }

    return exp;
  }

  function nice(val, round) {
    var exponent = quantityExponent(val);
    var exp10 = Math.pow(10, exponent);
    var f = val / exp10;
    var nf;

    if (round) {
      if (f < 1.5) {
        nf = 1;
      } else if (f < 2.5) {
        nf = 2;
      } else if (f < 4) {
        nf = 3;
      } else if (f < 7) {
        nf = 5;
      } else {
        nf = 10;
      }
    } else {
      if (f < 1) {
        nf = 1;
      } else if (f < 2) {
        nf = 2;
      } else if (f < 3) {
        nf = 3;
      } else if (f < 5) {
        nf = 5;
      } else {
        nf = 10;
      }
    }

    val = nf * exp10;
    return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
  }

  function quantile(ascArr, p) {
    var H = (ascArr.length - 1) * p + 1;
    var h = Math.floor(H);
    var v = +ascArr[h - 1];
    var e = H - h;
    return e ? v + e * (ascArr[h] - v) : v;
  }

  function reformIntervals(list) {
    list.sort(function (a, b) {
      return littleThan(a, b, 0) ? -1 : 1;
    });
    var curr = -Infinity;
    var currClose = 1;

    for (var i = 0; i < list.length;) {
      var interval = list[i].interval;
      var close_1 = list[i].close;

      for (var lg = 0; lg < 2; lg++) {
        if (interval[lg] <= curr) {
          interval[lg] = curr;
          close_1[lg] = !lg ? 1 - currClose : 1;
        }

        curr = interval[lg];
        currClose = close_1[lg];
      }

      if (interval[0] === interval[1] && close_1[0] * close_1[1] !== 1) {
        list.splice(i, 1);
      } else {
        i++;
      }
    }

    return list;

    function littleThan(a, b, lg) {
      return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1));
    }
  }

  function numericToNumber(val) {
    var valFloat = parseFloat(val);
    return valFloat == val && (valFloat !== 0 || typeof val !== 'string' || val.indexOf('x') <= 0) ? valFloat : NaN;
  }

  function isNumeric(val) {
    return !isNaN(numericToNumber(val));
  }

  function getRandomIdBase() {
    return Math.round(Math.random() * 9);
  }

  function getGreatestCommonDividor(a, b) {
    if (b === 0) {
      return a;
    }

    return getGreatestCommonDividor(b, a % b);
  }

  function getLeastCommonMultiple(a, b) {
    if (a == null) {
      return b;
    }

    if (b == null) {
      return a;
    }

    return a * b / getGreatestCommonDividor(a, b);
  }

  var numberUtil = /*#__PURE__*/Object.freeze({
    __proto__: null,
    linearMap: linearMap,
    parsePercent: parsePercent$2,
    round: round$1,
    asc: asc,
    getPrecision: getPrecision,
    getPrecisionSafe: getPrecisionSafe,
    getPixelPrecision: getPixelPrecision,
    getPercentWithPrecision: getPercentWithPrecision,
    MAX_SAFE_INTEGER: MAX_SAFE_INTEGER,
    remRadian: remRadian,
    isRadianAroundZero: isRadianAroundZero,
    parseDate: parseDate,
    quantity: quantity,
    quantityExponent: quantityExponent,
    nice: nice,
    quantile: quantile,
    reformIntervals: reformIntervals,
    numericToNumber: numericToNumber,
    isNumeric: isNumeric,
    getRandomIdBase: getRandomIdBase,
    getGreatestCommonDividor: getGreatestCommonDividor,
    getLeastCommonMultiple: getLeastCommonMultiple
  });
  var ECHARTS_PREFIX = '[ECharts] ';
  var storedLogs = {};
  var hasConsole = typeof console !== 'undefined' && console.warn && console.log;

  function warn(str) {
    if (hasConsole) {
      console.warn(ECHARTS_PREFIX + str);
    }
  }

  function error(str) {
    if (hasConsole) {
      console.error(ECHARTS_PREFIX + str);
    }
  }

  function deprecateLog(str) {
    if (true) {
      if (storedLogs[str]) {
        return;
      }

      if (hasConsole) {
        storedLogs[str] = true;
        console.warn(ECHARTS_PREFIX + 'DEPRECATED: ' + str);
      }
    }
  }

  function deprecateReplaceLog(oldOpt, newOpt, scope) {
    if (true) {
      deprecateLog((scope ? "[" + scope + "]" : '') + (oldOpt + " is deprecated, use " + newOpt + " instead."));
    }
  }

  function consoleLog() {
    var args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }

    if (true) {
      if (typeof console !== 'undefined' && console.log) {
        console.log.apply(console, args);
      }
    }
  }

  function makePrintable() {
    var hintInfo = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      hintInfo[_i] = arguments[_i];
    }

    var msg = '';

    if (true) {
      var makePrintableStringIfPossible_1 = function (val) {
        return val === void 0 ? 'undefined' : val === Infinity ? 'Infinity' : val === -Infinity ? '-Infinity' : eqNaN(val) ? 'NaN' : val instanceof Date ? 'Date(' + val.toISOString() + ')' : isFunction(val) ? 'function () { ... }' : isRegExp(val) ? val + '' : null;
      };

      msg = map(hintInfo, function (arg) {
        if (isString(arg)) {
          return arg;
        } else {
          var printableStr = makePrintableStringIfPossible_1(arg);

          if (printableStr != null) {
            return printableStr;
          } else if (typeof JSON !== 'undefined' && JSON.stringify) {
            try {
              return JSON.stringify(arg, function (n, val) {
                var printableStr = makePrintableStringIfPossible_1(val);
                return printableStr == null ? val : printableStr;
              });
            } catch (err) {
              return '?';
            }
          } else {
            return '?';
          }
        }
      }).join(' ');
    }

    return msg;
  }

  function throwError(msg) {
    throw new Error(msg);
  }

  var DUMMY_COMPONENT_NAME_PREFIX = 'series\0';
  var INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0';

  function normalizeToArray(value) {
    return value instanceof Array ? value : value == null ? [] : [value];
  }

  function defaultEmphasis(opt, key, subOpts) {
    if (opt) {
      opt[key] = opt[key] || {};
      opt.emphasis = opt.emphasis || {};
      opt.emphasis[key] = opt.emphasis[key] || {};

      for (var i = 0, len = subOpts.length; i < len; i++) {
        var subOptName = subOpts[i];

        if (!opt.emphasis[key].hasOwnProperty(subOptName) && opt[key].hasOwnProperty(subOptName)) {
          opt.emphasis[key][subOptName] = opt[key][subOptName];
        }
      }
    }
  }

  var TEXT_STYLE_OPTIONS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding'];

  function getDataItemValue(dataItem) {
    return isObject(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date) ? dataItem.value : dataItem;
  }

  function isDataItemOption(dataItem) {
    return isObject(dataItem) && !(dataItem instanceof Array);
  }

  function mappingToExists(existings, newCmptOptions, mode) {
    var isNormalMergeMode = mode === 'normalMerge';
    var isReplaceMergeMode = mode === 'replaceMerge';
    var isReplaceAllMode = mode === 'replaceAll';
    existings = existings || [];
    newCmptOptions = (newCmptOptions || []).slice();
    var existingIdIdxMap = createHashMap();
    each(newCmptOptions, function (cmptOption, index) {
      if (!isObject(cmptOption)) {
        newCmptOptions[index] = null;
        return;
      }

      if (true) {
        if (cmptOption.id != null && !isValidIdOrName(cmptOption.id)) {
          warnInvalidateIdOrName(cmptOption.id);
        }

        if (cmptOption.name != null && !isValidIdOrName(cmptOption.name)) {
          warnInvalidateIdOrName(cmptOption.name);
        }
      }
    });
    var result = prepareResult(existings, existingIdIdxMap, mode);

    if (isNormalMergeMode || isReplaceMergeMode) {
      mappingById(result, existings, existingIdIdxMap, newCmptOptions);
    }

    if (isNormalMergeMode) {
      mappingByName(result, newCmptOptions);
    }

    if (isNormalMergeMode || isReplaceMergeMode) {
      mappingByIndex(result, newCmptOptions, isReplaceMergeMode);
    } else if (isReplaceAllMode) {
      mappingInReplaceAllMode(result, newCmptOptions);
    }

    makeIdAndName(result);
    return result;
  }

  function prepareResult(existings, existingIdIdxMap, mode) {
    var result = [];

    if (mode === 'replaceAll') {
      return result;
    }

    for (var index = 0; index < existings.length; index++) {
      var existing = existings[index];

      if (existing && existing.id != null) {
        existingIdIdxMap.set(existing.id, index);
      }

      result.push({
        existing: mode === 'replaceMerge' || isComponentIdInternal(existing) ? null : existing,
        newOption: null,
        keyInfo: null,
        brandNew: null
      });
    }

    return result;
  }

  function mappingById(result, existings, existingIdIdxMap, newCmptOptions) {
    each(newCmptOptions, function (cmptOption, index) {
      if (!cmptOption || cmptOption.id == null) {
        return;
      }

      var optionId = makeComparableKey(cmptOption.id);
      var existingIdx = existingIdIdxMap.get(optionId);

      if (existingIdx != null) {
        var resultItem = result[existingIdx];
        assert(!resultItem.newOption, 'Duplicated option on id "' + optionId + '".');
        resultItem.newOption = cmptOption;
        resultItem.existing = existings[existingIdx];
        newCmptOptions[index] = null;
      }
    });
  }

  function mappingByName(result, newCmptOptions) {
    each(newCmptOptions, function (cmptOption, index) {
      if (!cmptOption || cmptOption.name == null) {
        return;
      }

      for (var i = 0; i < result.length; i++) {
        var existing = result[i].existing;

        if (!result[i].newOption && existing && (existing.id == null || cmptOption.id == null) && !isComponentIdInternal(cmptOption) && !isComponentIdInternal(existing) && keyExistAndEqual('name', existing, cmptOption)) {
          result[i].newOption = cmptOption;
          newCmptOptions[index] = null;
          return;
        }
      }
    });
  }

  function mappingByIndex(result, newCmptOptions, brandNew) {
    each(newCmptOptions, function (cmptOption) {
      if (!cmptOption) {
        return;
      }

      var resultItem;
      var nextIdx = 0;

      while ((resultItem = result[nextIdx]) && (resultItem.newOption || isComponentIdInternal(resultItem.existing) || resultItem.existing && cmptOption.id != null && !keyExistAndEqual('id', cmptOption, resultItem.existing))) {
        nextIdx++;
      }

      if (resultItem) {
        resultItem.newOption = cmptOption;
        resultItem.brandNew = brandNew;
      } else {
        result.push({
          newOption: cmptOption,
          brandNew: brandNew,
          existing: null,
          keyInfo: null
        });
      }

      nextIdx++;
    });
  }

  function mappingInReplaceAllMode(result, newCmptOptions) {
    each(newCmptOptions, function (cmptOption) {
      result.push({
        newOption: cmptOption,
        brandNew: true,
        existing: null,
        keyInfo: null
      });
    });
  }

  function makeIdAndName(mapResult) {
    var idMap = createHashMap();
    each(mapResult, function (item) {
      var existing = item.existing;
      existing && idMap.set(existing.id, item);
    });
    each(mapResult, function (item) {
      var opt = item.newOption;
      assert(!opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, 'id duplicates: ' + (opt && opt.id));
      opt && opt.id != null && idMap.set(opt.id, item);
      !item.keyInfo && (item.keyInfo = {});
    });
    each(mapResult, function (item, index) {
      var existing = item.existing;
      var opt = item.newOption;
      var keyInfo = item.keyInfo;

      if (!isObject(opt)) {
        return;
      }

      keyInfo.name = opt.name != null ? makeComparableKey(opt.name) : existing ? existing.name : DUMMY_COMPONENT_NAME_PREFIX + index;

      if (existing) {
        keyInfo.id = makeComparableKey(existing.id);
      } else if (opt.id != null) {
        keyInfo.id = makeComparableKey(opt.id);
      } else {
        var idNum = 0;

        do {
          keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
        } while (idMap.get(keyInfo.id));
      }

      idMap.set(keyInfo.id, item);
    });
  }

  function keyExistAndEqual(attr, obj1, obj2) {
    var key1 = convertOptionIdName(obj1[attr], null);
    var key2 = convertOptionIdName(obj2[attr], null);
    return key1 != null && key2 != null && key1 === key2;
  }

  function makeComparableKey(val) {
    if (true) {
      if (val == null) {
        throw new Error();
      }
    }

    return convertOptionIdName(val, '');
  }

  function convertOptionIdName(idOrName, defaultValue) {
    if (idOrName == null) {
      return defaultValue;
    }

    var type = typeof idOrName;
    return type === 'string' ? idOrName : type === 'number' || isStringSafe(idOrName) ? idOrName + '' : defaultValue;
  }

  function warnInvalidateIdOrName(idOrName) {
    if (true) {
      warn('`' + idOrName + '` is invalid id or name. Must be a string or number.');
    }
  }

  function isValidIdOrName(idOrName) {
    return isStringSafe(idOrName) || isNumeric(idOrName);
  }

  function isNameSpecified(componentModel) {
    var name = componentModel.name;
    return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));
  }

  function isComponentIdInternal(cmptOption) {
    return cmptOption && cmptOption.id != null && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0;
  }

  function makeInternalComponentId(idSuffix) {
    return INTERNAL_COMPONENT_ID_PREFIX + idSuffix;
  }

  function setComponentTypeToKeyInfo(mappingResult, mainType, componentModelCtor) {
    each(mappingResult, function (item) {
      var newOption = item.newOption;

      if (isObject(newOption)) {
        item.keyInfo.mainType = mainType;
        item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor);
      }
    });
  }

  function determineSubType(mainType, newCmptOption, existComponent, componentModelCtor) {
    var subType = newCmptOption.type ? newCmptOption.type : existComponent ? existComponent.subType : componentModelCtor.determineSubType(mainType, newCmptOption);
    return subType;
  }

  function compressBatches(batchA, batchB) {
    var mapA = {};
    var mapB = {};
    makeMap(batchA || [], mapA);
    makeMap(batchB || [], mapB, mapA);
    return [mapToArray(mapA), mapToArray(mapB)];

    function makeMap(sourceBatch, map, otherMap) {
      for (var i = 0, len = sourceBatch.length; i < len; i++) {
        var seriesId = convertOptionIdName(sourceBatch[i].seriesId, null);

        if (seriesId == null) {
          return;
        }

        var dataIndices = normalizeToArray(sourceBatch[i].dataIndex);
        var otherDataIndices = otherMap && otherMap[seriesId];

        for (var j = 0, lenj = dataIndices.length; j < lenj; j++) {
          var dataIndex = dataIndices[j];

          if (otherDataIndices && otherDataIndices[dataIndex]) {
            otherDataIndices[dataIndex] = null;
          } else {
            (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1;
          }
        }
      }
    }

    function mapToArray(map, isData) {
      var result = [];

      for (var i in map) {
        if (map.hasOwnProperty(i) && map[i] != null) {
          if (isData) {
            result.push(+i);
          } else {
            var dataIndices = mapToArray(map[i], true);
            dataIndices.length && result.push({
              seriesId: i,
              dataIndex: dataIndices
            });
          }
        }
      }

      return result;
    }
  }

  function queryDataIndex(data, payload) {
    if (payload.dataIndexInside != null) {
      return payload.dataIndexInside;
    } else if (payload.dataIndex != null) {
      return isArray(payload.dataIndex) ? map(payload.dataIndex, function (value) {
        return data.indexOfRawIndex(value);
      }) : data.indexOfRawIndex(payload.dataIndex);
    } else if (payload.name != null) {
      return isArray(payload.name) ? map(payload.name, function (value) {
        return data.indexOfName(value);
      }) : data.indexOfName(payload.name);
    }
  }

  function makeInner() {
    var key = '__ec_inner_' + innerUniqueIndex++;
    return function (hostObj) {
      return hostObj[key] || (hostObj[key] = {});
    };
  }

  var innerUniqueIndex = getRandomIdBase();

  function parseFinder(ecModel, finderInput, opt) {
    var finder;

    if (isString(finderInput)) {
      var obj = {};
      obj[finderInput + 'Index'] = 0;
      finder = obj;
    } else {
      finder = finderInput;
    }

    var queryOptionMap = createHashMap();
    var result = {};
    var mainTypeSpecified = false;
    each(finder, function (value, key) {
      if (key === 'dataIndex' || key === 'dataIndexInside') {
        result[key] = value;
        return;
      }

      var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || [];
      var mainType = parsedKey[1];
      var queryType = (parsedKey[2] || '').toLowerCase();

      if (!mainType || !queryType || opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) {
        return;
      }

      mainTypeSpecified = mainTypeSpecified || !!mainType;
      var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {});
      queryOption[queryType] = value;
    });
    var defaultMainType = opt ? opt.defaultMainType : null;

    if (!mainTypeSpecified && defaultMainType) {
      queryOptionMap.set(defaultMainType, {});
    }

    queryOptionMap.each(function (queryOption, mainType) {
      var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
        useDefault: defaultMainType === mainType,
        enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
        enableNone: opt && opt.enableNone != null ? opt.enableNone : true
      });
      result[mainType + 'Models'] = queryResult.models;
      result[mainType + 'Model'] = queryResult.models[0];
    });
    return result;
  }

  var SINGLE_REFERRING = {
    useDefault: true,
    enableAll: false,
    enableNone: false
  };
  var MULTIPLE_REFERRING = {
    useDefault: false,
    enableAll: true,
    enableNone: true
  };

  function queryReferringComponents(ecModel, mainType, userOption, opt) {
    opt = opt || SINGLE_REFERRING;
    var indexOption = userOption.index;
    var idOption = userOption.id;
    var nameOption = userOption.name;
    var result = {
      models: null,
      specified: indexOption != null || idOption != null || nameOption != null
    };

    if (!result.specified) {
      var firstCmpt = void 0;
      result.models = opt.useDefault && (firstCmpt = ecModel.getComponent(mainType)) ? [firstCmpt] : [];
      return result;
    }

    if (indexOption === 'none' || indexOption === false) {
      assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.');
      result.models = [];
      return result;
    }

    if (indexOption === 'all') {
      assert(opt.enableAll, '`"all"` is not a valid value on index option.');
      indexOption = idOption = nameOption = null;
    }

    result.models = ecModel.queryComponents({
      mainType: mainType,
      index: indexOption,
      id: idOption,
      name: nameOption
    });
    return result;
  }

  function setAttribute(dom, key, value) {
    dom.setAttribute ? dom.setAttribute(key, value) : dom[key] = value;
  }

  function getAttribute(dom, key) {
    return dom.getAttribute ? dom.getAttribute(key) : dom[key];
  }

  function getTooltipRenderMode(renderModeOption) {
    if (renderModeOption === 'auto') {
      return env.domSupported ? 'html' : 'richText';
    } else {
      return renderModeOption || 'html';
    }
  }

  function groupData(array, getKey) {
    var buckets = createHashMap();
    var keys = [];
    each(array, function (item) {
      var key = getKey(item);
      (buckets.get(key) || (keys.push(key), buckets.set(key, []))).push(item);
    });
    return {
      keys: keys,
      buckets: buckets
    };
  }

  function interpolateRawValues(data, precision, sourceValue, targetValue, percent) {
    var isAutoPrecision = precision == null || precision === 'auto';

    if (targetValue == null) {
      return targetValue;
    }

    if (typeof targetValue === 'number') {
      var value = interpolateNumber(sourceValue || 0, targetValue, percent);
      return round$1(value, isAutoPrecision ? Math.max(getPrecisionSafe(sourceValue || 0), getPrecisionSafe(targetValue)) : precision);
    } else if (typeof targetValue === 'string') {
      return percent < 1 ? sourceValue : targetValue;
    } else {
      var interpolated = [];
      var leftArr = sourceValue || [];
      var rightArr = targetValue;
      var length_1 = Math.max(leftArr.length, rightArr.length);

      for (var i = 0; i < length_1; ++i) {
        var info = data.getDimensionInfo(i);

        if (info.type === 'ordinal') {
          interpolated[i] = (percent < 1 ? leftArr : rightArr)[i];
        } else {
          var leftVal = leftArr && leftArr[i] ? leftArr[i] : 0;
          var rightVal = rightArr[i];
          var value = leftArr == null ? targetValue[i] : interpolateNumber(leftVal, rightVal, percent);
          interpolated[i] = round$1(value, isAutoPrecision ? Math.max(getPrecisionSafe(leftVal), getPrecisionSafe(rightVal)) : precision);
        }
      }

      return interpolated;
    }
  }

  var TYPE_DELIMITER = '.';
  var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';
  var IS_EXTENDED_CLASS = '___EC__EXTENDED_CLASS___';

  function parseClassType(componentType) {
    var ret = {
      main: '',
      sub: ''
    };

    if (componentType) {
      var typeArr = componentType.split(TYPE_DELIMITER);
      ret.main = typeArr[0] || '';
      ret.sub = typeArr[1] || '';
    }

    return ret;
  }

  function checkClassType(componentType) {
    assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal');
  }

  function isExtendedClass(clz) {
    return !!(clz && clz[IS_EXTENDED_CLASS]);
  }

  function enableClassExtend(rootClz, mandatoryMethods) {
    rootClz.$constructor = rootClz;

    rootClz.extend = function (proto) {
      if (true) {
        each(mandatoryMethods, function (method) {
          if (!proto[method]) {
            console.warn('Method `' + method + '` should be implemented' + (proto.type ? ' in ' + proto.type : '') + '.');
          }
        });
      }

      var superClass = this;

      function ExtendedClass() {
        var args = [];

        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }

        if (!proto.$constructor) {
          if (!isESClass(superClass)) {
            superClass.apply(this, arguments);
          } else {
            var ins = createObject(ExtendedClass.prototype, new (superClass.bind.apply(superClass, __spreadArrays([void 0], args)))());
            return ins;
          }
        } else {
          proto.$constructor.apply(this, arguments);
        }
      }

      ExtendedClass[IS_EXTENDED_CLASS] = true;
      extend(ExtendedClass.prototype, proto);
      ExtendedClass.extend = this.extend;
      ExtendedClass.superCall = superCall;
      ExtendedClass.superApply = superApply;
      inherits(ExtendedClass, this);
      ExtendedClass.superClass = superClass;
      return ExtendedClass;
    };
  }

  function isESClass(fn) {
    return typeof fn === 'function' && /^class\s/.test(Function.prototype.toString.call(fn));
  }

  function mountExtend(SubClz, SupperClz) {
    SubClz.extend = SupperClz.extend;
  }

  var classBase = Math.round(Math.random() * 10);

  function enableClassCheck(target) {
    var classAttr = ['__\0is_clz', classBase++].join('_');
    target.prototype[classAttr] = true;

    if (true) {
      assert(!target.isInstance, 'The method "is" can not be defined.');
    }

    target.isInstance = function (obj) {
      return !!(obj && obj[classAttr]);
    };
  }

  function superCall(context, methodName) {
    var args = [];

    for (var _i = 2; _i < arguments.length; _i++) {
      args[_i - 2] = arguments[_i];
    }

    return this.superClass.prototype[methodName].apply(context, args);
  }

  function superApply(context, methodName, args) {
    return this.superClass.prototype[methodName].apply(context, args);
  }

  function enableClassManagement(target, options) {
    options = options || {};
    var storage = {};

    target.registerClass = function (clz) {
      var componentFullType = clz.type || clz.prototype.type;

      if (componentFullType) {
        checkClassType(componentFullType);
        clz.prototype.type = componentFullType;
        var componentTypeInfo = parseClassType(componentFullType);

        if (!componentTypeInfo.sub) {
          if (true) {
            if (storage[componentTypeInfo.main]) {
              console.warn(componentTypeInfo.main + ' exists.');
            }
          }

          storage[componentTypeInfo.main] = clz;
        } else if (componentTypeInfo.sub !== IS_CONTAINER) {
          var container = makeContainer(componentTypeInfo);
          container[componentTypeInfo.sub] = clz;
        }
      }

      return clz;
    };

    target.getClass = function (mainType, subType, throwWhenNotFound) {
      var clz = storage[mainType];

      if (clz && clz[IS_CONTAINER]) {
        clz = subType ? clz[subType] : null;
      }

      if (throwWhenNotFound && !clz) {
        throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' not exists. Load it first.');
      }

      return clz;
    };

    target.getClassesByMainType = function (componentType) {
      var componentTypeInfo = parseClassType(componentType);
      var result = [];
      var obj = storage[componentTypeInfo.main];

      if (obj && obj[IS_CONTAINER]) {
        each(obj, function (o, type) {
          type !== IS_CONTAINER && result.push(o);
        });
      } else {
        result.push(obj);
      }

      return result;
    };

    target.hasClass = function (componentType) {
      var componentTypeInfo = parseClassType(componentType);
      return !!storage[componentTypeInfo.main];
    };

    target.getAllClassMainTypes = function () {
      var types = [];
      each(storage, function (obj, type) {
        types.push(type);
      });
      return types;
    };

    target.hasSubTypes = function (componentType) {
      var componentTypeInfo = parseClassType(componentType);
      var obj = storage[componentTypeInfo.main];
      return obj && obj[IS_CONTAINER];
    };

    function makeContainer(componentTypeInfo) {
      var container = storage[componentTypeInfo.main];

      if (!container || !container[IS_CONTAINER]) {
        container = storage[componentTypeInfo.main] = {};
        container[IS_CONTAINER] = true;
      }

      return container;
    }

    if (options.registerWhenExtend) {
      var originalExtend_1 = target.extend;

      if (originalExtend_1) {
        target.extend = function (proto) {
          var ExtendedClass = originalExtend_1.call(this, proto);
          return target.registerClass(ExtendedClass);
        };
      }
    }
  }

  function makeStyleMapper(properties, ignoreParent) {
    for (var i = 0; i < properties.length; i++) {
      if (!properties[i][1]) {
        properties[i][1] = properties[i][0];
      }
    }

    ignoreParent = ignoreParent || false;
    return function (model, excludes, includes) {
      var style = {};

      for (var i = 0; i < properties.length; i++) {
        var propName = properties[i][1];

        if (excludes && indexOf(excludes, propName) >= 0 || includes && indexOf(includes, propName) < 0) {
          continue;
        }

        var val = model.getShallow(propName, ignoreParent);

        if (val != null) {
          style[properties[i][0]] = val;
        }
      }

      return style;
    };
  }

  var AREA_STYLE_KEY_MAP = [['fill', 'color'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['opacity'], ['shadowColor']];
  var getAreaStyle = makeStyleMapper(AREA_STYLE_KEY_MAP);

  var AreaStyleMixin = function () {
    function AreaStyleMixin() {}

    AreaStyleMixin.prototype.getAreaStyle = function (excludes, includes) {
      return getAreaStyle(this, excludes, includes);
    };

    return AreaStyleMixin;
  }();

  var getECData = makeInner();
  var _highlightNextDigit = 1;
  var _highlightKeyMap = {};
  var getSavedStates = makeInner();
  var HOVER_STATE_NORMAL = 0;
  var HOVER_STATE_BLUR = 1;
  var HOVER_STATE_EMPHASIS = 2;
  var SPECIAL_STATES = ['emphasis', 'blur', 'select'];
  var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select'];
  var Z2_EMPHASIS_LIFT = 10;
  var Z2_SELECT_LIFT = 9;
  var HIGHLIGHT_ACTION_TYPE = 'highlight';
  var DOWNPLAY_ACTION_TYPE = 'downplay';
  var SELECT_ACTION_TYPE = 'select';
  var UNSELECT_ACTION_TYPE = 'unselect';
  var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect';

  function hasFillOrStroke(fillOrStroke) {
    return fillOrStroke != null && fillOrStroke !== 'none';
  }

  var liftedColorCache = new LRU(100);

  function liftColor(color$1) {
    if (typeof color$1 !== 'string') {
      return color$1;
    }

    var liftedColor = liftedColorCache.get(color$1);

    if (!liftedColor) {
      liftedColor = lift(color$1, -0.1);
      liftedColorCache.put(color$1, liftedColor);
    }

    return liftedColor;
  }

  function doChangeHoverState(el, stateName, hoverStateEnum) {
    if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) {
      el.onHoverStateChange(stateName);
    }

    el.hoverState = hoverStateEnum;
  }

  function singleEnterEmphasis(el) {
    doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS);
  }

  function singleLeaveEmphasis(el) {
    if (el.hoverState === HOVER_STATE_EMPHASIS) {
      doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
    }
  }

  function singleEnterBlur(el) {
    doChangeHoverState(el, 'blur', HOVER_STATE_BLUR);
  }

  function singleLeaveBlur(el) {
    if (el.hoverState === HOVER_STATE_BLUR) {
      doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
    }
  }

  function singleEnterSelect(el) {
    el.selected = true;
  }

  function singleLeaveSelect(el) {
    el.selected = false;
  }

  function updateElementState(el, updater, commonParam) {
    updater(el, commonParam);
  }

  function traverseUpdateState(el, updater, commonParam) {
    updateElementState(el, updater, commonParam);
    el.isGroup && el.traverse(function (child) {
      updateElementState(child, updater, commonParam);
    });
  }

  function setStatesFlag(el, stateName) {
    switch (stateName) {
      case 'emphasis':
        el.hoverState = HOVER_STATE_EMPHASIS;
        break;

      case 'normal':
        el.hoverState = HOVER_STATE_NORMAL;
        break;

      case 'blur':
        el.hoverState = HOVER_STATE_BLUR;
        break;

      case 'select':
        el.selected = true;
    }
  }

  function getFromStateStyle(el, props, toStateName, defaultValue) {
    var style = el.style;
    var fromState = {};

    for (var i = 0; i < props.length; i++) {
      var propName = props[i];
      var val = style[propName];
      fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val;
    }

    for (var i = 0; i < el.animators.length; i++) {
      var animator = el.animators[i];

      if (animator.__fromStateTransition && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') {
        animator.saveFinalToTarget(fromState, props);
      }
    }

    return fromState;
  }

  function createEmphasisDefaultState(el, stateName, targetStates, state) {
    var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0;
    var cloned = false;

    if (el instanceof Path) {
      var store = getSavedStates(el);
      var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill;
      var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke;

      if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) {
        state = state || {};
        var emphasisStyle = state.style || {};

        if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) {
          cloned = true;
          state = extend({}, state);
          emphasisStyle = extend({}, emphasisStyle);
          emphasisStyle.fill = liftColor(fromFill);
        } else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) {
          if (!cloned) {
            state = extend({}, state);
            emphasisStyle = extend({}, emphasisStyle);
          }

          emphasisStyle.stroke = liftColor(fromStroke);
        }

        state.style = emphasisStyle;
      }
    }

    if (state) {
      if (state.z2 == null) {
        if (!cloned) {
          state = extend({}, state);
        }

        var z2EmphasisLift = el.z2EmphasisLift;
        state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT);
      }
    }

    return state;
  }

  function createSelectDefaultState(el, stateName, state) {
    if (state) {
      if (state.z2 == null) {
        state = extend({}, state);
        var z2SelectLift = el.z2SelectLift;
        state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT);
      }
    }

    return state;
  }

  function createBlurDefaultState(el, stateName, state) {
    var hasBlur = indexOf(el.currentStates, stateName) >= 0;
    var currentOpacity = el.style.opacity;
    var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, {
      opacity: 1
    }) : null;
    state = state || {};
    var blurStyle = state.style || {};

    if (blurStyle.opacity == null) {
      state = extend({}, state);
      blurStyle = extend({
        opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1
      }, blurStyle);
      state.style = blurStyle;
    }

    return state;
  }

  function elementStateProxy(stateName, targetStates) {
    var state = this.states[stateName];

    if (this.style) {
      if (stateName === 'emphasis') {
        return createEmphasisDefaultState(this, stateName, targetStates, state);
      } else if (stateName === 'blur') {
        return createBlurDefaultState(this, stateName, state);
      } else if (stateName === 'select') {
        return createSelectDefaultState(this, stateName, state);
      }
    }

    return state;
  }

  function setDefaultStateProxy(el) {
    el.stateProxy = elementStateProxy;
    var textContent = el.getTextContent();
    var textGuide = el.getTextGuideLine();

    if (textContent) {
      textContent.stateProxy = elementStateProxy;
    }

    if (textGuide) {
      textGuide.stateProxy = elementStateProxy;
    }
  }

  function enterEmphasisWhenMouseOver(el, e) {
    !shouldSilent(el, e) && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis);
  }

  function leaveEmphasisWhenMouseOut(el, e) {
    !shouldSilent(el, e) && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis);
  }

  function enterEmphasis(el, highlightDigit) {
    el.__highByOuter |= 1 << (highlightDigit || 0);
    traverseUpdateState(el, singleEnterEmphasis);
  }

  function leaveEmphasis(el, highlightDigit) {
    !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis);
  }

  function enterBlur(el) {
    traverseUpdateState(el, singleEnterBlur);
  }

  function leaveBlur(el) {
    traverseUpdateState(el, singleLeaveBlur);
  }

  function enterSelect(el) {
    traverseUpdateState(el, singleEnterSelect);
  }

  function leaveSelect(el) {
    traverseUpdateState(el, singleLeaveSelect);
  }

  function shouldSilent(el, e) {
    return el.__highDownSilentOnTouch && e.zrByTouch;
  }

  function allLeaveBlur(api) {
    var model = api.getModel();
    model.eachComponent(function (componentType, componentModel) {
      var view = componentType === 'series' ? api.getViewOfSeriesModel(componentModel) : api.getViewOfComponentModel(componentModel);
      view.group.traverse(function (child) {
        singleLeaveBlur(child);
      });
    });
  }

  function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur) {
    var ecModel = api.getModel();
    blurScope = blurScope || 'coordinateSystem';

    function leaveBlurOfIndices(data, dataIndices) {
      for (var i = 0; i < dataIndices.length; i++) {
        var itemEl = data.getItemGraphicEl(dataIndices[i]);
        itemEl && leaveBlur(itemEl);
      }
    }

    if (!isBlur) {
      allLeaveBlur(api);
      return;
    }

    if (targetSeriesIndex == null) {
      return;
    }

    if (!focus || focus === 'none') {
      return;
    }

    var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex);
    var targetCoordSys = targetSeriesModel.coordinateSystem;

    if (targetCoordSys && targetCoordSys.master) {
      targetCoordSys = targetCoordSys.master;
    }

    var blurredSeries = [];
    ecModel.eachSeries(function (seriesModel) {
      var sameSeries = targetSeriesModel === seriesModel;
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys && coordSys.master) {
        coordSys = coordSys.master;
      }

      var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries;

      if (!(blurScope === 'series' && !sameSeries || blurScope === 'coordinateSystem' && !sameCoordSys || focus === 'series' && sameSeries)) {
        var view = api.getViewOfSeriesModel(seriesModel);
        view.group.traverse(function (child) {
          singleEnterBlur(child);
        });

        if (isArrayLike(focus)) {
          leaveBlurOfIndices(seriesModel.getData(), focus);
        } else if (isObject(focus)) {
          var dataTypes = keys(focus);

          for (var d = 0; d < dataTypes.length; d++) {
            leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]);
          }
        }

        blurredSeries.push(seriesModel);
      }
    });
    ecModel.eachComponent(function (componentType, componentModel) {
      if (componentType === 'series') {
        return;
      }

      var view = api.getViewOfComponentModel(componentModel);

      if (view && view.blurSeries) {
        view.blurSeries(blurredSeries, ecModel);
      }
    });
  }

  function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) {
    if (!isHighDownPayload(payload)) {
      return;
    }

    var isHighlight = payload.type === HIGHLIGHT_ACTION_TYPE;
    var seriesIndex = seriesModel.seriesIndex;
    var data = seriesModel.getData(payload.dataType);
    var dataIndex = queryDataIndex(data, payload);
    dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0;
    var el = data.getItemGraphicEl(dataIndex);

    if (!el) {
      var count = data.count();
      var current = 0;

      while (!el && current < count) {
        el = data.getItemGraphicEl(current++);
      }
    }

    if (el) {
      var ecData = getECData(el);
      toggleSeriesBlurState(seriesIndex, ecData.focus, ecData.blurScope, api, isHighlight);
    } else {
      var focus_1 = seriesModel.get(['emphasis', 'focus']);
      var blurScope = seriesModel.get(['emphasis', 'blurScope']);

      if (focus_1 != null) {
        toggleSeriesBlurState(seriesIndex, focus_1, blurScope, api, isHighlight);
      }
    }
  }

  function toggleSelectionFromPayload(seriesModel, payload, api) {
    if (!isSelectChangePayload(payload)) {
      return;
    }

    var dataType = payload.dataType;
    var data = seriesModel.getData(dataType);
    var dataIndex = queryDataIndex(data, payload);

    if (!isArray(dataIndex)) {
      dataIndex = [dataIndex];
    }

    seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType);
  }

  function updateSeriesElementSelection(seriesModel) {
    var allData = seriesModel.getAllData();
    each(allData, function (_a) {
      var data = _a.data,
          type = _a.type;
      data.eachItemGraphicEl(function (el, idx) {
        seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el);
      });
    });
  }

  function getAllSelectedIndices(ecModel) {
    var ret = [];
    ecModel.eachSeries(function (seriesModel) {
      var allData = seriesModel.getAllData();
      each(allData, function (_a) {
        var data = _a.data,
            type = _a.type;
        var dataIndices = seriesModel.getSelectedDataIndices();

        if (dataIndices.length > 0) {
          var item = {
            dataIndex: dataIndices,
            seriesIndex: seriesModel.seriesIndex
          };

          if (type != null) {
            item.dataType = type;
          }

          ret.push(item);
        }
      });
    });
    return ret;
  }

  function enableHoverEmphasis(el, focus, blurScope) {
    setAsHighDownDispatcher(el, true);
    traverseUpdateState(el, setDefaultStateProxy);
    enableHoverFocus(el, focus, blurScope);
  }

  function enableHoverFocus(el, focus, blurScope) {
    var ecData = getECData(el);

    if (focus != null) {
      ecData.focus = focus;
      ecData.blurScope = blurScope;
    } else if (ecData.focus) {
      ecData.focus = null;
    }
  }

  var OTHER_STATES = ['emphasis', 'blur', 'select'];
  var defaultStyleGetterMap = {
    itemStyle: 'getItemStyle',
    lineStyle: 'getLineStyle',
    areaStyle: 'getAreaStyle'
  };

  function setStatesStylesFromModel(el, itemModel, styleType, getter) {
    styleType = styleType || 'itemStyle';

    for (var i = 0; i < OTHER_STATES.length; i++) {
      var stateName = OTHER_STATES[i];
      var model = itemModel.getModel([stateName, styleType]);
      var state = el.ensureState(stateName);
      state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]]();
    }
  }

  function setAsHighDownDispatcher(el, asDispatcher) {
    var disable = asDispatcher === false;
    var extendedEl = el;

    if (el.highDownSilentOnTouch) {
      extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch;
    }

    if (!disable || extendedEl.__highDownDispatcher) {
      extendedEl.__highByOuter = extendedEl.__highByOuter || 0;
      extendedEl.__highDownDispatcher = !disable;
    }
  }

  function isHighDownDispatcher(el) {
    return !!(el && el.__highDownDispatcher);
  }

  function getHighlightDigit(highlightKey) {
    var highlightDigit = _highlightKeyMap[highlightKey];

    if (highlightDigit == null && _highlightNextDigit <= 32) {
      highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++;
    }

    return highlightDigit;
  }

  function isSelectChangePayload(payload) {
    var payloadType = payload.type;
    return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE;
  }

  function isHighDownPayload(payload) {
    var payloadType = payload.type;
    return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE;
  }

  function savePathStates(el) {
    var store = getSavedStates(el);
    store.normalFill = el.style.fill;
    store.normalStroke = el.style.stroke;
    var selectState = el.states.select || {};
    store.selectFill = selectState.style && selectState.style.fill || null;
    store.selectStroke = selectState.style && selectState.style.stroke || null;
  }

  var mathMax$4 = Math.max;
  var mathMin$4 = Math.min;
  var _customShapeMap = {};

  function extendShape(opts) {
    return Path.extend(opts);
  }

  var extendPathFromString = extendFromString;

  function extendPath(pathData, opts) {
    return extendPathFromString(pathData, opts);
  }

  function registerShape(name, ShapeClass) {
    _customShapeMap[name] = ShapeClass;
  }

  function getShapeClass(name) {
    if (_customShapeMap.hasOwnProperty(name)) {
      return _customShapeMap[name];
    }
  }

  function makePath(pathData, opts, rect, layout) {
    var path = createFromString(pathData, opts);

    if (rect) {
      if (layout === 'center') {
        rect = centerGraphic(rect, path.getBoundingRect());
      }

      resizePath(path, rect);
    }

    return path;
  }

  function makeImage(imageUrl, rect, layout) {
    var zrImg = new ZRImage({
      style: {
        image: imageUrl,
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height
      },
      onload: function (img) {
        if (layout === 'center') {
          var boundingRect = {
            width: img.width,
            height: img.height
          };
          zrImg.setStyle(centerGraphic(rect, boundingRect));
        }
      }
    });
    return zrImg;
  }

  function centerGraphic(rect, boundingRect) {
    var aspect = boundingRect.width / boundingRect.height;
    var width = rect.height * aspect;
    var height;

    if (width <= rect.width) {
      height = rect.height;
    } else {
      width = rect.width;
      height = width / aspect;
    }

    var cx = rect.x + rect.width / 2;
    var cy = rect.y + rect.height / 2;
    return {
      x: cx - width / 2,
      y: cy - height / 2,
      width: width,
      height: height
    };
  }

  var mergePath$1 = mergePath;

  function resizePath(path, rect) {
    if (!path.applyTransform) {
      return;
    }

    var pathRect = path.getBoundingRect();
    var m = pathRect.calculateTransform(rect);
    path.applyTransform(m);
  }

  function subPixelOptimizeLine$1(param) {
    subPixelOptimizeLine(param.shape, param.shape, param.style);
    return param;
  }

  function subPixelOptimizeRect$1(param) {
    subPixelOptimizeRect(param.shape, param.shape, param.style);
    return param;
  }

  var subPixelOptimize$1 = subPixelOptimize;

  function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) {
    var isFrom = false;
    var removeOpt;

    if (typeof dataIndex === 'function') {
      during = cb;
      cb = dataIndex;
      dataIndex = null;
    } else if (isObject(dataIndex)) {
      cb = dataIndex.cb;
      during = dataIndex.during;
      isFrom = dataIndex.isFrom;
      removeOpt = dataIndex.removeOpt;
      dataIndex = dataIndex.dataIndex;
    }

    var isUpdate = animationType === 'update';
    var isRemove = animationType === 'remove';
    var animationPayload;

    if (animatableModel && animatableModel.ecModel) {
      var updatePayload = animatableModel.ecModel.getUpdatePayload();
      animationPayload = updatePayload && updatePayload.animation;
    }

    var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();

    if (!isRemove) {
      el.stopAnimation('remove');
    }

    if (animationEnabled) {
      var duration = void 0;
      var animationEasing = void 0;
      var animationDelay = void 0;

      if (animationPayload) {
        duration = animationPayload.duration || 0;
        animationEasing = animationPayload.easing || 'cubicOut';
        animationDelay = animationPayload.delay || 0;
      } else if (isRemove) {
        removeOpt = removeOpt || {};
        duration = retrieve2(removeOpt.duration, 200);
        animationEasing = retrieve2(removeOpt.easing, 'cubicOut');
        animationDelay = 0;
      } else {
        duration = animatableModel.getShallow(isUpdate ? 'animationDurationUpdate' : 'animationDuration');
        animationEasing = animatableModel.getShallow(isUpdate ? 'animationEasingUpdate' : 'animationEasing');
        animationDelay = animatableModel.getShallow(isUpdate ? 'animationDelayUpdate' : 'animationDelay');
      }

      if (typeof animationDelay === 'function') {
        animationDelay = animationDelay(dataIndex, animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null);
      }

      if (typeof duration === 'function') {
        duration = duration(dataIndex);
      }

      duration > 0 ? isFrom ? el.animateFrom(props, {
        duration: duration,
        delay: animationDelay || 0,
        easing: animationEasing,
        done: cb,
        force: !!cb || !!during,
        scope: animationType,
        during: during
      }) : el.animateTo(props, {
        duration: duration,
        delay: animationDelay || 0,
        easing: animationEasing,
        done: cb,
        force: !!cb || !!during,
        setToFinal: true,
        scope: animationType,
        during: during
      }) : (el.stopAnimation(), !isFrom && el.attr(props), cb && cb());
    } else {
      el.stopAnimation();
      !isFrom && el.attr(props);
      during && during(1);
      cb && cb();
    }
  }

  function updateProps(el, props, animatableModel, dataIndex, cb, during) {
    animateOrSetProps('update', el, props, animatableModel, dataIndex, cb, during);
  }

  function initProps(el, props, animatableModel, dataIndex, cb, during) {
    animateOrSetProps('init', el, props, animatableModel, dataIndex, cb, during);
  }

  function removeElement(el, props, animatableModel, dataIndex, cb, during) {
    if (isElementRemoved(el)) {
      return;
    }

    animateOrSetProps('remove', el, props, animatableModel, dataIndex, cb, during);
  }

  function fadeOutDisplayable(el, animatableModel, dataIndex, done) {
    el.removeTextContent();
    el.removeTextGuideLine();
    removeElement(el, {
      style: {
        opacity: 0
      }
    }, animatableModel, dataIndex, done);
  }

  function removeElementWithFadeOut(el, animatableModel, dataIndex) {
    function doRemove() {
      el.parent && el.parent.remove(el);
    }

    if (!el.isGroup) {
      fadeOutDisplayable(el, animatableModel, dataIndex, doRemove);
    } else {
      el.traverse(function (disp) {
        if (!disp.isGroup) {
          fadeOutDisplayable(disp, animatableModel, dataIndex, doRemove);
        }
      });
    }
  }

  function isElementRemoved(el) {
    if (!el.__zr) {
      return true;
    }

    for (var i = 0; i < el.animators.length; i++) {
      var animator = el.animators[i];

      if (animator.scope === 'remove') {
        return true;
      }
    }

    return false;
  }

  function getTransform(target, ancestor) {
    var mat = identity([]);

    while (target && target !== ancestor) {
      mul$1(mat, target.getLocalTransform(), mat);
      target = target.parent;
    }

    return mat;
  }

  function applyTransform$1(target, transform, invert$1) {
    if (transform && !isArrayLike(transform)) {
      transform = Transformable.getLocalTransform(transform);
    }

    if (invert$1) {
      transform = invert([], transform);
    }

    return applyTransform([], target, transform);
  }

  function transformDirection(direction, transform, invert) {
    var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]);
    var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]);
    var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0];
    vertex = applyTransform$1(vertex, transform, invert);
    return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top';
  }

  function isNotGroup(el) {
    return !el.isGroup;
  }

  function isPath(el) {
    return el.shape != null;
  }

  function groupTransition(g1, g2, animatableModel) {
    if (!g1 || !g2) {
      return;
    }

    function getElMap(g) {
      var elMap = {};
      g.traverse(function (el) {
        if (isNotGroup(el) && el.anid) {
          elMap[el.anid] = el;
        }
      });
      return elMap;
    }

    function getAnimatableProps(el) {
      var obj = {
        x: el.x,
        y: el.y,
        rotation: el.rotation
      };

      if (isPath(el)) {
        obj.shape = extend({}, el.shape);
      }

      return obj;
    }

    var elMap1 = getElMap(g1);
    g2.traverse(function (el) {
      if (isNotGroup(el) && el.anid) {
        var oldEl = elMap1[el.anid];

        if (oldEl) {
          var newProp = getAnimatableProps(el);
          el.attr(getAnimatableProps(oldEl));
          updateProps(el, newProp, animatableModel, getECData(el).dataIndex);
        }
      }
    });
  }

  function clipPointsByRect(points, rect) {
    return map(points, function (point) {
      var x = point[0];
      x = mathMax$4(x, rect.x);
      x = mathMin$4(x, rect.x + rect.width);
      var y = point[1];
      y = mathMax$4(y, rect.y);
      y = mathMin$4(y, rect.y + rect.height);
      return [x, y];
    });
  }

  function clipRectByRect(targetRect, rect) {
    var x = mathMax$4(targetRect.x, rect.x);
    var x2 = mathMin$4(targetRect.x + targetRect.width, rect.x + rect.width);
    var y = mathMax$4(targetRect.y, rect.y);
    var y2 = mathMin$4(targetRect.y + targetRect.height, rect.y + rect.height);

    if (x2 >= x && y2 >= y) {
      return {
        x: x,
        y: y,
        width: x2 - x,
        height: y2 - y
      };
    }
  }

  function createIcon(iconStr, opt, rect) {
    var innerOpts = extend({
      rectHover: true
    }, opt);
    var style = innerOpts.style = {
      strokeNoScale: true
    };
    rect = rect || {
      x: -1,
      y: -1,
      width: 2,
      height: 2
    };

    if (iconStr) {
      return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), defaults(style, rect), new ZRImage(innerOpts)) : makePath(iconStr.replace('path://', ''), innerOpts, rect, 'center');
    }
  }

  function linePolygonIntersect(a1x, a1y, a2x, a2y, points) {
    for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {
      var p = points[i];

      if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) {
        return true;
      }

      p2 = p;
    }
  }

  function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {
    var mx = a2x - a1x;
    var my = a2y - a1y;
    var nx = b2x - b1x;
    var ny = b2y - b1y;
    var nmCrossProduct = crossProduct2d(nx, ny, mx, my);

    if (nearZero(nmCrossProduct)) {
      return false;
    }

    var b1a1x = a1x - b1x;
    var b1a1y = a1y - b1y;
    var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct;

    if (q < 0 || q > 1) {
      return false;
    }

    var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct;

    if (p < 0 || p > 1) {
      return false;
    }

    return true;
  }

  function crossProduct2d(x1, y1, x2, y2) {
    return x1 * y2 - x2 * y1;
  }

  function nearZero(val) {
    return val <= 1e-6 && val >= -1e-6;
  }

  registerShape('circle', Circle);
  registerShape('ellipse', Ellipse);
  registerShape('sector', Sector);
  registerShape('ring', Ring);
  registerShape('polygon', Polygon);
  registerShape('polyline', Polyline);
  registerShape('rect', Rect);
  registerShape('line', Line);
  registerShape('bezierCurve', BezierCurve);
  registerShape('arc', Arc);
  var graphic = /*#__PURE__*/Object.freeze({
    __proto__: null,
    extendShape: extendShape,
    extendPath: extendPath,
    registerShape: registerShape,
    getShapeClass: getShapeClass,
    makePath: makePath,
    makeImage: makeImage,
    mergePath: mergePath$1,
    resizePath: resizePath,
    subPixelOptimizeLine: subPixelOptimizeLine$1,
    subPixelOptimizeRect: subPixelOptimizeRect$1,
    subPixelOptimize: subPixelOptimize$1,
    updateProps: updateProps,
    initProps: initProps,
    removeElement: removeElement,
    removeElementWithFadeOut: removeElementWithFadeOut,
    isElementRemoved: isElementRemoved,
    getTransform: getTransform,
    applyTransform: applyTransform$1,
    transformDirection: transformDirection,
    groupTransition: groupTransition,
    clipPointsByRect: clipPointsByRect,
    clipRectByRect: clipRectByRect,
    createIcon: createIcon,
    linePolygonIntersect: linePolygonIntersect,
    lineLineIntersect: lineLineIntersect,
    Group: Group,
    Image: ZRImage,
    Text: ZRText,
    Circle: Circle,
    Ellipse: Ellipse,
    Sector: Sector,
    Ring: Ring,
    Polygon: Polygon,
    Polyline: Polyline,
    Rect: Rect,
    Line: Line,
    BezierCurve: BezierCurve,
    Arc: Arc,
    IncrementalDisplayable: IncrementalDisplayble,
    CompoundPath: CompoundPath,
    LinearGradient: LinearGradient,
    RadialGradient: RadialGradient,
    BoundingRect: BoundingRect,
    OrientedBoundingRect: OrientedBoundingRect,
    Point: Point,
    Path: Path
  });
  var EMPTY_OBJ = {};

  function setLabelText(label, labelTexts) {
    for (var i = 0; i < SPECIAL_STATES.length; i++) {
      var stateName = SPECIAL_STATES[i];
      var text = labelTexts[stateName];
      var state = label.ensureState(stateName);
      state.style = state.style || {};
      state.style.text = text;
    }

    var oldStates = label.currentStates.slice();
    label.clearStates(true);
    label.setStyle({
      text: labelTexts.normal
    });
    label.useStates(oldStates, true);
  }

  function getLabelText(opt, stateModels, overrideValue) {
    var labelFetcher = opt.labelFetcher;
    var labelDataIndex = opt.labelDataIndex;
    var labelDimIndex = opt.labelDimIndex;
    var normalModel = stateModels.normal;
    var baseText;

    if (labelFetcher) {
      baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), overrideValue != null ? {
        value: overrideValue
      } : null);
    }

    if (baseText == null) {
      baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, overrideValue) : opt.defaultText;
    }

    var statesText = {
      normal: baseText
    };

    for (var i = 0; i < SPECIAL_STATES.length; i++) {
      var stateName = SPECIAL_STATES[i];
      var stateModel = stateModels[stateName];
      statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText);
    }

    return statesText;
  }

  function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified) {
    opt = opt || EMPTY_OBJ;
    var isSetOnText = targetEl instanceof ZRText;
    var needsCreateText = false;

    for (var i = 0; i < DISPLAY_STATES.length; i++) {
      var stateModel = labelStatesModels[DISPLAY_STATES[i]];

      if (stateModel && stateModel.getShallow('show')) {
        needsCreateText = true;
        break;
      }
    }

    var textContent = isSetOnText ? targetEl : targetEl.getTextContent();

    if (needsCreateText) {
      if (!isSetOnText) {
        if (!textContent) {
          textContent = new ZRText();
          targetEl.setTextContent(textContent);
        }

        if (targetEl.stateProxy) {
          textContent.stateProxy = targetEl.stateProxy;
        }
      }

      var labelStatesTexts = getLabelText(opt, labelStatesModels);
      var normalModel = labelStatesModels.normal;
      var showNormal = !!normalModel.getShallow('show');
      var normalStyle = createTextStyle(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText);
      normalStyle.text = labelStatesTexts.normal;

      if (!isSetOnText) {
        targetEl.setTextConfig(createTextConfig(normalModel, opt, false));
      }

      for (var i = 0; i < SPECIAL_STATES.length; i++) {
        var stateName = SPECIAL_STATES[i];
        var stateModel = labelStatesModels[stateName];

        if (stateModel) {
          var stateObj = textContent.ensureState(stateName);
          var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal);

          if (stateShow !== showNormal) {
            stateObj.ignore = !stateShow;
          }

          stateObj.style = createTextStyle(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText);
          stateObj.style.text = labelStatesTexts[stateName];

          if (!isSetOnText) {
            var targetElEmphasisState = targetEl.ensureState(stateName);
            targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true);
          }
        }
      }

      textContent.silent = !!normalModel.getShallow('silent');

      if (textContent.style.x != null) {
        normalStyle.x = textContent.style.x;
      }

      if (textContent.style.y != null) {
        normalStyle.y = textContent.style.y;
      }

      textContent.ignore = !showNormal;
      textContent.useStyle(normalStyle);
      textContent.dirty();

      if (opt.enableTextSetter) {
        labelInner(textContent).setLabelText = function (overrideValue) {
          var labelStatesTexts = getLabelText(opt, labelStatesModels, overrideValue);
          setLabelText(textContent, labelStatesTexts);
        };
      }
    } else if (textContent) {
      textContent.ignore = true;
    }

    targetEl.dirty();
  }

  function getLabelStatesModels(itemModel, labelName) {
    labelName = labelName || 'label';
    var statesModels = {
      normal: itemModel.getModel(labelName)
    };

    for (var i = 0; i < SPECIAL_STATES.length; i++) {
      var stateName = SPECIAL_STATES[i];
      statesModels[stateName] = itemModel.getModel([stateName, labelName]);
    }

    return statesModels;
  }

  function createTextStyle(textStyleModel, specifiedTextStyle, opt, isNotNormal, isAttached) {
    var textStyle = {};
    setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached);
    specifiedTextStyle && extend(textStyle, specifiedTextStyle);
    return textStyle;
  }

  function createTextConfig(textStyleModel, opt, isNotNormal) {
    opt = opt || {};
    var textConfig = {};
    var labelPosition;
    var labelRotate = textStyleModel.getShallow('rotate');
    var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5);
    var labelOffset = textStyleModel.getShallow('offset');
    labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside');
    labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top');

    if (labelPosition != null) {
      textConfig.position = labelPosition;
    }

    if (labelOffset != null) {
      textConfig.offset = labelOffset;
    }

    if (labelRotate != null) {
      labelRotate *= Math.PI / 180;
      textConfig.rotation = labelRotate;
    }

    if (labelDistance != null) {
      textConfig.distance = labelDistance;
    }

    textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto';
    return textConfig;
  }

  function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) {
    opt = opt || EMPTY_OBJ;
    var ecModel = textStyleModel.ecModel;
    var globalTextStyle = ecModel && ecModel.option.textStyle;
    var richItemNames = getRichItemNames(textStyleModel);
    var richResult;

    if (richItemNames) {
      richResult = {};

      for (var name_1 in richItemNames) {
        if (richItemNames.hasOwnProperty(name_1)) {
          var richTextStyle = textStyleModel.getModel(['rich', name_1]);
          setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true);
        }
      }
    }

    if (richResult) {
      textStyle.rich = richResult;
    }

    var overflow = textStyleModel.get('overflow');

    if (overflow) {
      textStyle.overflow = overflow;
    }

    var margin = textStyleModel.get('minMargin');

    if (margin != null) {
      textStyle.margin = margin;
    }

    setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false);
  }

  function getRichItemNames(textStyleModel) {
    var richItemNameMap;

    while (textStyleModel && textStyleModel !== textStyleModel.ecModel) {
      var rich = (textStyleModel.option || EMPTY_OBJ).rich;

      if (rich) {
        richItemNameMap = richItemNameMap || {};
        var richKeys = keys(rich);

        for (var i = 0; i < richKeys.length; i++) {
          var richKey = richKeys[i];
          richItemNameMap[richKey] = 1;
        }
      }

      textStyleModel = textStyleModel.parentModel;
    }

    return richItemNameMap;
  }

  var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'];
  var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign'];
  var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];

  function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) {
    globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ;
    var inheritColor = opt && opt.inheritColor;
    var fillColor = textStyleModel.getShallow('color');
    var strokeColor = textStyleModel.getShallow('textBorderColor');
    var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity);

    if (fillColor === 'inherit' || fillColor === 'auto') {
      if (true) {
        if (fillColor === 'auto') {
          deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\'');
        }
      }

      if (inheritColor) {
        fillColor = inheritColor;
      } else {
        fillColor = null;
      }
    }

    if (strokeColor === 'inherit' || strokeColor === 'auto') {
      if (true) {
        if (strokeColor === 'auto') {
          deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\'');
        }
      }

      if (inheritColor) {
        strokeColor = inheritColor;
      } else {
        strokeColor = null;
      }
    }

    if (!isAttached) {
      fillColor = fillColor || globalTextStyle.color;
      strokeColor = strokeColor || globalTextStyle.textBorderColor;
    }

    if (fillColor != null) {
      textStyle.fill = fillColor;
    }

    if (strokeColor != null) {
      textStyle.stroke = strokeColor;
    }

    var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth);

    if (textBorderWidth != null) {
      textStyle.lineWidth = textBorderWidth;
    }

    var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType);

    if (textBorderType != null) {
      textStyle.lineDash = textBorderType;
    }

    var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset);

    if (textBorderDashOffset != null) {
      textStyle.lineDashOffset = textBorderDashOffset;
    }

    if (!isNotNormal && opacity == null && !inRich) {
      opacity = opt && opt.defaultOpacity;
    }

    if (opacity != null) {
      textStyle.opacity = opacity;
    }

    if (!isNotNormal && !isAttached) {
      if (textStyle.fill == null && opt.inheritColor) {
        textStyle.fill = opt.inheritColor;
      }
    }

    for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) {
      var key = TEXT_PROPS_WITH_GLOBAL[i];
      var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]);

      if (val != null) {
        textStyle[key] = val;
      }
    }

    for (var i = 0; i < TEXT_PROPS_SELF.length; i++) {
      var key = TEXT_PROPS_SELF[i];
      var val = textStyleModel.getShallow(key);

      if (val != null) {
        textStyle[key] = val;
      }
    }

    if (textStyle.verticalAlign == null) {
      var baseline = textStyleModel.getShallow('baseline');

      if (baseline != null) {
        textStyle.verticalAlign = baseline;
      }
    }

    if (!isBlock || !opt.disableBox) {
      for (var i = 0; i < TEXT_PROPS_BOX.length; i++) {
        var key = TEXT_PROPS_BOX[i];
        var val = textStyleModel.getShallow(key);

        if (val != null) {
          textStyle[key] = val;
        }
      }

      var borderType = textStyleModel.getShallow('borderType');

      if (borderType != null) {
        textStyle.borderDash = borderType;
      }

      if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) {
        if (true) {
          if (textStyle.backgroundColor === 'auto') {
            deprecateReplaceLog('backgroundColor: \'auto\'', 'backgroundColor: \'inherit\'');
          }
        }

        textStyle.backgroundColor = inheritColor;
      }

      if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) {
        if (true) {
          if (textStyle.borderColor === 'auto') {
            deprecateReplaceLog('borderColor: \'auto\'', 'borderColor: \'inherit\'');
          }
        }

        textStyle.borderColor = inheritColor;
      }
    }
  }

  function getFont(opt, ecModel) {
    var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
    return trim([opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' '));
  }

  var labelInner = makeInner();

  function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) {
    if (!label) {
      return;
    }

    var obj = labelInner(label);
    obj.prevValue = obj.value;
    obj.value = value;
    var normalLabelModel = labelStatesModels.normal;
    obj.valueAnimation = normalLabelModel.get('valueAnimation');

    if (obj.valueAnimation) {
      obj.precision = normalLabelModel.get('precision');
      obj.defaultInterpolatedText = getDefaultText;
      obj.statesModels = labelStatesModels;
    }
  }

  function animateLabelValue(textEl, dataIndex, data, seriesModel) {
    var labelInnerStore = labelInner(textEl);

    if (!labelInnerStore.valueAnimation) {
      return;
    }

    var defaultInterpolatedText = labelInnerStore.defaultInterpolatedText;
    var prevValue = labelInnerStore.prevValue;
    var currentValue = labelInnerStore.value;

    function during(percent) {
      var interpolated = interpolateRawValues(data, labelInnerStore.precision, prevValue, currentValue, percent);
      var labelText = getLabelText({
        labelDataIndex: dataIndex,
        defaultText: defaultInterpolatedText ? defaultInterpolatedText(interpolated) : interpolated + ''
      }, labelInnerStore.statesModels, interpolated);
      setLabelText(textEl, labelText);
    }

    (prevValue == null ? initProps : updateProps)(textEl, {}, seriesModel, dataIndex, null, during);
  }

  var PATH_COLOR = ['textStyle', 'color'];
  var tmpRichText = new ZRText();

  var TextStyleMixin = function () {
    function TextStyleMixin() {}

    TextStyleMixin.prototype.getTextColor = function (isEmphasis) {
      var ecModel = this.ecModel;
      return this.getShallow('color') || (!isEmphasis && ecModel ? ecModel.get(PATH_COLOR) : null);
    };

    TextStyleMixin.prototype.getFont = function () {
      return getFont({
        fontStyle: this.getShallow('fontStyle'),
        fontWeight: this.getShallow('fontWeight'),
        fontSize: this.getShallow('fontSize'),
        fontFamily: this.getShallow('fontFamily')
      }, this.ecModel);
    };

    TextStyleMixin.prototype.getTextRect = function (text) {
      tmpRichText.useStyle({
        text: text,
        fontStyle: this.getShallow('fontStyle'),
        fontWeight: this.getShallow('fontWeight'),
        fontSize: this.getShallow('fontSize'),
        fontFamily: this.getShallow('fontFamily'),
        verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline'),
        padding: this.getShallow('padding'),
        lineHeight: this.getShallow('lineHeight'),
        rich: this.getShallow('rich')
      });
      tmpRichText.update();
      return tmpRichText.getBoundingRect();
    };

    return TextStyleMixin;
  }();

  var LINE_STYLE_KEY_MAP = [['lineWidth', 'width'], ['stroke', 'color'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'type'], ['lineDashOffset', 'dashOffset'], ['lineCap', 'cap'], ['lineJoin', 'join'], ['miterLimit']];
  var getLineStyle = makeStyleMapper(LINE_STYLE_KEY_MAP);

  var LineStyleMixin = function () {
    function LineStyleMixin() {}

    LineStyleMixin.prototype.getLineStyle = function (excludes) {
      return getLineStyle(this, excludes);
    };

    return LineStyleMixin;
  }();

  var ITEM_STYLE_KEY_MAP = [['fill', 'color'], ['stroke', 'borderColor'], ['lineWidth', 'borderWidth'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'borderType'], ['lineDashOffset', 'borderDashOffset'], ['lineCap', 'borderCap'], ['lineJoin', 'borderJoin'], ['miterLimit', 'borderMiterLimit']];
  var getItemStyle = makeStyleMapper(ITEM_STYLE_KEY_MAP);

  var ItemStyleMixin = function () {
    function ItemStyleMixin() {}

    ItemStyleMixin.prototype.getItemStyle = function (excludes, includes) {
      return getItemStyle(this, excludes, includes);
    };

    return ItemStyleMixin;
  }();

  var Model = function () {
    function Model(option, parentModel, ecModel) {
      this.parentModel = parentModel;
      this.ecModel = ecModel;
      this.option = option;
    }

    Model.prototype.init = function (option, parentModel, ecModel) {
      var rest = [];

      for (var _i = 3; _i < arguments.length; _i++) {
        rest[_i - 3] = arguments[_i];
      }
    };

    Model.prototype.mergeOption = function (option, ecModel) {
      merge(this.option, option, true);
    };

    Model.prototype.get = function (path, ignoreParent) {
      if (path == null) {
        return this.option;
      }

      return this._doGet(this.parsePath(path), !ignoreParent && this.parentModel);
    };

    Model.prototype.getShallow = function (key, ignoreParent) {
      var option = this.option;
      var val = option == null ? option : option[key];

      if (val == null && !ignoreParent) {
        var parentModel = this.parentModel;

        if (parentModel) {
          val = parentModel.getShallow(key);
        }
      }

      return val;
    };

    Model.prototype.getModel = function (path, parentModel) {
      var hasPath = path != null;
      var pathFinal = hasPath ? this.parsePath(path) : null;
      var obj = hasPath ? this._doGet(pathFinal) : this.option;
      parentModel = parentModel || this.parentModel && this.parentModel.getModel(this.resolveParentPath(pathFinal));
      return new Model(obj, parentModel, this.ecModel);
    };

    Model.prototype.isEmpty = function () {
      return this.option == null;
    };

    Model.prototype.restoreData = function () {};

    Model.prototype.clone = function () {
      var Ctor = this.constructor;
      return new Ctor(clone(this.option));
    };

    Model.prototype.parsePath = function (path) {
      if (typeof path === 'string') {
        return path.split('.');
      }

      return path;
    };

    Model.prototype.resolveParentPath = function (path) {
      return path;
    };

    Model.prototype.isAnimationEnabled = function () {
      if (!env.node && this.option) {
        if (this.option.animation != null) {
          return !!this.option.animation;
        } else if (this.parentModel) {
          return this.parentModel.isAnimationEnabled();
        }
      }
    };

    Model.prototype._doGet = function (pathArr, parentModel) {
      var obj = this.option;

      if (!pathArr) {
        return obj;
      }

      for (var i = 0; i < pathArr.length; i++) {
        if (!pathArr[i]) {
          continue;
        }

        obj = obj && typeof obj === 'object' ? obj[pathArr[i]] : null;

        if (obj == null) {
          break;
        }
      }

      if (obj == null && parentModel) {
        obj = parentModel._doGet(this.resolveParentPath(pathArr), parentModel.parentModel);
      }

      return obj;
    };

    return Model;
  }();

  enableClassExtend(Model);
  enableClassCheck(Model);
  mixin(Model, LineStyleMixin);
  mixin(Model, ItemStyleMixin);
  mixin(Model, AreaStyleMixin);
  mixin(Model, TextStyleMixin);
  var base = Math.round(Math.random() * 10);

  function getUID(type) {
    return [type || '', base++].join('_');
  }

  function enableSubTypeDefaulter(target) {
    var subTypeDefaulters = {};

    target.registerSubTypeDefaulter = function (componentType, defaulter) {
      var componentTypeInfo = parseClassType(componentType);
      subTypeDefaulters[componentTypeInfo.main] = defaulter;
    };

    target.determineSubType = function (componentType, option) {
      var type = option.type;

      if (!type) {
        var componentTypeMain = parseClassType(componentType).main;

        if (target.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) {
          type = subTypeDefaulters[componentTypeMain](option);
        }
      }

      return type;
    };
  }

  function enableTopologicalTravel(entity, dependencyGetter) {
    entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) {
      if (!targetNameList.length) {
        return;
      }

      var result = makeDepndencyGraph(fullNameList);
      var graph = result.graph;
      var noEntryList = result.noEntryList;
      var targetNameSet = {};
      each(targetNameList, function (name) {
        targetNameSet[name] = true;
      });

      while (noEntryList.length) {
        var currComponentType = noEntryList.pop();
        var currVertex = graph[currComponentType];
        var isInTargetNameSet = !!targetNameSet[currComponentType];

        if (isInTargetNameSet) {
          callback.call(context, currComponentType, currVertex.originalDeps.slice());
          delete targetNameSet[currComponentType];
        }

        each(currVertex.successor, isInTargetNameSet ? removeEdgeAndAdd : removeEdge);
      }

      each(targetNameSet, function () {
        var errMsg = '';

        if (true) {
          errMsg = makePrintable('Circle dependency may exists: ', targetNameSet, targetNameList, fullNameList);
        }

        throw new Error(errMsg);
      });

      function removeEdge(succComponentType) {
        graph[succComponentType].entryCount--;

        if (graph[succComponentType].entryCount === 0) {
          noEntryList.push(succComponentType);
        }
      }

      function removeEdgeAndAdd(succComponentType) {
        targetNameSet[succComponentType] = true;
        removeEdge(succComponentType);
      }
    };

    function makeDepndencyGraph(fullNameList) {
      var graph = {};
      var noEntryList = [];
      each(fullNameList, function (name) {
        var thisItem = createDependencyGraphItem(graph, name);
        var originalDeps = thisItem.originalDeps = dependencyGetter(name);
        var availableDeps = getAvailableDependencies(originalDeps, fullNameList);
        thisItem.entryCount = availableDeps.length;

        if (thisItem.entryCount === 0) {
          noEntryList.push(name);
        }

        each(availableDeps, function (dependentName) {
          if (indexOf(thisItem.predecessor, dependentName) < 0) {
            thisItem.predecessor.push(dependentName);
          }

          var thatItem = createDependencyGraphItem(graph, dependentName);

          if (indexOf(thatItem.successor, dependentName) < 0) {
            thatItem.successor.push(name);
          }
        });
      });
      return {
        graph: graph,
        noEntryList: noEntryList
      };
    }

    function createDependencyGraphItem(graph, name) {
      if (!graph[name]) {
        graph[name] = {
          predecessor: [],
          successor: []
        };
      }

      return graph[name];
    }

    function getAvailableDependencies(originalDeps, fullNameList) {
      var availableDeps = [];
      each(originalDeps, function (dep) {
        indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep);
      });
      return availableDeps;
    }
  }

  function inheritDefaultOption(superOption, subOption) {
    return merge(merge({}, superOption, true), subOption, true);
  }

  var langEN = {
    time: {
      month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      monthAbbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
      dayOfWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
      dayOfWeekAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
    },
    legend: {
      selector: {
        all: 'All',
        inverse: 'Inv'
      }
    },
    toolbox: {
      brush: {
        title: {
          rect: 'Box Select',
          polygon: 'Lasso Select',
          lineX: 'Horizontally Select',
          lineY: 'Vertically Select',
          keep: 'Keep Selections',
          clear: 'Clear Selections'
        }
      },
      dataView: {
        title: 'Data View',
        lang: ['Data View', 'Close', 'Refresh']
      },
      dataZoom: {
        title: {
          zoom: 'Zoom',
          back: 'Zoom Reset'
        }
      },
      magicType: {
        title: {
          line: 'Switch to Line Chart',
          bar: 'Switch to Bar Chart',
          stack: 'Stack',
          tiled: 'Tile'
        }
      },
      restore: {
        title: 'Restore'
      },
      saveAsImage: {
        title: 'Save as Image',
        lang: ['Right Click to Save Image']
      }
    },
    series: {
      typeNames: {
        pie: 'Pie chart',
        bar: 'Bar chart',
        line: 'Line chart',
        scatter: 'Scatter plot',
        effectScatter: 'Ripple scatter plot',
        radar: 'Radar chart',
        tree: 'Tree',
        treemap: 'Treemap',
        boxplot: 'Boxplot',
        candlestick: 'Candlestick',
        k: 'K line chart',
        heatmap: 'Heat map',
        map: 'Map',
        parallel: 'Parallel coordinate map',
        lines: 'Line graph',
        graph: 'Relationship graph',
        sankey: 'Sankey diagram',
        funnel: 'Funnel chart',
        gauge: 'Guage',
        pictorialBar: 'Pictorial bar',
        themeRiver: 'Theme River Map',
        sunburst: 'Sunburst'
      }
    },
    aria: {
      general: {
        withTitle: 'This is a chart about "{title}"',
        withoutTitle: 'This is a chart'
      },
      series: {
        single: {
          prefix: '',
          withName: ' with type {seriesType} named {seriesName}.',
          withoutName: ' with type {seriesType}.'
        },
        multiple: {
          prefix: '. It consists of {seriesCount} series count.',
          withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.',
          withoutName: ' The {seriesId} series is a {seriesType}.',
          separator: {
            middle: '',
            end: ''
          }
        }
      },
      data: {
        allData: 'The data is as follows: ',
        partialData: 'The first {displayCnt} items are: ',
        withName: 'the data for {name} is {value}',
        withoutName: '{value}',
        separator: {
          middle: ', ',
          end: '. '
        }
      }
    }
  };
  var langZH = {
    time: {
      month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
      monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
      dayOfWeek: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
      dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六']
    },
    legend: {
      selector: {
        all: '全选',
        inverse: '反选'
      }
    },
    toolbox: {
      brush: {
        title: {
          rect: '矩形选择',
          polygon: '圈选',
          lineX: '横向选择',
          lineY: '纵向选择',
          keep: '保持选择',
          clear: '清除选择'
        }
      },
      dataView: {
        title: '数据视图',
        lang: ['数据视图', '关闭', '刷新']
      },
      dataZoom: {
        title: {
          zoom: '区域缩放',
          back: '区域缩放还原'
        }
      },
      magicType: {
        title: {
          line: '切换为折线图',
          bar: '切换为柱状图',
          stack: '切换为堆叠',
          tiled: '切换为平铺'
        }
      },
      restore: {
        title: '还原'
      },
      saveAsImage: {
        title: '保存为图片',
        lang: ['右键另存为图片']
      }
    },
    series: {
      typeNames: {
        pie: '饼图',
        bar: '柱状图',
        line: '折线图',
        scatter: '散点图',
        effectScatter: '涟漪散点图',
        radar: '雷达图',
        tree: '树图',
        treemap: '矩形树图',
        boxplot: '箱型图',
        candlestick: 'K线图',
        k: 'K线图',
        heatmap: '热力图',
        map: '地图',
        parallel: '平行坐标图',
        lines: '线图',
        graph: '关系图',
        sankey: '桑基图',
        funnel: '漏斗图',
        gauge: '仪表盘图',
        pictorialBar: '象形柱图',
        themeRiver: '主题河流图',
        sunburst: '旭日图'
      }
    },
    aria: {
      general: {
        withTitle: '这是一个关于“{title}”的图表。',
        withoutTitle: '这是一个图表，'
      },
      series: {
        single: {
          prefix: '',
          withName: '图表类型是{seriesType}，表示{seriesName}。',
          withoutName: '图表类型是{seriesType}。'
        },
        multiple: {
          prefix: '它由{seriesCount}个图表系列组成。',
          withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType}，',
          withoutName: '第{seriesId}个系列是一个{seriesType}，',
          separator: {
            middle: '；',
            end: '。'
          }
        }
      },
      data: {
        allData: '其数据是——',
        partialData: '其中，前{displayCnt}项是——',
        withName: '{name}的数据是{value}',
        withoutName: '{value}',
        separator: {
          middle: '，',
          end: ''
        }
      }
    }
  };
  var LOCALE_ZH = 'ZH';
  var LOCALE_EN = 'EN';
  var DEFAULT_LOCALE = LOCALE_EN;
  var localeStorage = {};
  var localeModels = {};
  var SYSTEM_LANG = !env.domSupported ? DEFAULT_LOCALE : function () {
    var langStr = (document.documentElement.lang || navigator.language || navigator.browserLanguage).toUpperCase();
    return langStr.indexOf(LOCALE_ZH) > -1 ? LOCALE_ZH : DEFAULT_LOCALE;
  }();

  function registerLocale(locale, localeObj) {
    locale = locale.toUpperCase();
    localeModels[locale] = new Model(localeObj);
    localeStorage[locale] = localeObj;
  }

  function createLocaleObject(locale) {
    if (isString(locale)) {
      var localeObj = localeStorage[locale.toUpperCase()] || {};

      if (locale === LOCALE_ZH || locale === LOCALE_EN) {
        return clone(localeObj);
      } else {
        return merge(clone(localeObj), clone(localeStorage[DEFAULT_LOCALE]), false);
      }
    } else {
      return merge(clone(locale), clone(localeStorage[DEFAULT_LOCALE]), false);
    }
  }

  function getLocaleModel(lang) {
    return localeModels[lang];
  }

  function getDefaultLocaleModel() {
    return localeModels[DEFAULT_LOCALE];
  }

  registerLocale(LOCALE_EN, langEN);
  registerLocale(LOCALE_ZH, langZH);
  var ONE_SECOND = 1000;
  var ONE_MINUTE = ONE_SECOND * 60;
  var ONE_HOUR = ONE_MINUTE * 60;
  var ONE_DAY = ONE_HOUR * 24;
  var ONE_YEAR = ONE_DAY * 365;
  var defaultLeveledFormatter = {
    year: '{yyyy}',
    month: '{MMM}',
    day: '{d}',
    hour: '{HH}:{mm}',
    minute: '{HH}:{mm}',
    second: '{HH}:{mm}:{ss}',
    millisecond: '{hh}:{mm}:{ss} {SSS}',
    none: '{yyyy}-{MM}-{dd} {hh}:{mm}:{ss} {SSS}'
  };
  var fullDayFormatter = '{yyyy}-{MM}-{dd}';
  var fullLeveledFormatter = {
    year: '{yyyy}',
    month: '{yyyy}-{MM}',
    day: fullDayFormatter,
    hour: fullDayFormatter + ' ' + defaultLeveledFormatter.hour,
    minute: fullDayFormatter + ' ' + defaultLeveledFormatter.minute,
    second: fullDayFormatter + ' ' + defaultLeveledFormatter.second,
    millisecond: defaultLeveledFormatter.none
  };
  var primaryTimeUnits = ['year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond'];
  var timeUnits = ['year', 'half-year', 'quarter', 'month', 'week', 'half-week', 'day', 'half-day', 'quarter-day', 'hour', 'minute', 'second', 'millisecond'];

  function pad(str, len) {
    str += '';
    return '0000'.substr(0, len - str.length) + str;
  }

  function getPrimaryTimeUnit(timeUnit) {
    switch (timeUnit) {
      case 'half-year':
      case 'quarter':
        return 'month';

      case 'week':
      case 'half-week':
        return 'day';

      case 'half-day':
      case 'quarter-day':
        return 'hour';

      default:
        return timeUnit;
    }
  }

  function isPrimaryTimeUnit(timeUnit) {
    return timeUnit === getPrimaryTimeUnit(timeUnit);
  }

  function getDefaultFormatPrecisionOfInterval(timeUnit) {
    switch (timeUnit) {
      case 'year':
      case 'month':
        return 'day';

      case 'millisecond':
        return 'millisecond';

      default:
        return 'second';
    }
  }

  function format(time, template, isUTC, lang) {
    var date = parseDate(time);
    var y = date[fullYearGetterName(isUTC)]();
    var M = date[monthGetterName(isUTC)]() + 1;
    var q = Math.floor((M - 1) / 4) + 1;
    var d = date[dateGetterName(isUTC)]();
    var e = date['get' + (isUTC ? 'UTC' : '') + 'Day']();
    var H = date[hoursGetterName(isUTC)]();
    var h = (H - 1) % 12 + 1;
    var m = date[minutesGetterName(isUTC)]();
    var s = date[secondsGetterName(isUTC)]();
    var S = date[millisecondsGetterName(isUTC)]();
    var localeModel = lang instanceof Model ? lang : getLocaleModel(lang || SYSTEM_LANG) || getDefaultLocaleModel();
    var timeModel = localeModel.getModel('time');
    var month = timeModel.get('month');
    var monthAbbr = timeModel.get('monthAbbr');
    var dayOfWeek = timeModel.get('dayOfWeek');
    var dayOfWeekAbbr = timeModel.get('dayOfWeekAbbr');
    return (template || '').replace(/{yyyy}/g, y + '').replace(/{yy}/g, y % 100 + '').replace(/{Q}/g, q + '').replace(/{MMMM}/g, month[M - 1]).replace(/{MMM}/g, monthAbbr[M - 1]).replace(/{MM}/g, pad(M, 2)).replace(/{M}/g, M + '').replace(/{dd}/g, pad(d, 2)).replace(/{d}/g, d + '').replace(/{eeee}/g, dayOfWeek[e]).replace(/{ee}/g, dayOfWeekAbbr[e]).replace(/{e}/g, e + '').replace(/{HH}/g, pad(H, 2)).replace(/{H}/g, H + '').replace(/{hh}/g, pad(h + '', 2)).replace(/{h}/g, h + '').replace(/{mm}/g, pad(m, 2)).replace(/{m}/g, m + '').replace(/{ss}/g, pad(s, 2)).replace(/{s}/g, s + '').replace(/{SSS}/g, pad(S, 3)).replace(/{S}/g, S + '');
  }

  function leveledFormat(tick, idx, formatter, lang, isUTC) {
    var template = null;

    if (typeof formatter === 'string') {
      template = formatter;
    } else if (typeof formatter === 'function') {
      template = formatter(tick.value, idx, {
        level: tick.level
      });
    } else {
      var defaults$1 = extend({}, defaultLeveledFormatter);

      if (tick.level > 0) {
        for (var i = 0; i < primaryTimeUnits.length; ++i) {
          defaults$1[primaryTimeUnits[i]] = "{primary|" + defaults$1[primaryTimeUnits[i]] + "}";
        }
      }

      var mergedFormatter = formatter ? formatter.inherit === false ? formatter : defaults(formatter, defaults$1) : defaults$1;
      var unit = getUnitFromValue(tick.value, isUTC);

      if (mergedFormatter[unit]) {
        template = mergedFormatter[unit];
      } else if (mergedFormatter.inherit) {
        var targetId = timeUnits.indexOf(unit);

        for (var i = targetId - 1; i >= 0; --i) {
          if (mergedFormatter[unit]) {
            template = mergedFormatter[unit];
            break;
          }
        }

        template = template || defaults$1.none;
      }

      if (isArray(template)) {
        var levelId = tick.level == null ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level;
        levelId = Math.min(levelId, template.length - 1);
        template = template[levelId];
      }
    }

    return format(new Date(tick.value), template, isUTC, lang);
  }

  function getUnitFromValue(value, isUTC) {
    var date = parseDate(value);
    var M = date[monthGetterName(isUTC)]() + 1;
    var d = date[dateGetterName(isUTC)]();
    var h = date[hoursGetterName(isUTC)]();
    var m = date[minutesGetterName(isUTC)]();
    var s = date[secondsGetterName(isUTC)]();
    var S = date[millisecondsGetterName(isUTC)]();
    var isSecond = S === 0;
    var isMinute = isSecond && s === 0;
    var isHour = isMinute && m === 0;
    var isDay = isHour && h === 0;
    var isMonth = isDay && d === 1;
    var isYear = isMonth && M === 1;

    if (isYear) {
      return 'year';
    } else if (isMonth) {
      return 'month';
    } else if (isDay) {
      return 'day';
    } else if (isHour) {
      return 'hour';
    } else if (isMinute) {
      return 'minute';
    } else if (isSecond) {
      return 'second';
    } else {
      return 'millisecond';
    }
  }

  function getUnitValue(value, unit, isUTC) {
    var date = typeof value === 'number' ? parseDate(value) : value;
    unit = unit || getUnitFromValue(value, isUTC);

    switch (unit) {
      case 'year':
        return date[fullYearGetterName(isUTC)]();

      case 'half-year':
        return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0;

      case 'quarter':
        return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4);

      case 'month':
        return date[monthGetterName(isUTC)]();

      case 'day':
        return date[dateGetterName(isUTC)]();

      case 'half-day':
        return date[hoursGetterName(isUTC)]() / 24;

      case 'hour':
        return date[hoursGetterName(isUTC)]();

      case 'minute':
        return date[minutesGetterName(isUTC)]();

      case 'second':
        return date[secondsGetterName(isUTC)]();

      case 'millisecond':
        return date[millisecondsGetterName(isUTC)]();
    }
  }

  function fullYearGetterName(isUTC) {
    return isUTC ? 'getUTCFullYear' : 'getFullYear';
  }

  function monthGetterName(isUTC) {
    return isUTC ? 'getUTCMonth' : 'getMonth';
  }

  function dateGetterName(isUTC) {
    return isUTC ? 'getUTCDate' : 'getDate';
  }

  function hoursGetterName(isUTC) {
    return isUTC ? 'getUTCHours' : 'getHours';
  }

  function minutesGetterName(isUTC) {
    return isUTC ? 'getUTCMinutes' : 'getMinutes';
  }

  function secondsGetterName(isUTC) {
    return isUTC ? 'getUTCSeconds' : 'getSeconds';
  }

  function millisecondsGetterName(isUTC) {
    return isUTC ? 'getUTCSeconds' : 'getSeconds';
  }

  function fullYearSetterName(isUTC) {
    return isUTC ? 'setUTCFullYear' : 'setFullYear';
  }

  function monthSetterName(isUTC) {
    return isUTC ? 'setUTCMonth' : 'setMonth';
  }

  function dateSetterName(isUTC) {
    return isUTC ? 'setUTCDate' : 'setDate';
  }

  function hoursSetterName(isUTC) {
    return isUTC ? 'setUTCHours' : 'setHours';
  }

  function minutesSetterName(isUTC) {
    return isUTC ? 'setUTCMinutes' : 'setMinutes';
  }

  function secondsSetterName(isUTC) {
    return isUTC ? 'setUTCSeconds' : 'setSeconds';
  }

  function millisecondsSetterName(isUTC) {
    return isUTC ? 'setUTCSeconds' : 'setSeconds';
  }

  function getTextRect(text, font, align, verticalAlign, padding, rich, truncate, lineHeight) {
    deprecateLog('getTextRect is deprecated.');
    var textEl = new ZRText({
      style: {
        text: text,
        font: font,
        align: align,
        verticalAlign: verticalAlign,
        padding: padding,
        rich: rich,
        overflow: truncate ? 'truncate' : null,
        lineHeight: lineHeight
      }
    });
    return textEl.getBoundingRect();
  }

  function addCommas(x) {
    if (!isNumeric(x)) {
      return isString(x) ? x : '-';
    }

    var parts = (x + '').split('.');
    return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (parts.length > 1 ? '.' + parts[1] : '');
  }

  function toCamelCase(str, upperCaseFirst) {
    str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) {
      return group1.toUpperCase();
    });

    if (upperCaseFirst && str) {
      str = str.charAt(0).toUpperCase() + str.slice(1);
    }

    return str;
  }

  var normalizeCssArray$1 = normalizeCssArray;
  var replaceReg = /([&<>"'])/g;
  var replaceMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    '\'': '&#39;'
  };

  function encodeHTML(source) {
    return source == null ? '' : (source + '').replace(replaceReg, function (str, c) {
      return replaceMap[c];
    });
  }

  function makeValueReadable(value, valueType, useUTC) {
    var USER_READABLE_DEFUALT_TIME_PATTERN = 'yyyy-MM-dd hh:mm:ss';

    function stringToUserReadable(str) {
      return str && trim(str) ? str : '-';
    }

    function isNumberUserReadable(num) {
      return !!(num != null && !isNaN(num) && isFinite(num));
    }

    var isTypeTime = valueType === 'time';
    var isValueDate = value instanceof Date;

    if (isTypeTime || isValueDate) {
      var date = isTypeTime ? parseDate(value) : value;

      if (!isNaN(+date)) {
        return format(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC);
      } else if (isValueDate) {
        return '-';
      }
    }

    if (valueType === 'ordinal') {
      return isStringSafe(value) ? stringToUserReadable(value) : isNumber(value) ? isNumberUserReadable(value) ? value + '' : '-' : '-';
    }

    var numericResult = numericToNumber(value);
    return isNumberUserReadable(numericResult) ? addCommas(numericResult) : isStringSafe(value) ? stringToUserReadable(value) : '-';
  }

  var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

  var wrapVar = function (varName, seriesIdx) {
    return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
  };

  function formatTpl(tpl, paramsList, encode) {
    if (!isArray(paramsList)) {
      paramsList = [paramsList];
    }

    var seriesLen = paramsList.length;

    if (!seriesLen) {
      return '';
    }

    var $vars = paramsList[0].$vars || [];

    for (var i = 0; i < $vars.length; i++) {
      var alias = TPL_VAR_ALIAS[i];
      tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0));
    }

    for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
      for (var k = 0; k < $vars.length; k++) {
        var val = paramsList[seriesIdx][$vars[k]];
        tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val);
      }
    }

    return tpl;
  }

  function formatTplSimple(tpl, param, encode) {
    each(param, function (value, key) {
      tpl = tpl.replace('{' + key + '}', encode ? encodeHTML(value) : value);
    });
    return tpl;
  }

  function getTooltipMarker(inOpt, extraCssText) {
    var opt = isString(inOpt) ? {
      color: inOpt,
      extraCssText: extraCssText
    } : inOpt || {};
    var color = opt.color;
    var type = opt.type;
    extraCssText = opt.extraCssText;
    var renderMode = opt.renderMode || 'html';

    if (!color) {
      return '';
    }

    if (renderMode === 'html') {
      return type === 'subItem' ? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;' + 'border-radius:4px;width:4px;height:4px;background-color:' + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>' : '<span style="display:inline-block;margin-right:4px;' + 'border-radius:10px;width:10px;height:10px;background-color:' + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>';
    } else {
      var markerId = opt.markerId || 'markerX';
      return {
        renderMode: renderMode,
        content: '{' + markerId + '|}  ',
        style: type === 'subItem' ? {
          width: 4,
          height: 4,
          borderRadius: 2,
          backgroundColor: color
        } : {
          width: 10,
          height: 10,
          borderRadius: 5,
          backgroundColor: color
        }
      };
    }
  }

  function formatTime(tpl, value, isUTC) {
    if (true) {
      deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format');
    }

    if (tpl === 'week' || tpl === 'month' || tpl === 'quarter' || tpl === 'half-year' || tpl === 'year') {
      tpl = 'MM-dd\nyyyy';
    }

    var date = parseDate(value);
    var utc = isUTC ? 'UTC' : '';
    var y = date['get' + utc + 'FullYear']();
    var M = date['get' + utc + 'Month']() + 1;
    var d = date['get' + utc + 'Date']();
    var h = date['get' + utc + 'Hours']();
    var m = date['get' + utc + 'Minutes']();
    var s = date['get' + utc + 'Seconds']();
    var S = date['get' + utc + 'Milliseconds']();
    tpl = tpl.replace('MM', pad(M, 2)).replace('M', M).replace('yyyy', y).replace('yy', y % 100 + '').replace('dd', pad(d, 2)).replace('d', d).replace('hh', pad(h, 2)).replace('h', h).replace('mm', pad(m, 2)).replace('m', m).replace('ss', pad(s, 2)).replace('s', s).replace('SSS', pad(S, 3));
    return tpl;
  }

  function capitalFirst(str) {
    return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
  }

  function convertToColorString(color, defaultColor) {
    defaultColor = defaultColor || 'transparent';
    return isString(color) ? color : isObject(color) ? color.colorStops && (color.colorStops[0] || {}).color || defaultColor : defaultColor;
  }

  function windowOpen(link, target) {
    if (target === '_blank' || target === 'blank') {
      var blank = window.open();
      blank.opener = null;
      blank.location.href = link;
    } else {
      window.open(link, target);
    }
  }

  var formatUtil = /*#__PURE__*/Object.freeze({
    __proto__: null,
    addCommas: addCommas,
    toCamelCase: toCamelCase,
    normalizeCssArray: normalizeCssArray$1,
    encodeHTML: encodeHTML,
    makeValueReadable: makeValueReadable,
    formatTpl: formatTpl,
    formatTplSimple: formatTplSimple,
    getTooltipMarker: getTooltipMarker,
    formatTime: formatTime,
    capitalFirst: capitalFirst,
    convertToColorString: convertToColorString,
    windowOpen: windowOpen,
    truncateText: truncateText,
    getTextRect: getTextRect
  });
  var each$1 = each;
  var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height'];
  var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']];

  function boxLayout(orient, group, gap, maxWidth, maxHeight) {
    var x = 0;
    var y = 0;

    if (maxWidth == null) {
      maxWidth = Infinity;
    }

    if (maxHeight == null) {
      maxHeight = Infinity;
    }

    var currentLineMaxSize = 0;
    group.eachChild(function (child, idx) {
      var rect = child.getBoundingRect();
      var nextChild = group.childAt(idx + 1);
      var nextChildRect = nextChild && nextChild.getBoundingRect();
      var nextX;
      var nextY;

      if (orient === 'horizontal') {
        var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0);
        nextX = x + moveX;

        if (nextX > maxWidth || child.newline) {
          x = 0;
          nextX = moveX;
          y += currentLineMaxSize + gap;
          currentLineMaxSize = rect.height;
        } else {
          currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
        }
      } else {
        var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0);
        nextY = y + moveY;

        if (nextY > maxHeight || child.newline) {
          x += currentLineMaxSize + gap;
          y = 0;
          nextY = moveY;
          currentLineMaxSize = rect.width;
        } else {
          currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
        }
      }

      if (child.newline) {
        return;
      }

      child.x = x;
      child.y = y;
      child.markRedraw();
      orient === 'horizontal' ? x = nextX + gap : y = nextY + gap;
    });
  }

  var box = boxLayout;
  var vbox = curry(boxLayout, 'vertical');
  var hbox = curry(boxLayout, 'horizontal');

  function getAvailableSize(positionInfo, containerRect, margin) {
    var containerWidth = containerRect.width;
    var containerHeight = containerRect.height;
    var x = parsePercent$2(positionInfo.left, containerWidth);
    var y = parsePercent$2(positionInfo.top, containerHeight);
    var x2 = parsePercent$2(positionInfo.right, containerWidth);
    var y2 = parsePercent$2(positionInfo.bottom, containerHeight);
    (isNaN(x) || isNaN(parseFloat(positionInfo.left))) && (x = 0);
    (isNaN(x2) || isNaN(parseFloat(positionInfo.right))) && (x2 = containerWidth);
    (isNaN(y) || isNaN(parseFloat(positionInfo.top))) && (y = 0);
    (isNaN(y2) || isNaN(parseFloat(positionInfo.bottom))) && (y2 = containerHeight);
    margin = normalizeCssArray$1(margin || 0);
    return {
      width: Math.max(x2 - x - margin[1] - margin[3], 0),
      height: Math.max(y2 - y - margin[0] - margin[2], 0)
    };
  }

  function getLayoutRect(positionInfo, containerRect, margin) {
    margin = normalizeCssArray$1(margin || 0);
    var containerWidth = containerRect.width;
    var containerHeight = containerRect.height;
    var left = parsePercent$2(positionInfo.left, containerWidth);
    var top = parsePercent$2(positionInfo.top, containerHeight);
    var right = parsePercent$2(positionInfo.right, containerWidth);
    var bottom = parsePercent$2(positionInfo.bottom, containerHeight);
    var width = parsePercent$2(positionInfo.width, containerWidth);
    var height = parsePercent$2(positionInfo.height, containerHeight);
    var verticalMargin = margin[2] + margin[0];
    var horizontalMargin = margin[1] + margin[3];
    var aspect = positionInfo.aspect;

    if (isNaN(width)) {
      width = containerWidth - right - horizontalMargin - left;
    }

    if (isNaN(height)) {
      height = containerHeight - bottom - verticalMargin - top;
    }

    if (aspect != null) {
      if (isNaN(width) && isNaN(height)) {
        if (aspect > containerWidth / containerHeight) {
          width = containerWidth * 0.8;
        } else {
          height = containerHeight * 0.8;
        }
      }

      if (isNaN(width)) {
        width = aspect * height;
      }

      if (isNaN(height)) {
        height = width / aspect;
      }
    }

    if (isNaN(left)) {
      left = containerWidth - right - width - horizontalMargin;
    }

    if (isNaN(top)) {
      top = containerHeight - bottom - height - verticalMargin;
    }

    switch (positionInfo.left || positionInfo.right) {
      case 'center':
        left = containerWidth / 2 - width / 2 - margin[3];
        break;

      case 'right':
        left = containerWidth - width - horizontalMargin;
        break;
    }

    switch (positionInfo.top || positionInfo.bottom) {
      case 'middle':
      case 'center':
        top = containerHeight / 2 - height / 2 - margin[0];
        break;

      case 'bottom':
        top = containerHeight - height - verticalMargin;
        break;
    }

    left = left || 0;
    top = top || 0;

    if (isNaN(width)) {
      width = containerWidth - horizontalMargin - left - (right || 0);
    }

    if (isNaN(height)) {
      height = containerHeight - verticalMargin - top - (bottom || 0);
    }

    var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
    rect.margin = margin;
    return rect;
  }

  function positionElement(el, positionInfo, containerRect, margin, opt) {
    var h = !opt || !opt.hv || opt.hv[0];
    var v = !opt || !opt.hv || opt.hv[1];
    var boundingMode = opt && opt.boundingMode || 'all';

    if (!h && !v) {
      return;
    }

    var rect;

    if (boundingMode === 'raw') {
      rect = el.type === 'group' ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) : el.getBoundingRect();
    } else {
      rect = el.getBoundingRect();

      if (el.needLocalTransform()) {
        var transform = el.getLocalTransform();
        rect = rect.clone();
        rect.applyTransform(transform);
      }
    }

    var layoutRect = getLayoutRect(defaults({
      width: rect.width,
      height: rect.height
    }, positionInfo), containerRect, margin);
    var dx = h ? layoutRect.x - rect.x : 0;
    var dy = v ? layoutRect.y - rect.y : 0;

    if (boundingMode === 'raw') {
      el.x = dx;
      el.y = dy;
    } else {
      el.x += dx;
      el.y += dy;
    }

    el.markRedraw();
  }

  function sizeCalculable(option, hvIdx) {
    return option[HV_NAMES[hvIdx][0]] != null || option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null;
  }

  function fetchLayoutMode(ins) {
    var layoutMode = ins.layoutMode || ins.constructor.layoutMode;
    return isObject(layoutMode) ? layoutMode : layoutMode ? {
      type: layoutMode
    } : null;
  }

  function mergeLayoutParam(targetOption, newOption, opt) {
    var ignoreSize = opt && opt.ignoreSize;
    !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);
    var hResult = merge(HV_NAMES[0], 0);
    var vResult = merge(HV_NAMES[1], 1);
    copy(HV_NAMES[0], targetOption, hResult);
    copy(HV_NAMES[1], targetOption, vResult);

    function merge(names, hvIdx) {
      var newParams = {};
      var newValueCount = 0;
      var merged = {};
      var mergedValueCount = 0;
      var enoughParamNumber = 2;
      each$1(names, function (name) {
        merged[name] = targetOption[name];
      });
      each$1(names, function (name) {
        hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
        hasValue(newParams, name) && newValueCount++;
        hasValue(merged, name) && mergedValueCount++;
      });

      if (ignoreSize[hvIdx]) {
        if (hasValue(newOption, names[1])) {
          merged[names[2]] = null;
        } else if (hasValue(newOption, names[2])) {
          merged[names[1]] = null;
        }

        return merged;
      }

      if (mergedValueCount === enoughParamNumber || !newValueCount) {
        return merged;
      } else if (newValueCount >= enoughParamNumber) {
        return newParams;
      } else {
        for (var i = 0; i < names.length; i++) {
          var name_1 = names[i];

          if (!hasProp(newParams, name_1) && hasProp(targetOption, name_1)) {
            newParams[name_1] = targetOption[name_1];
            break;
          }
        }

        return newParams;
      }
    }

    function hasProp(obj, name) {
      return obj.hasOwnProperty(name);
    }

    function hasValue(obj, name) {
      return obj[name] != null && obj[name] !== 'auto';
    }

    function copy(names, target, source) {
      each$1(names, function (name) {
        target[name] = source[name];
      });
    }
  }

  function getLayoutParams(source) {
    return copyLayoutParams({}, source);
  }

  function copyLayoutParams(target, source) {
    source && target && each$1(LOCATION_PARAMS, function (name) {
      source.hasOwnProperty(name) && (target[name] = source[name]);
    });
    return target;
  }

  var inner = makeInner();

  var ComponentModel = function (_super) {
    __extends(ComponentModel, _super);

    function ComponentModel(option, parentModel, ecModel) {
      var _this = _super.call(this, option, parentModel, ecModel) || this;

      _this.uid = getUID('ec_cpt_model');
      return _this;
    }

    ComponentModel.prototype.init = function (option, parentModel, ecModel) {
      this.mergeDefaultAndTheme(option, ecModel);
    };

    ComponentModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
      var layoutMode = fetchLayoutMode(this);
      var inputPositionParams = layoutMode ? getLayoutParams(option) : {};
      var themeModel = ecModel.getTheme();
      merge(option, themeModel.get(this.mainType));
      merge(option, this.getDefaultOption());

      if (layoutMode) {
        mergeLayoutParam(option, inputPositionParams, layoutMode);
      }
    };

    ComponentModel.prototype.mergeOption = function (option, ecModel) {
      merge(this.option, option, true);
      var layoutMode = fetchLayoutMode(this);

      if (layoutMode) {
        mergeLayoutParam(this.option, option, layoutMode);
      }
    };

    ComponentModel.prototype.optionUpdated = function (newCptOption, isInit) {};

    ComponentModel.prototype.getDefaultOption = function () {
      var ctor = this.constructor;

      if (!isExtendedClass(ctor)) {
        return ctor.defaultOption;
      }

      var fields = inner(this);

      if (!fields.defaultOption) {
        var optList = [];
        var clz = ctor;

        while (clz) {
          var opt = clz.prototype.defaultOption;
          opt && optList.push(opt);
          clz = clz.superClass;
        }

        var defaultOption = {};

        for (var i = optList.length - 1; i >= 0; i--) {
          defaultOption = merge(defaultOption, optList[i], true);
        }

        fields.defaultOption = defaultOption;
      }

      return fields.defaultOption;
    };

    ComponentModel.prototype.getReferringComponents = function (mainType, opt) {
      var indexKey = mainType + 'Index';
      var idKey = mainType + 'Id';
      return queryReferringComponents(this.ecModel, mainType, {
        index: this.get(indexKey, true),
        id: this.get(idKey, true)
      }, opt);
    };

    ComponentModel.prototype.getBoxLayoutParams = function () {
      var boxLayoutModel = this;
      return {
        left: boxLayoutModel.get('left'),
        top: boxLayoutModel.get('top'),
        right: boxLayoutModel.get('right'),
        bottom: boxLayoutModel.get('bottom'),
        width: boxLayoutModel.get('width'),
        height: boxLayoutModel.get('height')
      };
    };

    ComponentModel.protoInitialize = function () {
      var proto = ComponentModel.prototype;
      proto.type = 'component';
      proto.id = '';
      proto.name = '';
      proto.mainType = '';
      proto.subType = '';
      proto.componentIndex = 0;
    }();

    return ComponentModel;
  }(Model);

  mountExtend(ComponentModel, Model);
  enableClassManagement(ComponentModel, {
    registerWhenExtend: true
  });
  enableSubTypeDefaulter(ComponentModel);
  enableTopologicalTravel(ComponentModel, getDependencies);

  function getDependencies(componentType) {
    var deps = [];
    each(ComponentModel.getClassesByMainType(componentType), function (clz) {
      deps = deps.concat(clz.dependencies || clz.prototype.dependencies || []);
    });
    deps = map(deps, function (type) {
      return parseClassType(type).main;
    });

    if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) {
      deps.unshift('dataset');
    }

    return deps;
  }

  var platform = '';

  if (typeof navigator !== 'undefined') {
    platform = navigator.platform || '';
  }

  var decalColor = 'rgba(0, 0, 0, 0.2)';
  var globalDefault = {
    darkMode: 'auto',
    color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
    gradientColor: ['#f6efa6', '#d88273', '#bf444c'],
    aria: {
      decal: {
        decals: [{
          color: decalColor,
          dashArrayX: [1, 0],
          dashArrayY: [2, 5],
          symbolSize: 1,
          rotation: Math.PI / 6
        }, {
          color: decalColor,
          symbol: 'circle',
          dashArrayX: [[8, 8], [0, 8, 8, 0]],
          dashArrayY: [6, 0],
          symbolSize: 0.8
        }, {
          color: decalColor,
          dashArrayX: [1, 0],
          dashArrayY: [4, 3],
          dashLineOffset: 0,
          rotation: -Math.PI / 4
        }, {
          color: decalColor,
          dashArrayX: [[6, 6], [0, 6, 6, 0]],
          dashArrayY: [6, 0]
        }, {
          color: decalColor,
          dashArrayX: [[1, 0], [1, 6]],
          dashArrayY: [1, 0, 6, 0],
          rotation: Math.PI / 4
        }, {
          color: decalColor,
          symbol: 'triangle',
          dashArrayX: [[9, 9], [0, 9, 9, 0]],
          dashArrayY: [7, 2],
          symbolSize: 0.75
        }]
      }
    },
    textStyle: {
      fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
      fontSize: 12,
      fontStyle: 'normal',
      fontWeight: 'normal'
    },
    blendMode: null,
    stateAnimation: {
      duration: 300,
      easing: 'cubicOut'
    },
    animation: 'auto',
    animationDuration: 1000,
    animationDurationUpdate: 500,
    animationEasing: 'cubicInOut',
    animationEasingUpdate: 'cubicInOut',
    animationThreshold: 2000,
    progressiveThreshold: 3000,
    progressive: 400,
    hoverLayerThreshold: 3000,
    useUTC: false
  };
  var VISUAL_DIMENSIONS = createHashMap(['tooltip', 'label', 'itemName', 'itemId', 'seriesName']);
  var SOURCE_FORMAT_ORIGINAL = 'original';
  var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows';
  var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows';
  var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns';
  var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray';
  var SOURCE_FORMAT_UNKNOWN = 'unknown';
  var SERIES_LAYOUT_BY_COLUMN = 'column';
  var SERIES_LAYOUT_BY_ROW = 'row';
  var BE_ORDINAL = {
    Must: 1,
    Might: 2,
    Not: 3
  };
  var innerGlobalModel = makeInner();

  function resetSourceDefaulter(ecModel) {
    innerGlobalModel(ecModel).datasetMap = createHashMap();
  }

  function inheritSourceMetaRawOption(upstream, newMetaRawOption) {
    var parentMetaRawOption = upstream ? upstream.metaRawOption : null;
    var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, parentMetaRawOption ? parentMetaRawOption.seriesLayoutBy : null);
    var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upstream ? upstream.startIndex : null);
    var dimensions = retrieve2(newMetaRawOption.dimensions, upstream ? upstream.dimensionsDefine : null);
    return {
      seriesLayoutBy: seriesLayoutBy,
      sourceHeader: sourceHeader,
      dimensions: dimensions
    };
  }

  function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) {
    var encode = {};
    var datasetModel = querySeriesUpstreamDatasetModel(seriesModel);

    if (!datasetModel || !coordDimensions) {
      return encode;
    }

    var encodeItemName = [];
    var encodeSeriesName = [];
    var ecModel = seriesModel.ecModel;
    var datasetMap = innerGlobalModel(ecModel).datasetMap;
    var key = datasetModel.uid + '_' + source.seriesLayoutBy;
    var baseCategoryDimIndex;
    var categoryWayValueDimStart;
    coordDimensions = coordDimensions.slice();
    each(coordDimensions, function (coordDimInfoLoose, coordDimIdx) {
      var coordDimInfo = isObject(coordDimInfoLoose) ? coordDimInfoLoose : coordDimensions[coordDimIdx] = {
        name: coordDimInfoLoose
      };

      if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) {
        baseCategoryDimIndex = coordDimIdx;
        categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo);
      }

      encode[coordDimInfo.name] = [];
    });
    var datasetRecord = datasetMap.get(key) || datasetMap.set(key, {
      categoryWayDim: categoryWayValueDimStart,
      valueWayDim: 0
    });
    each(coordDimensions, function (coordDimInfo, coordDimIdx) {
      var coordDimName = coordDimInfo.name;
      var count = getDataDimCountOnCoordDim(coordDimInfo);

      if (baseCategoryDimIndex == null) {
        var start = datasetRecord.valueWayDim;
        pushDim(encode[coordDimName], start, count);
        pushDim(encodeSeriesName, start, count);
        datasetRecord.valueWayDim += count;
      } else if (baseCategoryDimIndex === coordDimIdx) {
        pushDim(encode[coordDimName], 0, count);
        pushDim(encodeItemName, 0, count);
      } else {
        var start = datasetRecord.categoryWayDim;
        pushDim(encode[coordDimName], start, count);
        pushDim(encodeSeriesName, start, count);
        datasetRecord.categoryWayDim += count;
      }
    });

    function pushDim(dimIdxArr, idxFrom, idxCount) {
      for (var i = 0; i < idxCount; i++) {
        dimIdxArr.push(idxFrom + i);
      }
    }

    function getDataDimCountOnCoordDim(coordDimInfo) {
      var dimsDef = coordDimInfo.dimsDef;
      return dimsDef ? dimsDef.length : 1;
    }

    encodeItemName.length && (encode.itemName = encodeItemName);
    encodeSeriesName.length && (encode.seriesName = encodeSeriesName);
    return encode;
  }

  function makeSeriesEncodeForNameBased(seriesModel, source, dimCount) {
    var encode = {};
    var datasetModel = querySeriesUpstreamDatasetModel(seriesModel);

    if (!datasetModel) {
      return encode;
    }

    var sourceFormat = source.sourceFormat;
    var dimensionsDefine = source.dimensionsDefine;
    var potentialNameDimIndex;

    if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
      each(dimensionsDefine, function (dim, idx) {
        if ((isObject(dim) ? dim.name : dim) === 'name') {
          potentialNameDimIndex = idx;
        }
      });
    }

    var idxResult = function () {
      var idxRes0 = {};
      var idxRes1 = {};
      var guessRecords = [];

      for (var i = 0, len = Math.min(5, dimCount); i < len; i++) {
        var guessResult = doGuessOrdinal(source.data, sourceFormat, source.seriesLayoutBy, dimensionsDefine, source.startIndex, i);
        guessRecords.push(guessResult);
        var isPureNumber = guessResult === BE_ORDINAL.Not;

        if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) {
          idxRes0.v = i;
        }

        if (idxRes0.n == null || idxRes0.n === idxRes0.v || !isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not) {
          idxRes0.n = i;
        }

        if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) {
          return idxRes0;
        }

        if (!isPureNumber) {
          if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) {
            idxRes1.v = i;
          }

          if (idxRes1.n == null || idxRes1.n === idxRes1.v) {
            idxRes1.n = i;
          }
        }
      }

      function fulfilled(idxResult) {
        return idxResult.v != null && idxResult.n != null;
      }

      return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null;
    }();

    if (idxResult) {
      encode.value = [idxResult.v];
      var nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n;
      encode.itemName = [nameDimIndex];
      encode.seriesName = [nameDimIndex];
    }

    return encode;
  }

  function querySeriesUpstreamDatasetModel(seriesModel) {
    var thisData = seriesModel.get('data', true);

    if (!thisData) {
      return queryReferringComponents(seriesModel.ecModel, 'dataset', {
        index: seriesModel.get('datasetIndex', true),
        id: seriesModel.get('datasetId', true)
      }, SINGLE_REFERRING).models[0];
    }
  }

  function queryDatasetUpstreamDatasetModels(datasetModel) {
    if (!datasetModel.get('transform', true) && !datasetModel.get('fromTransformResult', true)) {
      return [];
    }

    return queryReferringComponents(datasetModel.ecModel, 'dataset', {
      index: datasetModel.get('fromDatasetIndex', true),
      id: datasetModel.get('fromDatasetId', true)
    }, SINGLE_REFERRING).models;
  }

  function guessOrdinal(source, dimIndex) {
    return doGuessOrdinal(source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex);
  }

  function doGuessOrdinal(data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex) {
    var result;
    var maxLoop = 5;

    if (isTypedArray(data)) {
      return BE_ORDINAL.Not;
    }

    var dimName;
    var dimType;

    if (dimensionsDefine) {
      var dimDefItem = dimensionsDefine[dimIndex];

      if (isObject(dimDefItem)) {
        dimName = dimDefItem.name;
        dimType = dimDefItem.type;
      } else if (isString(dimDefItem)) {
        dimName = dimDefItem;
      }
    }

    if (dimType != null) {
      return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not;
    }

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
      var dataArrayRows = data;

      if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
        var sample = dataArrayRows[dimIndex];

        for (var i = 0; i < (sample || []).length && i < maxLoop; i++) {
          if ((result = detectValue(sample[startIndex + i])) != null) {
            return result;
          }
        }
      } else {
        for (var i = 0; i < dataArrayRows.length && i < maxLoop; i++) {
          var row = dataArrayRows[startIndex + i];

          if (row && (result = detectValue(row[dimIndex])) != null) {
            return result;
          }
        }
      }
    } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
      var dataObjectRows = data;

      if (!dimName) {
        return BE_ORDINAL.Not;
      }

      for (var i = 0; i < dataObjectRows.length && i < maxLoop; i++) {
        var item = dataObjectRows[i];

        if (item && (result = detectValue(item[dimName])) != null) {
          return result;
        }
      }
    } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
      var dataKeyedColumns = data;

      if (!dimName) {
        return BE_ORDINAL.Not;
      }

      var sample = dataKeyedColumns[dimName];

      if (!sample || isTypedArray(sample)) {
        return BE_ORDINAL.Not;
      }

      for (var i = 0; i < sample.length && i < maxLoop; i++) {
        if ((result = detectValue(sample[i])) != null) {
          return result;
        }
      }
    } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
      var dataOriginal = data;

      for (var i = 0; i < dataOriginal.length && i < maxLoop; i++) {
        var item = dataOriginal[i];
        var val = getDataItemValue(item);

        if (!isArray(val)) {
          return BE_ORDINAL.Not;
        }

        if ((result = detectValue(val[dimIndex])) != null) {
          return result;
        }
      }
    }

    function detectValue(val) {
      var beStr = isString(val);

      if (val != null && isFinite(val) && val !== '') {
        return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not;
      } else if (beStr && val !== '-') {
        return BE_ORDINAL.Must;
      }
    }

    return BE_ORDINAL.Not;
  }

  var internalOptionCreatorMap = createHashMap();

  function registerInternalOptionCreator(mainType, creator) {
    assert(internalOptionCreatorMap.get(mainType) == null && creator);
    internalOptionCreatorMap.set(mainType, creator);
  }

  function concatInternalOptions(ecModel, mainType, newCmptOptionList) {
    var internalOptionCreator = internalOptionCreatorMap.get(mainType);

    if (!internalOptionCreator) {
      return newCmptOptionList;
    }

    var internalOptions = internalOptionCreator(ecModel);

    if (!internalOptions) {
      return newCmptOptionList;
    }

    if (true) {
      for (var i = 0; i < internalOptions.length; i++) {
        assert(isComponentIdInternal(internalOptions[i]));
      }
    }

    return newCmptOptionList.concat(internalOptions);
  }

  var innerColor = makeInner();
  var innerDecal = makeInner();

  var PaletteMixin = function () {
    function PaletteMixin() {}

    PaletteMixin.prototype.getColorFromPalette = function (name, scope, requestNum) {
      var defaultPalette = normalizeToArray(this.get('color', true));
      var layeredPalette = this.get('colorLayer', true);
      return getFromPalette(this, innerColor, defaultPalette, layeredPalette, name, scope, requestNum);
    };

    PaletteMixin.prototype.clearColorPalette = function () {
      clearPalette(this, innerColor);
    };

    return PaletteMixin;
  }();

  function getDecalFromPalette(ecModel, name, scope, requestNum) {
    var defaultDecals = normalizeToArray(ecModel.get(['aria', 'decal', 'decals']));
    return getFromPalette(ecModel, innerDecal, defaultDecals, null, name, scope, requestNum);
  }

  function getNearestPalette(palettes, requestColorNum) {
    var paletteNum = palettes.length;

    for (var i = 0; i < paletteNum; i++) {
      if (palettes[i].length > requestColorNum) {
        return palettes[i];
      }
    }

    return palettes[paletteNum - 1];
  }

  function getFromPalette(that, inner, defaultPalette, layeredPalette, name, scope, requestNum) {
    scope = scope || that;
    var scopeFields = inner(scope);
    var paletteIdx = scopeFields.paletteIdx || 0;
    var paletteNameMap = scopeFields.paletteNameMap = scopeFields.paletteNameMap || {};

    if (paletteNameMap.hasOwnProperty(name)) {
      return paletteNameMap[name];
    }

    var palette = requestNum == null || !layeredPalette ? defaultPalette : getNearestPalette(layeredPalette, requestNum);
    palette = palette || defaultPalette;

    if (!palette || !palette.length) {
      return;
    }

    var pickedPaletteItem = palette[paletteIdx];

    if (name) {
      paletteNameMap[name] = pickedPaletteItem;
    }

    scopeFields.paletteIdx = (paletteIdx + 1) % palette.length;
    return pickedPaletteItem;
  }

  function clearPalette(that, inner) {
    inner(that).paletteIdx = 0;
    inner(that).paletteNameMap = {};
  }

  var reCreateSeriesIndices;
  var assertSeriesInitialized;
  var initBase;
  var OPTION_INNER_KEY = '\0_ec_inner';

  var GlobalModel = function (_super) {
    __extends(GlobalModel, _super);

    function GlobalModel() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) {
      theme = theme || {};
      this.option = null;
      this._theme = new Model(theme);
      this._locale = new Model(locale);
      this._optionManager = optionManager;
    };

    GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) {
      assert(!(OPTION_INNER_KEY in option), 'please use chart.getOption()');
      var innerOpt = normalizeSetOptionInput(opts);

      this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt);

      this._resetOption(null, innerOpt);
    };

    GlobalModel.prototype.resetOption = function (type, opt) {
      return this._resetOption(type, normalizeSetOptionInput(opt));
    };

    GlobalModel.prototype._resetOption = function (type, opt) {
      var optionChanged = false;
      var optionManager = this._optionManager;

      if (!type || type === 'recreate') {
        var baseOption = optionManager.mountOption(type === 'recreate');

        if (!this.option || type === 'recreate') {
          initBase(this, baseOption);
        } else {
          this.restoreData();

          this._mergeOption(baseOption, opt);
        }

        optionChanged = true;
      }

      if (type === 'timeline' || type === 'media') {
        this.restoreData();
      }

      if (!type || type === 'recreate' || type === 'timeline') {
        var timelineOption = optionManager.getTimelineOption(this);

        if (timelineOption) {
          optionChanged = true;

          this._mergeOption(timelineOption, opt);
        }
      }

      if (!type || type === 'recreate' || type === 'media') {
        var mediaOptions = optionManager.getMediaOption(this);

        if (mediaOptions.length) {
          each(mediaOptions, function (mediaOption) {
            optionChanged = true;

            this._mergeOption(mediaOption, opt);
          }, this);
        }
      }

      return optionChanged;
    };

    GlobalModel.prototype.mergeOption = function (option) {
      this._mergeOption(option, null);
    };

    GlobalModel.prototype._mergeOption = function (newOption, opt) {
      var option = this.option;
      var componentsMap = this._componentsMap;
      var componentsCount = this._componentsCount;
      var newCmptTypes = [];
      var newCmptTypeMap = createHashMap();
      var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap;
      resetSourceDefaulter(this);
      each(newOption, function (componentOption, mainType) {
        if (componentOption == null) {
          return;
        }

        if (!ComponentModel.hasClass(mainType)) {
          option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true);
        } else if (mainType) {
          newCmptTypes.push(mainType);
          newCmptTypeMap.set(mainType, true);
        }
      });

      if (replaceMergeMainTypeMap) {
        replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) {
          if (ComponentModel.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) {
            newCmptTypes.push(mainTypeInReplaceMerge);
            newCmptTypeMap.set(mainTypeInReplaceMerge, true);
          }
        });
      }

      ComponentModel.topologicalTravel(newCmptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this);

      function visitComponent(mainType) {
        var newCmptOptionList = concatInternalOptions(this, mainType, normalizeToArray(newOption[mainType]));
        var oldCmptList = componentsMap.get(mainType);
        var mergeMode = !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge';
        var mappingResult = mappingToExists(oldCmptList, newCmptOptionList, mergeMode);
        setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel);
        option[mainType] = null;
        componentsMap.set(mainType, null);
        componentsCount.set(mainType, 0);
        var optionsByMainType = [];
        var cmptsByMainType = [];
        var cmptsCountByMainType = 0;
        each(mappingResult, function (resultItem, index) {
          var componentModel = resultItem.existing;
          var newCmptOption = resultItem.newOption;

          if (!newCmptOption) {
            if (componentModel) {
              componentModel.mergeOption({}, this);
              componentModel.optionUpdated({}, false);
            }
          } else {
            var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, true);

            if (componentModel && componentModel.constructor === ComponentModelClass) {
              componentModel.name = resultItem.keyInfo.name;
              componentModel.mergeOption(newCmptOption, this);
              componentModel.optionUpdated(newCmptOption, false);
            } else {
              var extraOpt = extend({
                componentIndex: index
              }, resultItem.keyInfo);
              componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt);
              extend(componentModel, extraOpt);

              if (resultItem.brandNew) {
                componentModel.__requireNewView = true;
              }

              componentModel.init(newCmptOption, this, this);
              componentModel.optionUpdated(null, true);
            }
          }

          if (componentModel) {
            optionsByMainType.push(componentModel.option);
            cmptsByMainType.push(componentModel);
            cmptsCountByMainType++;
          } else {
            optionsByMainType.push(void 0);
            cmptsByMainType.push(void 0);
          }
        }, this);
        option[mainType] = optionsByMainType;
        componentsMap.set(mainType, cmptsByMainType);
        componentsCount.set(mainType, cmptsCountByMainType);

        if (mainType === 'series') {
          reCreateSeriesIndices(this);
        }
      }

      if (!this._seriesIndices) {
        reCreateSeriesIndices(this);
      }
    };

    GlobalModel.prototype.getOption = function () {
      var option = clone(this.option);
      each(option, function (optInMainType, mainType) {
        if (ComponentModel.hasClass(mainType)) {
          var opts = normalizeToArray(optInMainType);
          var realLen = opts.length;
          var metNonInner = false;

          for (var i = realLen - 1; i >= 0; i--) {
            if (opts[i] && !isComponentIdInternal(opts[i])) {
              metNonInner = true;
            } else {
              opts[i] = null;
              !metNonInner && realLen--;
            }
          }

          opts.length = realLen;
          option[mainType] = opts;
        }
      });
      delete option[OPTION_INNER_KEY];
      return option;
    };

    GlobalModel.prototype.getTheme = function () {
      return this._theme;
    };

    GlobalModel.prototype.getLocaleModel = function () {
      return this._locale;
    };

    GlobalModel.prototype.getLocale = function (localePosition) {
      var locale = this.getLocaleModel();
      return locale.get(localePosition);
    };

    GlobalModel.prototype.setUpdatePayload = function (payload) {
      this._payload = payload;
    };

    GlobalModel.prototype.getUpdatePayload = function () {
      return this._payload;
    };

    GlobalModel.prototype.getComponent = function (mainType, idx) {
      var list = this._componentsMap.get(mainType);

      if (list) {
        var cmpt = list[idx || 0];

        if (cmpt) {
          return cmpt;
        } else if (idx == null) {
          for (var i = 0; i < list.length; i++) {
            if (list[i]) {
              return list[i];
            }
          }
        }
      }
    };

    GlobalModel.prototype.queryComponents = function (condition) {
      var mainType = condition.mainType;

      if (!mainType) {
        return [];
      }

      var index = condition.index;
      var id = condition.id;
      var name = condition.name;

      var cmpts = this._componentsMap.get(mainType);

      if (!cmpts || !cmpts.length) {
        return [];
      }

      var result;

      if (index != null) {
        result = [];
        each(normalizeToArray(index), function (idx) {
          cmpts[idx] && result.push(cmpts[idx]);
        });
      } else if (id != null) {
        result = queryByIdOrName('id', id, cmpts);
      } else if (name != null) {
        result = queryByIdOrName('name', name, cmpts);
      } else {
        result = filter(cmpts, function (cmpt) {
          return !!cmpt;
        });
      }

      return filterBySubType(result, condition);
    };

    GlobalModel.prototype.findComponents = function (condition) {
      var query = condition.query;
      var mainType = condition.mainType;
      var queryCond = getQueryCond(query);
      var result = queryCond ? this.queryComponents(queryCond) : filter(this._componentsMap.get(mainType), function (cmpt) {
        return !!cmpt;
      });
      return doFilter(filterBySubType(result, condition));

      function getQueryCond(q) {
        var indexAttr = mainType + 'Index';
        var idAttr = mainType + 'Id';
        var nameAttr = mainType + 'Name';
        return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? {
          mainType: mainType,
          index: q[indexAttr],
          id: q[idAttr],
          name: q[nameAttr]
        } : null;
      }

      function doFilter(res) {
        return condition.filter ? filter(res, condition.filter) : res;
      }
    };

    GlobalModel.prototype.eachComponent = function (mainType, cb, context) {
      var componentsMap = this._componentsMap;

      if (isFunction(mainType)) {
        var ctxForAll_1 = cb;
        var cbForAll_1 = mainType;
        componentsMap.each(function (cmpts, componentType) {
          for (var i = 0; cmpts && i < cmpts.length; i++) {
            var cmpt = cmpts[i];
            cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex);
          }
        });
      } else {
        var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject(mainType) ? this.findComponents(mainType) : null;

        for (var i = 0; cmpts && i < cmpts.length; i++) {
          var cmpt = cmpts[i];
          cmpt && cb.call(context, cmpt, cmpt.componentIndex);
        }
      }
    };

    GlobalModel.prototype.getSeriesByName = function (name) {
      var nameStr = convertOptionIdName(name, null);
      return filter(this._componentsMap.get('series'), function (oneSeries) {
        return !!oneSeries && nameStr != null && oneSeries.name === nameStr;
      });
    };

    GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) {
      return this._componentsMap.get('series')[seriesIndex];
    };

    GlobalModel.prototype.getSeriesByType = function (subType) {
      return filter(this._componentsMap.get('series'), function (oneSeries) {
        return !!oneSeries && oneSeries.subType === subType;
      });
    };

    GlobalModel.prototype.getSeries = function () {
      return filter(this._componentsMap.get('series').slice(), function (oneSeries) {
        return !!oneSeries;
      });
    };

    GlobalModel.prototype.getSeriesCount = function () {
      return this._componentsCount.get('series');
    };

    GlobalModel.prototype.eachSeries = function (cb, context) {
      assertSeriesInitialized(this);
      each(this._seriesIndices, function (rawSeriesIndex) {
        var series = this._componentsMap.get('series')[rawSeriesIndex];

        cb.call(context, series, rawSeriesIndex);
      }, this);
    };

    GlobalModel.prototype.eachRawSeries = function (cb, context) {
      each(this._componentsMap.get('series'), function (series) {
        series && cb.call(context, series, series.componentIndex);
      });
    };

    GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) {
      assertSeriesInitialized(this);
      each(this._seriesIndices, function (rawSeriesIndex) {
        var series = this._componentsMap.get('series')[rawSeriesIndex];

        if (series.subType === subType) {
          cb.call(context, series, rawSeriesIndex);
        }
      }, this);
    };

    GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) {
      return each(this.getSeriesByType(subType), cb, context);
    };

    GlobalModel.prototype.isSeriesFiltered = function (seriesModel) {
      assertSeriesInitialized(this);
      return this._seriesIndicesMap.get(seriesModel.componentIndex) == null;
    };

    GlobalModel.prototype.getCurrentSeriesIndices = function () {
      return (this._seriesIndices || []).slice();
    };

    GlobalModel.prototype.filterSeries = function (cb, context) {
      assertSeriesInitialized(this);
      var newSeriesIndices = [];
      each(this._seriesIndices, function (seriesRawIdx) {
        var series = this._componentsMap.get('series')[seriesRawIdx];

        cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx);
      }, this);
      this._seriesIndices = newSeriesIndices;
      this._seriesIndicesMap = createHashMap(newSeriesIndices);
    };

    GlobalModel.prototype.restoreData = function (payload) {
      reCreateSeriesIndices(this);
      var componentsMap = this._componentsMap;
      var componentTypes = [];
      componentsMap.each(function (components, componentType) {
        if (ComponentModel.hasClass(componentType)) {
          componentTypes.push(componentType);
        }
      });
      ComponentModel.topologicalTravel(componentTypes, ComponentModel.getAllClassMainTypes(), function (componentType) {
        each(componentsMap.get(componentType), function (component) {
          if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) {
            component.restoreData();
          }
        });
      });
    };

    GlobalModel.internalField = function () {
      reCreateSeriesIndices = function (ecModel) {
        var seriesIndices = ecModel._seriesIndices = [];
        each(ecModel._componentsMap.get('series'), function (series) {
          series && seriesIndices.push(series.componentIndex);
        });
        ecModel._seriesIndicesMap = createHashMap(seriesIndices);
      };

      assertSeriesInitialized = function (ecModel) {
        if (true) {
          if (!ecModel._seriesIndices) {
            throw new Error('Option should contains series.');
          }
        }
      };

      initBase = function (ecModel, baseOption) {
        ecModel.option = {};
        ecModel.option[OPTION_INNER_KEY] = 1;
        ecModel._componentsMap = createHashMap({
          series: []
        });
        ecModel._componentsCount = createHashMap();
        var airaOption = baseOption.aria;

        if (isObject(airaOption) && airaOption.enabled == null) {
          airaOption.enabled = true;
        }

        mergeTheme(baseOption, ecModel._theme.option);
        merge(baseOption, globalDefault, false);

        ecModel._mergeOption(baseOption, null);
      };
    }();

    return GlobalModel;
  }(Model);

  function isNotTargetSeries(seriesModel, payload) {
    if (payload) {
      var index = payload.seriesIndex;
      var id = payload.seriesId;
      var name_1 = payload.seriesName;
      return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1;
    }
  }

  function mergeTheme(option, theme) {
    var notMergeColorLayer = option.color && !option.colorLayer;
    each(theme, function (themeItem, name) {
      if (name === 'colorLayer' && notMergeColorLayer) {
        return;
      }

      if (!ComponentModel.hasClass(name)) {
        if (typeof themeItem === 'object') {
          option[name] = !option[name] ? clone(themeItem) : merge(option[name], themeItem, false);
        } else {
          if (option[name] == null) {
            option[name] = themeItem;
          }
        }
      }
    });
  }

  function queryByIdOrName(attr, idOrName, cmpts) {
    if (isArray(idOrName)) {
      var keyMap_1 = createHashMap();
      each(idOrName, function (idOrNameItem) {
        if (idOrNameItem != null) {
          var idName = convertOptionIdName(idOrNameItem, null);
          idName != null && keyMap_1.set(idOrNameItem, true);
        }
      });
      return filter(cmpts, function (cmpt) {
        return cmpt && keyMap_1.get(cmpt[attr]);
      });
    } else {
      var idName_1 = convertOptionIdName(idOrName, null);
      return filter(cmpts, function (cmpt) {
        return cmpt && idName_1 != null && cmpt[attr] === idName_1;
      });
    }
  }

  function filterBySubType(components, condition) {
    return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) {
      return cmpt && cmpt.subType === condition.subType;
    }) : components;
  }

  function normalizeSetOptionInput(opts) {
    var replaceMergeMainTypeMap = createHashMap();
    opts && each(normalizeToArray(opts.replaceMerge), function (mainType) {
      if (true) {
        assert(ComponentModel.hasClass(mainType), '"' + mainType + '" is not valid component main type in "replaceMerge"');
      }

      replaceMergeMainTypeMap.set(mainType, true);
    });
    return {
      replaceMergeMainTypeMap: replaceMergeMainTypeMap
    };
  }

  mixin(GlobalModel, PaletteMixin);
  var availableMethods = ['getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getOption', 'getId', 'updateLabelLayout'];

  var ExtensionAPI = function () {
    function ExtensionAPI(ecInstance) {
      each(availableMethods, function (methodName) {
        this[methodName] = bind(ecInstance[methodName], ecInstance);
      }, this);
    }

    return ExtensionAPI;
  }();

  var coordinateSystemCreators = {};

  var CoordinateSystemManager = function () {
    function CoordinateSystemManager() {
      this._coordinateSystems = [];
    }

    CoordinateSystemManager.prototype.create = function (ecModel, api) {
      var coordinateSystems = [];
      each(coordinateSystemCreators, function (creater, type) {
        var list = creater.create(ecModel, api);
        coordinateSystems = coordinateSystems.concat(list || []);
      });
      this._coordinateSystems = coordinateSystems;
    };

    CoordinateSystemManager.prototype.update = function (ecModel, api) {
      each(this._coordinateSystems, function (coordSys) {
        coordSys.update && coordSys.update(ecModel, api);
      });
    };

    CoordinateSystemManager.prototype.getCoordinateSystems = function () {
      return this._coordinateSystems.slice();
    };

    CoordinateSystemManager.register = function (type, creator) {
      coordinateSystemCreators[type] = creator;
    };

    CoordinateSystemManager.get = function (type) {
      return coordinateSystemCreators[type];
    };

    return CoordinateSystemManager;
  }();

  var QUERY_REG = /^(min|max)?(.+)$/;

  var OptionManager = function () {
    function OptionManager(api) {
      this._timelineOptions = [];
      this._mediaList = [];
      this._currentMediaIndices = [];
      this._api = api;
    }

    OptionManager.prototype.setOption = function (rawOption, optionPreprocessorFuncs, opt) {
      if (rawOption) {
        each(normalizeToArray(rawOption.series), function (series) {
          series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data);
        });
        each(normalizeToArray(rawOption.dataset), function (dataset) {
          dataset && dataset.source && isTypedArray(dataset.source) && setAsPrimitive(dataset.source);
        });
      }

      rawOption = clone(rawOption);
      var optionBackup = this._optionBackup;
      var newParsedOption = parseRawOption(rawOption, optionPreprocessorFuncs, !optionBackup);
      this._newBaseOption = newParsedOption.baseOption;

      if (optionBackup) {
        if (newParsedOption.timelineOptions.length) {
          optionBackup.timelineOptions = newParsedOption.timelineOptions;
        }

        if (newParsedOption.mediaList.length) {
          optionBackup.mediaList = newParsedOption.mediaList;
        }

        if (newParsedOption.mediaDefault) {
          optionBackup.mediaDefault = newParsedOption.mediaDefault;
        }
      } else {
        this._optionBackup = newParsedOption;
      }
    };

    OptionManager.prototype.mountOption = function (isRecreate) {
      var optionBackup = this._optionBackup;
      this._timelineOptions = optionBackup.timelineOptions;
      this._mediaList = optionBackup.mediaList;
      this._mediaDefault = optionBackup.mediaDefault;
      this._currentMediaIndices = [];
      return clone(isRecreate ? optionBackup.baseOption : this._newBaseOption);
    };

    OptionManager.prototype.getTimelineOption = function (ecModel) {
      var option;
      var timelineOptions = this._timelineOptions;

      if (timelineOptions.length) {
        var timelineModel = ecModel.getComponent('timeline');

        if (timelineModel) {
          option = clone(timelineOptions[timelineModel.getCurrentIndex()]);
        }
      }

      return option;
    };

    OptionManager.prototype.getMediaOption = function (ecModel) {
      var ecWidth = this._api.getWidth();

      var ecHeight = this._api.getHeight();

      var mediaList = this._mediaList;
      var mediaDefault = this._mediaDefault;
      var indices = [];
      var result = [];

      if (!mediaList.length && !mediaDefault) {
        return result;
      }

      for (var i = 0, len = mediaList.length; i < len; i++) {
        if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) {
          indices.push(i);
        }
      }

      if (!indices.length && mediaDefault) {
        indices = [-1];
      }

      if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) {
        result = map(indices, function (index) {
          return clone(index === -1 ? mediaDefault.option : mediaList[index].option);
        });
      }

      this._currentMediaIndices = indices;
      return result;
    };

    return OptionManager;
  }();

  function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) {
    var mediaList = [];
    var mediaDefault;
    var baseOption;
    var declaredBaseOption = rawOption.baseOption;
    var timelineOnRoot = rawOption.timeline;
    var timelineOptionsOnRoot = rawOption.options;
    var mediaOnRoot = rawOption.media;
    var hasMedia = !!rawOption.media;
    var hasTimeline = !!(timelineOptionsOnRoot || timelineOnRoot || declaredBaseOption && declaredBaseOption.timeline);

    if (declaredBaseOption) {
      baseOption = declaredBaseOption;

      if (!baseOption.timeline) {
        baseOption.timeline = timelineOnRoot;
      }
    } else {
      if (hasTimeline || hasMedia) {
        rawOption.options = rawOption.media = null;
      }

      baseOption = rawOption;
    }

    if (hasMedia) {
      if (isArray(mediaOnRoot)) {
        each(mediaOnRoot, function (singleMedia) {
          if (true) {
            if (singleMedia && !singleMedia.option && isObject(singleMedia.query) && isObject(singleMedia.query.option)) {
              error('Illegal media option. Must be like { media: [ { query: {}, option: {} } ] }');
            }
          }

          if (singleMedia && singleMedia.option) {
            if (singleMedia.query) {
              mediaList.push(singleMedia);
            } else if (!mediaDefault) {
              mediaDefault = singleMedia;
            }
          }
        });
      } else {
        if (true) {
          error('Illegal media option. Must be an array. Like { media: [ {...}, {...} ] }');
        }
      }
    }

    doPreprocess(baseOption);
    each(timelineOptionsOnRoot, function (option) {
      return doPreprocess(option);
    });
    each(mediaList, function (media) {
      return doPreprocess(media.option);
    });

    function doPreprocess(option) {
      each(optionPreprocessorFuncs, function (preProcess) {
        preProcess(option, isNew);
      });
    }

    return {
      baseOption: baseOption,
      timelineOptions: timelineOptionsOnRoot || [],
      mediaDefault: mediaDefault,
      mediaList: mediaList
    };
  }

  function applyMediaQuery(query, ecWidth, ecHeight) {
    var realMap = {
      width: ecWidth,
      height: ecHeight,
      aspectratio: ecWidth / ecHeight
    };
    var applicatable = true;
    each(query, function (value, attr) {
      var matched = attr.match(QUERY_REG);

      if (!matched || !matched[1] || !matched[2]) {
        return;
      }

      var operator = matched[1];
      var realAttr = matched[2].toLowerCase();

      if (!compare(realMap[realAttr], value, operator)) {
        applicatable = false;
      }
    });
    return applicatable;
  }

  function compare(real, expect, operator) {
    if (operator === 'min') {
      return real >= expect;
    } else if (operator === 'max') {
      return real <= expect;
    } else {
      return real === expect;
    }
  }

  function indicesEquals(indices1, indices2) {
    return indices1.join(',') === indices2.join(',');
  }

  var each$2 = each;
  var isObject$1 = isObject;
  var POSSIBLE_STYLES = ['areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', 'chordStyle', 'label', 'labelLine'];

  function compatEC2ItemStyle(opt) {
    var itemStyleOpt = opt && opt.itemStyle;

    if (!itemStyleOpt) {
      return;
    }

    for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) {
      var styleName = POSSIBLE_STYLES[i];
      var normalItemStyleOpt = itemStyleOpt.normal;
      var emphasisItemStyleOpt = itemStyleOpt.emphasis;

      if (normalItemStyleOpt && normalItemStyleOpt[styleName]) {
        if (true) {
          deprecateReplaceLog("itemStyle.normal." + styleName, styleName);
        }

        opt[styleName] = opt[styleName] || {};

        if (!opt[styleName].normal) {
          opt[styleName].normal = normalItemStyleOpt[styleName];
        } else {
          merge(opt[styleName].normal, normalItemStyleOpt[styleName]);
        }

        normalItemStyleOpt[styleName] = null;
      }

      if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) {
        if (true) {
          deprecateReplaceLog("itemStyle.emphasis." + styleName, "emphasis." + styleName);
        }

        opt[styleName] = opt[styleName] || {};

        if (!opt[styleName].emphasis) {
          opt[styleName].emphasis = emphasisItemStyleOpt[styleName];
        } else {
          merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]);
        }

        emphasisItemStyleOpt[styleName] = null;
      }
    }
  }

  function convertNormalEmphasis(opt, optType, useExtend) {
    if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) {
      var normalOpt = opt[optType].normal;
      var emphasisOpt = opt[optType].emphasis;

      if (normalOpt) {
        if (true) {
          deprecateLog("'normal' hierarchy in " + optType + " has been removed since 4.0. All style properties are configured in " + optType + " directly now.");
        }

        if (useExtend) {
          opt[optType].normal = opt[optType].emphasis = null;
          defaults(opt[optType], normalOpt);
        } else {
          opt[optType] = normalOpt;
        }
      }

      if (emphasisOpt) {
        if (true) {
          deprecateLog(optType + ".emphasis has been changed to emphasis." + optType + " since 4.0");
        }

        opt.emphasis = opt.emphasis || {};
        opt.emphasis[optType] = emphasisOpt;

        if (emphasisOpt.focus) {
          opt.emphasis.focus = emphasisOpt.focus;
        }

        if (emphasisOpt.blurScope) {
          opt.emphasis.blurScope = emphasisOpt.blurScope;
        }
      }
    }
  }

  function removeEC3NormalStatus(opt) {
    convertNormalEmphasis(opt, 'itemStyle');
    convertNormalEmphasis(opt, 'lineStyle');
    convertNormalEmphasis(opt, 'areaStyle');
    convertNormalEmphasis(opt, 'label');
    convertNormalEmphasis(opt, 'labelLine');
    convertNormalEmphasis(opt, 'upperLabel');
    convertNormalEmphasis(opt, 'edgeLabel');
  }

  function compatTextStyle(opt, propName) {
    var labelOptSingle = isObject$1(opt) && opt[propName];
    var textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle;

    if (textStyle) {
      if (true) {
        deprecateLog("textStyle hierarchy in " + propName + " has been removed since 4.0. All textStyle properties are configured in " + propName + " directly now.");
      }

      for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) {
        var textPropName = TEXT_STYLE_OPTIONS[i];

        if (textStyle.hasOwnProperty(textPropName)) {
          labelOptSingle[textPropName] = textStyle[textPropName];
        }
      }
    }
  }

  function compatEC3CommonStyles(opt) {
    if (opt) {
      removeEC3NormalStatus(opt);
      compatTextStyle(opt, 'label');
      opt.emphasis && compatTextStyle(opt.emphasis, 'label');
    }
  }

  function processSeries(seriesOpt) {
    if (!isObject$1(seriesOpt)) {
      return;
    }

    compatEC2ItemStyle(seriesOpt);
    removeEC3NormalStatus(seriesOpt);
    compatTextStyle(seriesOpt, 'label');
    compatTextStyle(seriesOpt, 'upperLabel');
    compatTextStyle(seriesOpt, 'edgeLabel');

    if (seriesOpt.emphasis) {
      compatTextStyle(seriesOpt.emphasis, 'label');
      compatTextStyle(seriesOpt.emphasis, 'upperLabel');
      compatTextStyle(seriesOpt.emphasis, 'edgeLabel');
    }

    var markPoint = seriesOpt.markPoint;

    if (markPoint) {
      compatEC2ItemStyle(markPoint);
      compatEC3CommonStyles(markPoint);
    }

    var markLine = seriesOpt.markLine;

    if (markLine) {
      compatEC2ItemStyle(markLine);
      compatEC3CommonStyles(markLine);
    }

    var markArea = seriesOpt.markArea;

    if (markArea) {
      compatEC3CommonStyles(markArea);
    }

    var data = seriesOpt.data;

    if (seriesOpt.type === 'graph') {
      data = data || seriesOpt.nodes;
      var edgeData = seriesOpt.links || seriesOpt.edges;

      if (edgeData && !isTypedArray(edgeData)) {
        for (var i = 0; i < edgeData.length; i++) {
          compatEC3CommonStyles(edgeData[i]);
        }
      }

      each(seriesOpt.categories, function (opt) {
        removeEC3NormalStatus(opt);
      });
    }

    if (data && !isTypedArray(data)) {
      for (var i = 0; i < data.length; i++) {
        compatEC3CommonStyles(data[i]);
      }
    }

    markPoint = seriesOpt.markPoint;

    if (markPoint && markPoint.data) {
      var mpData = markPoint.data;

      for (var i = 0; i < mpData.length; i++) {
        compatEC3CommonStyles(mpData[i]);
      }
    }

    markLine = seriesOpt.markLine;

    if (markLine && markLine.data) {
      var mlData = markLine.data;

      for (var i = 0; i < mlData.length; i++) {
        if (isArray(mlData[i])) {
          compatEC3CommonStyles(mlData[i][0]);
          compatEC3CommonStyles(mlData[i][1]);
        } else {
          compatEC3CommonStyles(mlData[i]);
        }
      }
    }

    if (seriesOpt.type === 'gauge') {
      compatTextStyle(seriesOpt, 'axisLabel');
      compatTextStyle(seriesOpt, 'title');
      compatTextStyle(seriesOpt, 'detail');
    } else if (seriesOpt.type === 'treemap') {
      convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle');
      each(seriesOpt.levels, function (opt) {
        removeEC3NormalStatus(opt);
      });
    } else if (seriesOpt.type === 'tree') {
      removeEC3NormalStatus(seriesOpt.leaves);
    }
  }

  function toArr(o) {
    return isArray(o) ? o : o ? [o] : [];
  }

  function toObj(o) {
    return (isArray(o) ? o[0] : o) || {};
  }

  function globalCompatStyle(option, isTheme) {
    each$2(toArr(option.series), function (seriesOpt) {
      isObject$1(seriesOpt) && processSeries(seriesOpt);
    });
    var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar'];
    isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis');
    each$2(axes, function (axisName) {
      each$2(toArr(option[axisName]), function (axisOpt) {
        if (axisOpt) {
          compatTextStyle(axisOpt, 'axisLabel');
          compatTextStyle(axisOpt.axisPointer, 'label');
        }
      });
    });
    each$2(toArr(option.parallel), function (parallelOpt) {
      var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault;
      compatTextStyle(parallelAxisDefault, 'axisLabel');
      compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label');
    });
    each$2(toArr(option.calendar), function (calendarOpt) {
      convertNormalEmphasis(calendarOpt, 'itemStyle');
      compatTextStyle(calendarOpt, 'dayLabel');
      compatTextStyle(calendarOpt, 'monthLabel');
      compatTextStyle(calendarOpt, 'yearLabel');
    });
    each$2(toArr(option.radar), function (radarOpt) {
      compatTextStyle(radarOpt, 'name');

      if (radarOpt.name && radarOpt.axisName == null) {
        radarOpt.axisName = radarOpt.name;
        delete radarOpt.name;

        if (true) {
          deprecateLog('name property in radar component has been changed to axisName');
        }
      }

      if (radarOpt.nameGap != null && radarOpt.axisNameGap == null) {
        radarOpt.axisNameGap = radarOpt.nameGap;
        delete radarOpt.nameGap;

        if (true) {
          deprecateLog('nameGap property in radar component has been changed to axisNameGap');
        }
      }
    });
    each$2(toArr(option.geo), function (geoOpt) {
      if (isObject$1(geoOpt)) {
        compatEC3CommonStyles(geoOpt);
        each$2(toArr(geoOpt.regions), function (regionObj) {
          compatEC3CommonStyles(regionObj);
        });
      }
    });
    each$2(toArr(option.timeline), function (timelineOpt) {
      compatEC3CommonStyles(timelineOpt);
      convertNormalEmphasis(timelineOpt, 'label');
      convertNormalEmphasis(timelineOpt, 'itemStyle');
      convertNormalEmphasis(timelineOpt, 'controlStyle', true);
      var data = timelineOpt.data;
      isArray(data) && each(data, function (item) {
        if (isObject(item)) {
          convertNormalEmphasis(item, 'label');
          convertNormalEmphasis(item, 'itemStyle');
        }
      });
    });
    each$2(toArr(option.toolbox), function (toolboxOpt) {
      convertNormalEmphasis(toolboxOpt, 'iconStyle');
      each$2(toolboxOpt.feature, function (featureOpt) {
        convertNormalEmphasis(featureOpt, 'iconStyle');
      });
    });
    compatTextStyle(toObj(option.axisPointer), 'label');
    compatTextStyle(toObj(option.tooltip).axisPointer, 'label');
  }

  function get(opt, path) {
    var pathArr = path.split(',');
    var obj = opt;

    for (var i = 0; i < pathArr.length; i++) {
      obj = obj && obj[pathArr[i]];

      if (obj == null) {
        break;
      }
    }

    return obj;
  }

  function set$1(opt, path, val, overwrite) {
    var pathArr = path.split(',');
    var obj = opt;
    var key;
    var i = 0;

    for (; i < pathArr.length - 1; i++) {
      key = pathArr[i];

      if (obj[key] == null) {
        obj[key] = {};
      }

      obj = obj[key];
    }

    if (overwrite || obj[pathArr[i]] == null) {
      obj[pathArr[i]] = val;
    }
  }

  function compatLayoutProperties(option) {
    option && each(LAYOUT_PROPERTIES, function (prop) {
      if (prop[0] in option && !(prop[1] in option)) {
        option[prop[1]] = option[prop[0]];
      }
    });
  }

  var LAYOUT_PROPERTIES = [['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']];
  var COMPATITABLE_COMPONENTS = ['grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline'];
  var BAR_ITEM_STYLE_MAP = [['borderRadius', 'barBorderRadius'], ['borderColor', 'barBorderColor'], ['borderWidth', 'barBorderWidth']];

  function compatBarItemStyle(option) {
    var itemStyle = option && option.itemStyle;

    if (itemStyle) {
      for (var i = 0; i < BAR_ITEM_STYLE_MAP.length; i++) {
        var oldName = BAR_ITEM_STYLE_MAP[i][1];
        var newName = BAR_ITEM_STYLE_MAP[i][0];

        if (itemStyle[oldName] != null) {
          itemStyle[newName] = itemStyle[oldName];

          if (true) {
            deprecateReplaceLog(oldName, newName);
          }
        }
      }
    }
  }

  function compatPieLabel(option) {
    if (!option) {
      return;
    }

    if (option.alignTo === 'edge' && option.margin != null && option.edgeDistance == null) {
      if (true) {
        deprecateReplaceLog('label.margin', 'label.edgeDistance', 'pie');
      }

      option.edgeDistance = option.margin;
    }
  }

  function compatSunburstState(option) {
    if (!option) {
      return;
    }

    if (option.downplay && !option.blur) {
      option.blur = option.downplay;

      if (true) {
        deprecateReplaceLog('downplay', 'blur', 'sunburst');
      }
    }
  }

  function compatGraphFocus(option) {
    if (!option) {
      return;
    }

    if (option.focusNodeAdjacency != null) {
      option.emphasis = option.emphasis || {};

      if (option.emphasis.focus == null) {
        if (true) {
          deprecateReplaceLog('focusNodeAdjacency', 'emphasis: { focus: \'adjacency\'}', 'graph/sankey');
        }

        option.emphasis.focus = 'adjacency';
      }
    }
  }

  function traverseTree(data, cb) {
    if (data) {
      for (var i = 0; i < data.length; i++) {
        cb(data[i]);
        data[i] && traverseTree(data[i].children, cb);
      }
    }
  }

  function globalBackwardCompat(option, isTheme) {
    globalCompatStyle(option, isTheme);
    option.series = normalizeToArray(option.series);
    each(option.series, function (seriesOpt) {
      if (!isObject(seriesOpt)) {
        return;
      }

      var seriesType = seriesOpt.type;

      if (seriesType === 'line') {
        if (seriesOpt.clipOverflow != null) {
          seriesOpt.clip = seriesOpt.clipOverflow;

          if (true) {
            deprecateReplaceLog('clipOverflow', 'clip', 'line');
          }
        }
      } else if (seriesType === 'pie' || seriesType === 'gauge') {
        if (seriesOpt.clockWise != null) {
          seriesOpt.clockwise = seriesOpt.clockWise;

          if (true) {
            deprecateReplaceLog('clockWise', 'clockwise');
          }
        }

        compatPieLabel(seriesOpt.label);
        var data = seriesOpt.data;

        if (data && !isTypedArray(data)) {
          for (var i = 0; i < data.length; i++) {
            compatPieLabel(data[i]);
          }
        }

        if (seriesOpt.hoverOffset != null) {
          seriesOpt.emphasis = seriesOpt.emphasis || {};

          if (seriesOpt.emphasis.scaleSize = null) {
            if (true) {
              deprecateReplaceLog('hoverOffset', 'emphasis.scaleSize');
            }

            seriesOpt.emphasis.scaleSize = seriesOpt.hoverOffset;
          }
        }
      } else if (seriesType === 'gauge') {
        var pointerColor = get(seriesOpt, 'pointer.color');
        pointerColor != null && set$1(seriesOpt, 'itemStyle.color', pointerColor);
      } else if (seriesType === 'bar') {
        compatBarItemStyle(seriesOpt);
        compatBarItemStyle(seriesOpt.backgroundStyle);
        compatBarItemStyle(seriesOpt.emphasis);
        var data = seriesOpt.data;

        if (data && !isTypedArray(data)) {
          for (var i = 0; i < data.length; i++) {
            if (typeof data[i] === 'object') {
              compatBarItemStyle(data[i]);
              compatBarItemStyle(data[i] && data[i].emphasis);
            }
          }
        }
      } else if (seriesType === 'sunburst') {
        var highlightPolicy = seriesOpt.highlightPolicy;

        if (highlightPolicy) {
          seriesOpt.emphasis = seriesOpt.emphasis || {};

          if (!seriesOpt.emphasis.focus) {
            seriesOpt.emphasis.focus = highlightPolicy;

            if (true) {
              deprecateReplaceLog('highlightPolicy', 'emphasis.focus', 'sunburst');
            }
          }
        }

        compatSunburstState(seriesOpt);
        traverseTree(seriesOpt.data, compatSunburstState);
      } else if (seriesType === 'graph' || seriesType === 'sankey') {
        compatGraphFocus(seriesOpt);
      } else if (seriesType === 'map') {
        if (seriesOpt.mapType && !seriesOpt.map) {
          if (true) {
            deprecateReplaceLog('mapType', 'map', 'map');
          }

          seriesOpt.map = seriesOpt.mapType;
        }

        if (seriesOpt.mapLocation) {
          if (true) {
            deprecateLog('`mapLocation` is not used anymore.');
          }

          defaults(seriesOpt, seriesOpt.mapLocation);
        }
      }

      if (seriesOpt.hoverAnimation != null) {
        seriesOpt.emphasis = seriesOpt.emphasis || {};

        if (seriesOpt.emphasis && seriesOpt.emphasis.scale == null) {
          if (true) {
            deprecateReplaceLog('hoverAnimation', 'emphasis.scale');
          }

          seriesOpt.emphasis.scale = seriesOpt.hoverAnimation;
        }
      }

      compatLayoutProperties(seriesOpt);
    });

    if (option.dataRange) {
      option.visualMap = option.dataRange;
    }

    each(COMPATITABLE_COMPONENTS, function (componentName) {
      var options = option[componentName];

      if (options) {
        if (!isArray(options)) {
          options = [options];
        }

        each(options, function (option) {
          compatLayoutProperties(option);
        });
      }
    });
  }

  function dataStack(ecModel) {
    var stackInfoMap = createHashMap();
    ecModel.eachSeries(function (seriesModel) {
      var stack = seriesModel.get('stack');

      if (stack) {
        var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []);
        var data = seriesModel.getData();
        var stackInfo = {
          stackResultDimension: data.getCalculationInfo('stackResultDimension'),
          stackedOverDimension: data.getCalculationInfo('stackedOverDimension'),
          stackedDimension: data.getCalculationInfo('stackedDimension'),
          stackedByDimension: data.getCalculationInfo('stackedByDimension'),
          isStackedByIndex: data.getCalculationInfo('isStackedByIndex'),
          data: data,
          seriesModel: seriesModel
        };

        if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) {
          return;
        }

        stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel);
        stackInfoList.push(stackInfo);
      }
    });
    stackInfoMap.each(calculateStack);
  }

  function calculateStack(stackInfoList) {
    each(stackInfoList, function (targetStackInfo, idxInStack) {
      var resultVal = [];
      var resultNaN = [NaN, NaN];
      var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension];
      var targetData = targetStackInfo.data;
      var isStackedByIndex = targetStackInfo.isStackedByIndex;
      var newData = targetData.map(dims, function (v0, v1, dataIndex) {
        var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex);

        if (isNaN(sum)) {
          return resultNaN;
        }

        var byValue;
        var stackedDataRawIndex;

        if (isStackedByIndex) {
          stackedDataRawIndex = targetData.getRawIndex(dataIndex);
        } else {
          byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex);
        }

        var stackedOver = NaN;

        for (var j = idxInStack - 1; j >= 0; j--) {
          var stackInfo = stackInfoList[j];

          if (!isStackedByIndex) {
            stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue);
          }

          if (stackedDataRawIndex >= 0) {
            var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex);

            if (sum >= 0 && val > 0 || sum <= 0 && val < 0) {
              sum += val;
              stackedOver = val;
              break;
            }
          }
        }

        resultVal[0] = sum;
        resultVal[1] = stackedOver;
        return resultVal;
      });
      targetData.hostModel.setData(newData);
      targetStackInfo.data = newData;
    });
  }

  var SourceImpl = function () {
    function SourceImpl(fields) {
      this.data = fields.data || (fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []);
      this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN;
      this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN;
      this.startIndex = fields.startIndex || 0;
      this.dimensionsDefine = fields.dimensionsDefine;
      this.dimensionsDetectedCount = fields.dimensionsDetectedCount;
      this.encodeDefine = fields.encodeDefine;
      this.metaRawOption = fields.metaRawOption;
    }

    return SourceImpl;
  }();

  function isSourceInstance(val) {
    return val instanceof SourceImpl;
  }

  function createSource(sourceData, thisMetaRawOption, sourceFormat, encodeDefine) {
    sourceFormat = sourceFormat || detectSourceFormat(sourceData);
    var seriesLayoutBy = thisMetaRawOption.seriesLayoutBy;
    var determined = determineSourceDimensions(sourceData, sourceFormat, seriesLayoutBy, thisMetaRawOption.sourceHeader, thisMetaRawOption.dimensions);
    var source = new SourceImpl({
      data: sourceData,
      sourceFormat: sourceFormat,
      seriesLayoutBy: seriesLayoutBy,
      dimensionsDefine: determined.dimensionsDefine,
      startIndex: determined.startIndex,
      dimensionsDetectedCount: determined.dimensionsDetectedCount,
      encodeDefine: makeEncodeDefine(encodeDefine),
      metaRawOption: clone(thisMetaRawOption)
    });
    return source;
  }

  function createSourceFromSeriesDataOption(data) {
    return new SourceImpl({
      data: data,
      sourceFormat: isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL
    });
  }

  function cloneSourceShallow(source) {
    return new SourceImpl({
      data: source.data,
      sourceFormat: source.sourceFormat,
      seriesLayoutBy: source.seriesLayoutBy,
      dimensionsDefine: clone(source.dimensionsDefine),
      startIndex: source.startIndex,
      dimensionsDetectedCount: source.dimensionsDetectedCount,
      encodeDefine: makeEncodeDefine(source.encodeDefine)
    });
  }

  function makeEncodeDefine(encodeDefine) {
    return encodeDefine ? createHashMap(encodeDefine) : null;
  }

  function detectSourceFormat(data) {
    var sourceFormat = SOURCE_FORMAT_UNKNOWN;

    if (isTypedArray(data)) {
      sourceFormat = SOURCE_FORMAT_TYPED_ARRAY;
    } else if (isArray(data)) {
      if (data.length === 0) {
        sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
      }

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

        if (item == null) {
          continue;
        } else if (isArray(item)) {
          sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
          break;
        } else if (isObject(item)) {
          sourceFormat = SOURCE_FORMAT_OBJECT_ROWS;
          break;
        }
      }
    } else if (isObject(data)) {
      for (var key in data) {
        if (hasOwn(data, key) && isArrayLike(data[key])) {
          sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS;
          break;
        }
      }
    } else if (data != null) {
      throw new Error('Invalid data');
    }

    return sourceFormat;
  }

  function determineSourceDimensions(data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine) {
    var dimensionsDetectedCount;
    var startIndex;

    if (!data) {
      return {
        dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
        startIndex: startIndex,
        dimensionsDetectedCount: dimensionsDetectedCount
      };
    }

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
      var dataArrayRows = data;

      if (sourceHeader === 'auto' || sourceHeader == null) {
        arrayRowsTravelFirst(function (val) {
          if (val != null && val !== '-') {
            if (isString(val)) {
              startIndex == null && (startIndex = 1);
            } else {
              startIndex = 0;
            }
          }
        }, seriesLayoutBy, dataArrayRows, 10);
      } else {
        startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0;
      }

      if (!dimensionsDefine && startIndex === 1) {
        dimensionsDefine = [];
        arrayRowsTravelFirst(function (val, index) {
          dimensionsDefine[index] = val != null ? val + '' : '';
        }, seriesLayoutBy, dataArrayRows, Infinity);
      }

      dimensionsDetectedCount = dimensionsDefine ? dimensionsDefine.length : seriesLayoutBy === SERIES_LAYOUT_BY_ROW ? dataArrayRows.length : dataArrayRows[0] ? dataArrayRows[0].length : null;
    } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
      if (!dimensionsDefine) {
        dimensionsDefine = objectRowsCollectDimensions(data);
      }
    } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
      if (!dimensionsDefine) {
        dimensionsDefine = [];
        each(data, function (colArr, key) {
          dimensionsDefine.push(key);
        });
      }
    } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
      var value0 = getDataItemValue(data[0]);
      dimensionsDetectedCount = isArray(value0) && value0.length || 1;
    } else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
      if (true) {
        assert(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.');
      }
    }

    return {
      startIndex: startIndex,
      dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
      dimensionsDetectedCount: dimensionsDetectedCount
    };
  }

  function objectRowsCollectDimensions(data) {
    var firstIndex = 0;
    var obj;

    while (firstIndex < data.length && !(obj = data[firstIndex++])) {}

    if (obj) {
      var dimensions_1 = [];
      each(obj, function (value, key) {
        dimensions_1.push(key);
      });
      return dimensions_1;
    }
  }

  function normalizeDimensionsOption(dimensionsDefine) {
    if (!dimensionsDefine) {
      return;
    }

    var nameMap = createHashMap();
    return map(dimensionsDefine, function (rawItem, index) {
      rawItem = isObject(rawItem) ? rawItem : {
        name: rawItem
      };
      var item = {
        name: rawItem.name,
        displayName: rawItem.displayName,
        type: rawItem.type
      };

      if (name == null) {
        return item;
      }

      item.name += '';

      if (item.displayName == null) {
        item.displayName = item.name;
      }

      var exist = nameMap.get(item.name);

      if (!exist) {
        nameMap.set(item.name, {
          count: 1
        });
      } else {
        item.name += '-' + exist.count++;
      }

      return item;
    });
  }

  function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) {
    if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
      for (var i = 0; i < data.length && i < maxLoop; i++) {
        cb(data[i] ? data[i][0] : null, i);
      }
    } else {
      var value0 = data[0] || [];

      for (var i = 0; i < value0.length && i < maxLoop; i++) {
        cb(value0[i], i);
      }
    }
  }

  var _a, _b, _c;

  var providerMethods;
  var mountMethods;

  var DefaultDataProvider = function () {
    function DefaultDataProvider(sourceParam, dimSize) {
      var source = !isSourceInstance(sourceParam) ? createSourceFromSeriesDataOption(sourceParam) : sourceParam;
      this._source = source;
      var data = this._data = source.data;

      if (source.sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
        if (true) {
          if (dimSize == null) {
            throw new Error('Typed array data must specify dimension size');
          }
        }

        this._offset = 0;
        this._dimSize = dimSize;
        this._data = data;
      }

      mountMethods(this, data, source);
    }

    DefaultDataProvider.prototype.getSource = function () {
      return this._source;
    };

    DefaultDataProvider.prototype.count = function () {
      return 0;
    };

    DefaultDataProvider.prototype.getItem = function (idx, out) {
      return;
    };

    DefaultDataProvider.prototype.appendData = function (newData) {};

    DefaultDataProvider.prototype.clean = function () {};

    DefaultDataProvider.protoInitialize = function () {
      var proto = DefaultDataProvider.prototype;
      proto.pure = false;
      proto.persistent = true;
    }();

    DefaultDataProvider.internalField = function () {
      var _a;

      mountMethods = function (provider, data, source) {
        var sourceFormat = source.sourceFormat;
        var seriesLayoutBy = source.seriesLayoutBy;
        var startIndex = source.startIndex;
        var dimsDef = source.dimensionsDefine;
        var methods = providerMethods[getMethodMapKey(sourceFormat, seriesLayoutBy)];

        if (true) {
          assert(methods, 'Invalide sourceFormat: ' + sourceFormat);
        }

        extend(provider, methods);

        if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
          provider.getItem = getItemForTypedArray;
          provider.count = countForTypedArray;
          provider.fillStorage = fillStorageForTypedArray;
        } else {
          var rawItemGetter = getRawSourceItemGetter(sourceFormat, seriesLayoutBy);
          provider.getItem = bind(rawItemGetter, null, data, startIndex, dimsDef);
          var rawCounter = getRawSourceDataCounter(sourceFormat, seriesLayoutBy);
          provider.count = bind(rawCounter, null, data, startIndex, dimsDef);
        }
      };

      var getItemForTypedArray = function (idx, out) {
        idx = idx - this._offset;
        out = out || [];
        var data = this._data;
        var dimSize = this._dimSize;
        var offset = dimSize * idx;

        for (var i = 0; i < dimSize; i++) {
          out[i] = data[offset + i];
        }

        return out;
      };

      var fillStorageForTypedArray = function (start, end, storage, extent) {
        var data = this._data;
        var dimSize = this._dimSize;

        for (var dim = 0; dim < dimSize; dim++) {
          var dimExtent = extent[dim];
          var min = dimExtent[0] == null ? Infinity : dimExtent[0];
          var max = dimExtent[1] == null ? -Infinity : dimExtent[1];
          var count = end - start;
          var arr = storage[dim];

          for (var i = 0; i < count; i++) {
            var val = data[(start + i) * dimSize + dim];
            arr[start + i] = val;
            val < min && (min = val);
            val > max && (max = val);
          }

          dimExtent[0] = min;
          dimExtent[1] = max;
        }
      };

      var countForTypedArray = function () {
        return this._data ? this._data.length / this._dimSize : 0;
      };

      providerMethods = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = {
        pure: true,
        appendData: appendDataSimply
      }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = {
        pure: true,
        appendData: function () {
          throw new Error('Do not support appendData when set seriesLayoutBy: "row".');
        }
      }, _a[SOURCE_FORMAT_OBJECT_ROWS] = {
        pure: true,
        appendData: appendDataSimply
      }, _a[SOURCE_FORMAT_KEYED_COLUMNS] = {
        pure: true,
        appendData: function (newData) {
          var data = this._data;
          each(newData, function (newCol, key) {
            var oldCol = data[key] || (data[key] = []);

            for (var i = 0; i < (newCol || []).length; i++) {
              oldCol.push(newCol[i]);
            }
          });
        }
      }, _a[SOURCE_FORMAT_ORIGINAL] = {
        appendData: appendDataSimply
      }, _a[SOURCE_FORMAT_TYPED_ARRAY] = {
        persistent: false,
        pure: true,
        appendData: function (newData) {
          if (true) {
            assert(isTypedArray(newData), 'Added data must be TypedArray if data in initialization is TypedArray');
          }

          this._data = newData;
        },
        clean: function () {
          this._offset += this.count();
          this._data = null;
        }
      }, _a);

      function appendDataSimply(newData) {
        for (var i = 0; i < newData.length; i++) {
          this._data.push(newData[i]);
        }
      }
    }();

    return DefaultDataProvider;
  }();

  var getItemSimply = function (rawData, startIndex, dimsDef, idx) {
    return rawData[idx];
  };

  var rawSourceItemGetterMap = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef, idx) {
    return rawData[idx + startIndex];
  }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef, idx) {
    idx += startIndex;
    var item = [];
    var data = rawData;

    for (var i = 0; i < data.length; i++) {
      var row = data[i];
      item.push(row ? row[idx] : null);
    }

    return item;
  }, _a[SOURCE_FORMAT_OBJECT_ROWS] = getItemSimply, _a[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef, idx) {
    var item = [];

    for (var i = 0; i < dimsDef.length; i++) {
      var dimName = dimsDef[i].name;

      if (true) {
        if (dimName == null) {
          throw new Error();
        }
      }

      var col = rawData[dimName];
      item.push(col ? col[idx] : null);
    }

    return item;
  }, _a[SOURCE_FORMAT_ORIGINAL] = getItemSimply, _a);

  function getRawSourceItemGetter(sourceFormat, seriesLayoutBy) {
    var method = rawSourceItemGetterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)];

    if (true) {
      assert(method, 'Do not suppport get item on "' + sourceFormat + '", "' + seriesLayoutBy + '".');
    }

    return method;
  }

  var countSimply = function (rawData, startIndex, dimsDef) {
    return rawData.length;
  };

  var rawSourceDataCounterMap = (_b = {}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef) {
    return Math.max(0, rawData.length - startIndex);
  }, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef) {
    var row = rawData[0];
    return row ? Math.max(0, row.length - startIndex) : 0;
  }, _b[SOURCE_FORMAT_OBJECT_ROWS] = countSimply, _b[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef) {
    var dimName = dimsDef[0].name;

    if (true) {
      if (dimName == null) {
        throw new Error();
      }
    }

    var col = rawData[dimName];
    return col ? col.length : 0;
  }, _b[SOURCE_FORMAT_ORIGINAL] = countSimply, _b);

  function getRawSourceDataCounter(sourceFormat, seriesLayoutBy) {
    var method = rawSourceDataCounterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)];

    if (true) {
      assert(method, 'Do not suppport count on "' + sourceFormat + '", "' + seriesLayoutBy + '".');
    }

    return method;
  }

  var getRawValueSimply = function (dataItem, dimIndex, dimName) {
    return dimIndex != null ? dataItem[dimIndex] : dataItem;
  };

  var rawSourceValueGetterMap = (_c = {}, _c[SOURCE_FORMAT_ARRAY_ROWS] = getRawValueSimply, _c[SOURCE_FORMAT_OBJECT_ROWS] = function (dataItem, dimIndex, dimName) {
    return dimIndex != null ? dataItem[dimName] : dataItem;
  }, _c[SOURCE_FORMAT_KEYED_COLUMNS] = getRawValueSimply, _c[SOURCE_FORMAT_ORIGINAL] = function (dataItem, dimIndex, dimName) {
    var value = getDataItemValue(dataItem);
    return dimIndex == null || !(value instanceof Array) ? value : value[dimIndex];
  }, _c[SOURCE_FORMAT_TYPED_ARRAY] = getRawValueSimply, _c);

  function getRawSourceValueGetter(sourceFormat) {
    var method = rawSourceValueGetterMap[sourceFormat];

    if (true) {
      assert(method, 'Do not suppport get value on "' + sourceFormat + '".');
    }

    return method;
  }

  function getMethodMapKey(sourceFormat, seriesLayoutBy) {
    return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + seriesLayoutBy : sourceFormat;
  }

  function retrieveRawValue(data, dataIndex, dim) {
    if (!data) {
      return;
    }

    var dataItem = data.getRawDataItem(dataIndex);

    if (dataItem == null) {
      return;
    }

    var sourceFormat = data.getProvider().getSource().sourceFormat;
    var dimName;
    var dimIndex;
    var dimInfo = data.getDimensionInfo(dim);

    if (dimInfo) {
      dimName = dimInfo.name;
      dimIndex = dimInfo.index;
    }

    return getRawSourceValueGetter(sourceFormat)(dataItem, dimIndex, dimName);
  }

  var DIMENSION_LABEL_REG = /\{@(.+?)\}/g;

  var DataFormatMixin = function () {
    function DataFormatMixin() {}

    DataFormatMixin.prototype.getDataParams = function (dataIndex, dataType) {
      var data = this.getData(dataType);
      var rawValue = this.getRawValue(dataIndex, dataType);
      var rawDataIndex = data.getRawIndex(dataIndex);
      var name = data.getName(dataIndex);
      var itemOpt = data.getRawDataItem(dataIndex);
      var style = data.getItemVisual(dataIndex, 'style');
      var color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill'];
      var borderColor = style && style.stroke;
      var mainType = this.mainType;
      var isSeries = mainType === 'series';
      var userOutput = data.userOutput;
      return {
        componentType: mainType,
        componentSubType: this.subType,
        componentIndex: this.componentIndex,
        seriesType: isSeries ? this.subType : null,
        seriesIndex: this.seriesIndex,
        seriesId: isSeries ? this.id : null,
        seriesName: isSeries ? this.name : null,
        name: name,
        dataIndex: rawDataIndex,
        data: itemOpt,
        dataType: dataType,
        value: rawValue,
        color: color,
        borderColor: borderColor,
        dimensionNames: userOutput ? userOutput.dimensionNames : null,
        encode: userOutput ? userOutput.encode : null,
        $vars: ['seriesName', 'name', 'value']
      };
    };

    DataFormatMixin.prototype.getFormattedLabel = function (dataIndex, status, dataType, labelDimIndex, formatter, extendParams) {
      status = status || 'normal';
      var data = this.getData(dataType);
      var params = this.getDataParams(dataIndex, dataType);

      if (extendParams) {
        extend(params, extendParams);
      }

      if (labelDimIndex != null && params.value instanceof Array) {
        params.value = params.value[labelDimIndex];
      }

      if (!formatter) {
        var itemModel = data.getItemModel(dataIndex);
        formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : [status, 'label', 'formatter']);
      }

      if (typeof formatter === 'function') {
        params.status = status;
        params.dimensionIndex = labelDimIndex;
        return formatter(params);
      } else if (typeof formatter === 'string') {
        var str = formatTpl(formatter, params);
        return str.replace(DIMENSION_LABEL_REG, function (origin, dim) {
          var len = dim.length;

          if (dim.charAt(0) === '[' && dim.charAt(len - 1) === ']') {
            dim = +dim.slice(1, len - 1);
          }

          return retrieveRawValue(data, dataIndex, dim);
        });
      }
    };

    DataFormatMixin.prototype.getRawValue = function (idx, dataType) {
      return retrieveRawValue(this.getData(dataType), idx);
    };

    DataFormatMixin.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      return;
    };

    return DataFormatMixin;
  }();

  function normalizeTooltipFormatResult(result) {
    var markupText;
    var markupFragment;

    if (isObject(result)) {
      if (result.type) {
        markupFragment = result;
      } else {
        if (true) {
          console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result));
        }
      }
    } else {
      markupText = result;
    }

    return {
      markupText: markupText,
      markupFragment: markupFragment
    };
  }

  function createTask(define) {
    return new Task(define);
  }

  var Task = function () {
    function Task(define) {
      define = define || {};
      this._reset = define.reset;
      this._plan = define.plan;
      this._count = define.count;
      this._onDirty = define.onDirty;
      this._dirty = true;
    }

    Task.prototype.perform = function (performArgs) {
      var upTask = this._upstream;
      var skip = performArgs && performArgs.skip;

      if (this._dirty && upTask) {
        var context = this.context;
        context.data = context.outputData = upTask.context.outputData;
      }

      if (this.__pipeline) {
        this.__pipeline.currentTask = this;
      }

      var planResult;

      if (this._plan && !skip) {
        planResult = this._plan(this.context);
      }

      var lastModBy = normalizeModBy(this._modBy);
      var lastModDataCount = this._modDataCount || 0;
      var modBy = normalizeModBy(performArgs && performArgs.modBy);
      var modDataCount = performArgs && performArgs.modDataCount || 0;

      if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
        planResult = 'reset';
      }

      function normalizeModBy(val) {
        !(val >= 1) && (val = 1);
        return val;
      }

      var forceFirstProgress;

      if (this._dirty || planResult === 'reset') {
        this._dirty = false;
        forceFirstProgress = this._doReset(skip);
      }

      this._modBy = modBy;
      this._modDataCount = modDataCount;
      var step = performArgs && performArgs.step;

      if (upTask) {
        if (true) {
          assert(upTask._outputDueEnd != null);
        }

        this._dueEnd = upTask._outputDueEnd;
      } else {
        if (true) {
          assert(!this._progress || this._count);
        }

        this._dueEnd = this._count ? this._count(this.context) : Infinity;
      }

      if (this._progress) {
        var start = this._dueIndex;
        var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd);

        if (!skip && (forceFirstProgress || start < end)) {
          var progress = this._progress;

          if (isArray(progress)) {
            for (var i = 0; i < progress.length; i++) {
              this._doProgress(progress[i], start, end, modBy, modDataCount);
            }
          } else {
            this._doProgress(progress, start, end, modBy, modDataCount);
          }
        }

        this._dueIndex = end;
        var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end;

        if (true) {
          assert(outputDueEnd >= this._outputDueEnd);
        }

        this._outputDueEnd = outputDueEnd;
      } else {
        this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd;
      }

      return this.unfinished();
    };

    Task.prototype.dirty = function () {
      this._dirty = true;
      this._onDirty && this._onDirty(this.context);
    };

    Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) {
      iterator.reset(start, end, modBy, modDataCount);
      this._callingProgress = progress;

      this._callingProgress({
        start: start,
        end: end,
        count: end - start,
        next: iterator.next
      }, this.context);
    };

    Task.prototype._doReset = function (skip) {
      this._dueIndex = this._outputDueEnd = this._dueEnd = 0;
      this._settedOutputEnd = null;
      var progress;
      var forceFirstProgress;

      if (!skip && this._reset) {
        progress = this._reset(this.context);

        if (progress && progress.progress) {
          forceFirstProgress = progress.forceFirstProgress;
          progress = progress.progress;
        }

        if (isArray(progress) && !progress.length) {
          progress = null;
        }
      }

      this._progress = progress;
      this._modBy = this._modDataCount = null;
      var downstream = this._downstream;
      downstream && downstream.dirty();
      return forceFirstProgress;
    };

    Task.prototype.unfinished = function () {
      return this._progress && this._dueIndex < this._dueEnd;
    };

    Task.prototype.pipe = function (downTask) {
      if (true) {
        assert(downTask && !downTask._disposed && downTask !== this);
      }

      if (this._downstream !== downTask || this._dirty) {
        this._downstream = downTask;
        downTask._upstream = this;
        downTask.dirty();
      }
    };

    Task.prototype.dispose = function () {
      if (this._disposed) {
        return;
      }

      this._upstream && (this._upstream._downstream = null);
      this._downstream && (this._downstream._upstream = null);
      this._dirty = false;
      this._disposed = true;
    };

    Task.prototype.getUpstream = function () {
      return this._upstream;
    };

    Task.prototype.getDownstream = function () {
      return this._downstream;
    };

    Task.prototype.setOutputEnd = function (end) {
      this._outputDueEnd = this._settedOutputEnd = end;
    };

    return Task;
  }();

  var iterator = function () {
    var end;
    var current;
    var modBy;
    var modDataCount;
    var winCount;
    var it = {
      reset: function (s, e, sStep, sCount) {
        current = s;
        end = e;
        modBy = sStep;
        modDataCount = sCount;
        winCount = Math.ceil(modDataCount / modBy);
        it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext;
      }
    };
    return it;

    function sequentialNext() {
      return current < end ? current++ : null;
    }

    function modNext() {
      var dataIndex = current % winCount * modBy + Math.ceil(current / winCount);
      var result = current >= end ? null : dataIndex < modDataCount ? dataIndex : current;
      current++;
      return result;
    }
  }();

  function parseDataValue(value, opt) {
    var dimType = opt && opt.type;

    if (dimType === 'ordinal') {
      var ordinalMeta = opt && opt.ordinalMeta;
      return ordinalMeta ? ordinalMeta.parseAndCollect(value) : value;
    }

    if (dimType === 'time' && typeof value !== 'number' && value != null && value !== '-') {
      value = +parseDate(value);
    }

    return value == null || value === '' ? NaN : +value;
  }

  var valueParserMap = createHashMap({
    'number': function (val) {
      return parseFloat(val);
    },
    'time': function (val) {
      return +parseDate(val);
    },
    'trim': function (val) {
      return typeof val === 'string' ? trim(val) : val;
    }
  });

  function getRawValueParser(type) {
    return valueParserMap.get(type);
  }

  var ORDER_COMPARISON_OP_MAP = {
    lt: function (lval, rval) {
      return lval < rval;
    },
    lte: function (lval, rval) {
      return lval <= rval;
    },
    gt: function (lval, rval) {
      return lval > rval;
    },
    gte: function (lval, rval) {
      return lval >= rval;
    }
  };

  var FilterOrderComparator = function () {
    function FilterOrderComparator(op, rval) {
      if (typeof rval !== 'number') {
        var errMsg = '';

        if (true) {
          errMsg = 'rvalue of "<", ">", "<=", ">=" can only be number in filter.';
        }

        throwError(errMsg);
      }

      this._opFn = ORDER_COMPARISON_OP_MAP[op];
      this._rvalFloat = numericToNumber(rval);
    }

    FilterOrderComparator.prototype.evaluate = function (lval) {
      return typeof lval === 'number' ? this._opFn(lval, this._rvalFloat) : this._opFn(numericToNumber(lval), this._rvalFloat);
    };

    return FilterOrderComparator;
  }();

  var SortOrderComparator = function () {
    function SortOrderComparator(order, incomparable) {
      var isDesc = order === 'desc';
      this._resultLT = isDesc ? 1 : -1;

      if (incomparable == null) {
        incomparable = isDesc ? 'min' : 'max';
      }

      this._incomparable = incomparable === 'min' ? -Infinity : Infinity;
    }

    SortOrderComparator.prototype.evaluate = function (lval, rval) {
      var lvalTypeof = typeof lval;
      var rvalTypeof = typeof rval;
      var lvalFloat = lvalTypeof === 'number' ? lval : numericToNumber(lval);
      var rvalFloat = rvalTypeof === 'number' ? rval : numericToNumber(rval);
      var lvalNotNumeric = isNaN(lvalFloat);
      var rvalNotNumeric = isNaN(rvalFloat);

      if (lvalNotNumeric) {
        lvalFloat = this._incomparable;
      }

      if (rvalNotNumeric) {
        rvalFloat = this._incomparable;
      }

      if (lvalNotNumeric && rvalNotNumeric) {
        var lvalIsStr = lvalTypeof === 'string';
        var rvalIsStr = rvalTypeof === 'string';

        if (lvalIsStr) {
          lvalFloat = rvalIsStr ? lval : 0;
        }

        if (rvalIsStr) {
          rvalFloat = lvalIsStr ? rval : 0;
        }
      }

      return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0;
    };

    return SortOrderComparator;
  }();

  var FilterEqualityComparator = function () {
    function FilterEqualityComparator(isEq, rval) {
      this._rval = rval;
      this._isEQ = isEq;
      this._rvalTypeof = typeof rval;
      this._rvalFloat = numericToNumber(rval);
    }

    FilterEqualityComparator.prototype.evaluate = function (lval) {
      var eqResult = lval === this._rval;

      if (!eqResult) {
        var lvalTypeof = typeof lval;

        if (lvalTypeof !== this._rvalTypeof && (lvalTypeof === 'number' || this._rvalTypeof === 'number')) {
          eqResult = numericToNumber(lval) === this._rvalFloat;
        }
      }

      return this._isEQ ? eqResult : !eqResult;
    };

    return FilterEqualityComparator;
  }();

  function createFilterComparator(op, rval) {
    return op === 'eq' || op === 'ne' ? new FilterEqualityComparator(op === 'eq', rval) : hasOwn(ORDER_COMPARISON_OP_MAP, op) ? new FilterOrderComparator(op, rval) : null;
  }

  var ExternalSource = function () {
    function ExternalSource() {}

    ExternalSource.prototype.getRawData = function () {
      throw new Error('not supported');
    };

    ExternalSource.prototype.getRawDataItem = function (dataIndex) {
      throw new Error('not supported');
    };

    ExternalSource.prototype.cloneRawData = function () {
      return;
    };

    ExternalSource.prototype.getDimensionInfo = function (dim) {
      return;
    };

    ExternalSource.prototype.cloneAllDimensionInfo = function () {
      return;
    };

    ExternalSource.prototype.count = function () {
      return;
    };

    ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) {
      return;
    };

    ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) {
      return;
    };

    ExternalSource.prototype.convertValue = function (rawVal, dimInfo) {
      return parseDataValue(rawVal, dimInfo);
    };

    return ExternalSource;
  }();

  function createExternalSource(internalSource, externalTransform) {
    var extSource = new ExternalSource();
    var data = internalSource.data;
    var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat;
    var sourceHeaderCount = internalSource.startIndex;
    var dimensions = [];
    var dimsByName = {};
    var dimsDef = internalSource.dimensionsDefine;

    if (dimsDef) {
      each(dimsDef, function (dimDef, idx) {
        var name = dimDef.name;
        var dimDefExt = {
          index: idx,
          name: name,
          displayName: dimDef.displayName
        };
        dimensions.push(dimDefExt);

        if (name != null) {
          var errMsg = '';

          if (hasOwn(dimsByName, name)) {
            if (true) {
              errMsg = 'dimension name "' + name + '" duplicated.';
            }

            throwError(errMsg);
          }

          dimsByName[name] = dimDefExt;
        }
      });
    } else {
      for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) {
        dimensions.push({
          index: i
        });
      }
    }

    var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);

    if (externalTransform.__isBuiltIn) {
      extSource.getRawDataItem = function (dataIndex) {
        return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
      };

      extSource.getRawData = bind(getRawData, null, internalSource);
    }

    extSource.cloneRawData = bind(cloneRawData, null, internalSource);
    var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);
    extSource.count = bind(rawCounter, null, data, sourceHeaderCount, dimensions);
    var rawValueGetter = getRawSourceValueGetter(sourceFormat);

    extSource.retrieveValue = function (dataIndex, dimIndex) {
      var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
      return retrieveValueFromItem(rawItem, dimIndex);
    };

    var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) {
      if (dataItem == null) {
        return;
      }

      var dimDef = dimensions[dimIndex];

      if (dimDef) {
        return rawValueGetter(dataItem, dimIndex, dimDef.name);
      }
    };

    extSource.getDimensionInfo = bind(getDimensionInfo, null, dimensions, dimsByName);
    extSource.cloneAllDimensionInfo = bind(cloneAllDimensionInfo, null, dimensions);
    return extSource;
  }

  function getRawData(upstream) {
    var sourceFormat = upstream.sourceFormat;
    var data = upstream.data;

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || !data || isArray(data) && !data.length) {
      return upstream.data;
    }

    var errMsg = '';

    if (true) {
      errMsg = '`getRawData` is not supported in source format ' + sourceFormat;
    }

    throwError(errMsg);
  }

  function cloneRawData(upstream) {
    var sourceFormat = upstream.sourceFormat;
    var data = upstream.data;

    if (!data) {
      return data;
    } else if (isArray(data) && !data.length) {
      return [];
    } else if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
      var result = [];

      for (var i = 0, len = data.length; i < len; i++) {
        result.push(data[i].slice());
      }

      return result;
    } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
      var result = [];

      for (var i = 0, len = data.length; i < len; i++) {
        result.push(extend({}, data[i]));
      }

      return result;
    }
  }

  function getDimensionInfo(dimensions, dimsByName, dim) {
    if (dim == null) {
      return;
    }

    if (typeof dim === 'number' || !isNaN(dim) && !hasOwn(dimsByName, dim)) {
      return dimensions[dim];
    } else if (hasOwn(dimsByName, dim)) {
      return dimsByName[dim];
    }
  }

  function cloneAllDimensionInfo(dimensions) {
    return clone(dimensions);
  }

  var externalTransformMap = createHashMap();

  function registerExternalTransform(externalTransform) {
    externalTransform = clone(externalTransform);
    var type = externalTransform.type;
    var errMsg = '';

    if (!type) {
      if (true) {
        errMsg = 'Must have a `type` when `registerTransform`.';
      }

      throwError(errMsg);
    }

    var typeParsed = type.split(':');

    if (typeParsed.length !== 2) {
      if (true) {
        errMsg = 'Name must include namespace like "ns:regression".';
      }

      throwError(errMsg);
    }

    var isBuiltIn = false;

    if (typeParsed[0] === 'echarts') {
      type = typeParsed[1];
      isBuiltIn = true;
    }

    externalTransform.__isBuiltIn = isBuiltIn;
    externalTransformMap.set(type, externalTransform);
  }

  function applyDataTransform(rawTransOption, sourceList, infoForPrint) {
    var pipedTransOption = normalizeToArray(rawTransOption);
    var pipeLen = pipedTransOption.length;
    var errMsg = '';

    if (!pipeLen) {
      if (true) {
        errMsg = 'If `transform` declared, it should at least contain one transform.';
      }

      throwError(errMsg);
    }

    for (var i = 0, len = pipeLen; i < len; i++) {
      var transOption = pipedTransOption[i];
      sourceList = applySingleDataTransform(transOption, sourceList, infoForPrint, pipeLen === 1 ? null : i);

      if (i !== len - 1) {
        sourceList.length = Math.max(sourceList.length, 1);
      }
    }

    return sourceList;
  }

  function applySingleDataTransform(transOption, upSourceList, infoForPrint, pipeIndex) {
    var errMsg = '';

    if (!upSourceList.length) {
      if (true) {
        errMsg = 'Must have at least one upstream dataset.';
      }

      throwError(errMsg);
    }

    if (!isObject(transOption)) {
      if (true) {
        errMsg = 'transform declaration must be an object rather than ' + typeof transOption + '.';
      }

      throwError(errMsg);
    }

    var transType = transOption.type;
    var externalTransform = externalTransformMap.get(transType);

    if (!externalTransform) {
      if (true) {
        errMsg = 'Can not find transform on type "' + transType + '".';
      }

      throwError(errMsg);
    }

    var extUpSourceList = map(upSourceList, function (upSource) {
      return createExternalSource(upSource, externalTransform);
    });
    var resultList = normalizeToArray(externalTransform.transform({
      upstream: extUpSourceList[0],
      upstreamList: extUpSourceList,
      config: clone(transOption.config)
    }));

    if (true) {
      if (transOption.print) {
        var printStrArr = map(resultList, function (extSource) {
          var pipeIndexStr = pipeIndex != null ? ' === pipe index: ' + pipeIndex : '';
          return ['=== dataset index: ' + infoForPrint.datasetIndex + pipeIndexStr + ' ===', '- transform result data:', makePrintable(extSource.data), '- transform result dimensions:', makePrintable(extSource.dimensions)].join('\n');
        }).join('\n');
        consoleLog(printStrArr);
      }
    }

    return map(resultList, function (result) {
      var errMsg = '';

      if (!isObject(result)) {
        if (true) {
          errMsg = 'A transform should not return some empty results.';
        }

        throwError(errMsg);
      }

      var resultData = result.data;

      if (resultData != null) {
        if (!isObject(resultData) && !isArrayLike(resultData)) {
          if (true) {
            errMsg = 'Result data should be object or array in data transform.';
          }

          throwError(errMsg);
        }
      } else {
        resultData = upSourceList[0].data;
      }

      var resultMetaRawOption = inheritSourceMetaRawOption(upSourceList[0], {
        seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,
        sourceHeader: 0,
        dimensions: result.dimensions
      });
      return createSource(resultData, resultMetaRawOption, null, null);
    });
  }

  var SourceManager = function () {
    function SourceManager(sourceHost) {
      this._sourceList = [];
      this._upstreamSignList = [];
      this._versionSignBase = 0;
      this._sourceHost = sourceHost;
    }

    SourceManager.prototype.dirty = function () {
      this._setLocalSource([], []);
    };

    SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) {
      this._sourceList = sourceList;
      this._upstreamSignList = upstreamSignList;
      this._versionSignBase++;

      if (this._versionSignBase > 9e10) {
        this._versionSignBase = 0;
      }
    };

    SourceManager.prototype._getVersionSign = function () {
      return this._sourceHost.uid + '_' + this._versionSignBase;
    };

    SourceManager.prototype.prepareSource = function () {
      if (this._isDirty()) {
        this._createSource();
      }
    };

    SourceManager.prototype._createSource = function () {
      this._setLocalSource([], []);

      var sourceHost = this._sourceHost;

      var upSourceMgrList = this._getUpstreamSourceManagers();

      var hasUpstream = !!upSourceMgrList.length;
      var resultSourceList;
      var upstreamSignList;

      if (isSeries(sourceHost)) {
        var seriesModel = sourceHost;
        var data = void 0;
        var sourceFormat = void 0;
        var upSource = void 0;

        if (hasUpstream) {
          var upSourceMgr = upSourceMgrList[0];
          upSourceMgr.prepareSource();
          upSource = upSourceMgr.getSource();
          data = upSource.data;
          sourceFormat = upSource.sourceFormat;
          upstreamSignList = [upSourceMgr._getVersionSign()];
        } else {
          data = seriesModel.get('data', true);
          sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL;
          upstreamSignList = [];
        }

        var thisMetaRawOption = inheritSourceMetaRawOption(upSource, this._getSourceMetaRawOption());
        resultSourceList = [createSource(data, thisMetaRawOption, sourceFormat, seriesModel.get('encode', true))];
      } else {
        var datasetModel = sourceHost;

        if (hasUpstream) {
          var result = this._applyTransform(upSourceMgrList);

          resultSourceList = result.sourceList;
          upstreamSignList = result.upstreamSignList;
        } else {
          var sourceData = datasetModel.get('source', true);
          resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null, null)];
          upstreamSignList = [];
        }
      }

      if (true) {
        assert(resultSourceList && upstreamSignList);
      }

      this._setLocalSource(resultSourceList, upstreamSignList);
    };

    SourceManager.prototype._applyTransform = function (upMgrList) {
      var datasetModel = this._sourceHost;
      var transformOption = datasetModel.get('transform', true);
      var fromTransformResult = datasetModel.get('fromTransformResult', true);

      if (true) {
        assert(fromTransformResult != null || transformOption != null);
      }

      if (fromTransformResult != null) {
        var errMsg = '';

        if (upMgrList.length !== 1) {
          if (true) {
            errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset';
          }

          doThrow(errMsg);
        }
      }

      var sourceList;
      var upSourceList = [];
      var upstreamSignList = [];
      each(upMgrList, function (upMgr) {
        upMgr.prepareSource();
        var upSource = upMgr.getSource(fromTransformResult || 0);
        var errMsg = '';

        if (fromTransformResult != null && !upSource) {
          if (true) {
            errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult;
          }

          doThrow(errMsg);
        }

        upSourceList.push(upSource);
        upstreamSignList.push(upMgr._getVersionSign());
      });

      if (transformOption) {
        sourceList = applyDataTransform(transformOption, upSourceList, {
          datasetIndex: datasetModel.componentIndex
        });
      } else if (fromTransformResult != null) {
        sourceList = [cloneSourceShallow(upSourceList[0])];
      }

      return {
        sourceList: sourceList,
        upstreamSignList: upstreamSignList
      };
    };

    SourceManager.prototype._isDirty = function () {
      var sourceList = this._sourceList;

      if (!sourceList.length) {
        return true;
      }

      var upSourceMgrList = this._getUpstreamSourceManagers();

      for (var i = 0; i < upSourceMgrList.length; i++) {
        var upSrcMgr = upSourceMgrList[i];

        if (upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) {
          return true;
        }
      }
    };

    SourceManager.prototype.getSource = function (sourceIndex) {
      return this._sourceList[sourceIndex || 0];
    };

    SourceManager.prototype._getUpstreamSourceManagers = function () {
      var sourceHost = this._sourceHost;

      if (isSeries(sourceHost)) {
        var datasetModel = querySeriesUpstreamDatasetModel(sourceHost);
        return !datasetModel ? [] : [datasetModel.getSourceManager()];
      } else {
        return map(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) {
          return datasetModel.getSourceManager();
        });
      }
    };

    SourceManager.prototype._getSourceMetaRawOption = function () {
      var sourceHost = this._sourceHost;
      var seriesLayoutBy;
      var sourceHeader;
      var dimensions;

      if (isSeries(sourceHost)) {
        seriesLayoutBy = sourceHost.get('seriesLayoutBy', true);
        sourceHeader = sourceHost.get('sourceHeader', true);
        dimensions = sourceHost.get('dimensions', true);
      } else if (!this._getUpstreamSourceManagers().length) {
        var model = sourceHost;
        seriesLayoutBy = model.get('seriesLayoutBy', true);
        sourceHeader = model.get('sourceHeader', true);
        dimensions = model.get('dimensions', true);
      }

      return {
        seriesLayoutBy: seriesLayoutBy,
        sourceHeader: sourceHeader,
        dimensions: dimensions
      };
    };

    return SourceManager;
  }();

  function disableTransformOptionMerge(datasetModel) {
    var transformOption = datasetModel.option.transform;
    transformOption && setAsPrimitive(datasetModel.option.transform);
  }

  function isSeries(sourceHost) {
    return sourceHost.mainType === 'series';
  }

  function doThrow(errMsg) {
    throw new Error(errMsg);
  }

  var TOOLTIP_NAME_TEXT_STYLE_CSS = 'font-size:12px;color:#6e7079';
  var TOOLTIP_TEXT_STYLE_RICH = {
    fontSize: 12,
    fill: '#6e7079'
  };
  var TOOLTIP_VALUE_TEXT_STYLE_CSS = 'font-size:14px;color:#464646;font-weight:900';
  var TOOLTIP_VALUE_TEXT_STYLE_RICH = {
    fontSize: 14,
    fill: '#464646',
    fontWeight: 900
  };
  var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1';
  var HTML_GAPS = [0, 10, 20, 30];
  var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n'];

  function createTooltipMarkup(type, option) {
    option.type = type;
    return option;
  }

  function getBuilder(fragment) {
    return hasOwn(builderMap, fragment.type) && builderMap[fragment.type];
  }

  var builderMap = {
    section: {
      planLayout: function (fragment) {
        var subBlockLen = fragment.blocks.length;
        var thisBlockHasInnerGap = subBlockLen > 1 || subBlockLen > 0 && !fragment.noHeader;
        var thisGapLevelBetweenSubBlocks = 0;
        each(fragment.blocks, function (subBlock) {
          getBuilder(subBlock).planLayout(subBlock);
          var subGapLevel = subBlock.__gapLevelBetweenSubBlocks;

          if (subGapLevel >= thisGapLevelBetweenSubBlocks) {
            thisGapLevelBetweenSubBlocks = subGapLevel + (thisBlockHasInnerGap && (!subGapLevel || subBlock.type === 'section' && !subBlock.noHeader) ? 1 : 0);
          }
        });
        fragment.__gapLevelBetweenSubBlocks = thisGapLevelBetweenSubBlocks;
      },
      build: function (ctx, fragment, topMarginForOuterGap) {
        var noHeader = fragment.noHeader;
        var gaps = getGap(fragment);
        var subMarkupText = buildSubBlocks(ctx, fragment, noHeader ? topMarginForOuterGap : gaps.html);

        if (noHeader) {
          return subMarkupText;
        }

        var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);

        if (ctx.renderMode === 'richText') {
          return wrapInlineNameRichText(ctx, displayableHeader) + gaps.richText + subMarkupText;
        } else {
          return wrapBlockHTML("<div style=\"" + TOOLTIP_NAME_TEXT_STYLE_CSS + ";" + TOOLTIP_LINE_HEIGHT_CSS + ";\">" + encodeHTML(displayableHeader) + '</div>' + subMarkupText, topMarginForOuterGap);
        }
      }
    },
    nameValue: {
      planLayout: function (fragment) {
        fragment.__gapLevelBetweenSubBlocks = 0;
      },
      build: function (ctx, fragment, topMarginForOuterGap) {
        var renderMode = ctx.renderMode;
        var noName = fragment.noName;
        var noValue = fragment.noValue;
        var noMarker = !fragment.markerType;
        var name = fragment.name;
        var value = fragment.value;
        var useUTC = ctx.useUTC;

        if (noName && noValue) {
          return;
        }

        var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode);
        var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC);
        var valueTypeOption = fragment.valueType;
        var readableValueList = noValue ? [] : isArray(value) ? map(value, function (val, idx) {
          return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC);
        }) : [makeValueReadable(value, isArray(valueTypeOption) ? valueTypeOption[0] : valueTypeOption, useUTC)];
        var valueAlignRight = !noMarker || !noName;
        var valueCloseToMarker = !noMarker && noName;
        return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName)) + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker)), topMarginForOuterGap);
      }
    }
  };

  function buildSubBlocks(ctx, fragment, topMarginForOuterGap) {
    var subMarkupTextList = [];
    var subBlocks = fragment.blocks || [];
    assert(!subBlocks || isArray(subBlocks));
    subBlocks = subBlocks || [];
    var orderMode = ctx.orderMode;

    if (fragment.sortBlocks && orderMode) {
      subBlocks = subBlocks.slice();
      var orderMap = {
        valueAsc: 'asc',
        valueDesc: 'desc'
      };

      if (hasOwn(orderMap, orderMode)) {
        var comparator_1 = new SortOrderComparator(orderMap[orderMode], null);
        subBlocks.sort(function (a, b) {
          return comparator_1.evaluate(a.sortParam, b.sortParam);
        });
      } else if (orderMode === 'seriesDesc') {
        subBlocks.reverse();
      }
    }

    var gaps = getGap(fragment);
    each(subBlocks, function (subBlock, idx) {
      var subMarkupText = getBuilder(subBlock).build(ctx, subBlock, idx > 0 ? gaps.html : 0);
      subMarkupText != null && subMarkupTextList.push(subMarkupText);
    });

    if (!subMarkupTextList.length) {
      return;
    }

    return ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), topMarginForOuterGap);
  }

  function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC) {
    if (!fragment) {
      return;
    }

    var builder = getBuilder(fragment);
    builder.planLayout(fragment);
    var ctx = {
      useUTC: useUTC,
      renderMode: renderMode,
      orderMode: orderMode,
      markupStyleCreator: markupStyleCreator
    };
    return builder.build(ctx, fragment, 0);
  }

  function getGap(fragment) {
    var gapLevelBetweenSubBlocks = fragment.__gapLevelBetweenSubBlocks;
    return {
      html: HTML_GAPS[gapLevelBetweenSubBlocks],
      richText: RICH_TEXT_GAPS[gapLevelBetweenSubBlocks]
    };
  }

  function wrapBlockHTML(encodedContent, topGap) {
    var clearfix = '<div style="clear:both"></div>';
    var marginCSS = "margin: " + topGap + "px 0 0";
    return "<div style=\"" + marginCSS + ";" + TOOLTIP_LINE_HEIGHT_CSS + ";\">" + encodedContent + clearfix + '</div>';
  }

  function wrapInlineNameHTML(name, leftHasMarker) {
    var marginCss = leftHasMarker ? 'margin-left:2px' : '';
    return "<span style=\"" + TOOLTIP_NAME_TEXT_STYLE_CSS + ";" + marginCss + "\">" + encodeHTML(name) + '</span>';
  }

  function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker) {
    var paddingStr = valueCloseToMarker ? '10px' : '20px';
    var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : '';
    return "<span style=\"" + alignCSS + ";" + TOOLTIP_VALUE_TEXT_STYLE_CSS + "\">" + map(valueList, function (value) {
      return encodeHTML(value);
    }).join('&nbsp;&nbsp;') + '</span>';
  }

  function wrapInlineNameRichText(ctx, name) {
    return ctx.markupStyleCreator.wrapRichTextStyle(name, TOOLTIP_TEXT_STYLE_RICH);
  }

  function wrapInlineValueRichText(ctx, valueList, alignRight, valueCloseToMarker) {
    var styles = [TOOLTIP_VALUE_TEXT_STYLE_RICH];
    var paddingLeft = valueCloseToMarker ? 10 : 20;
    alignRight && styles.push({
      padding: [0, 0, 0, paddingLeft],
      align: 'right'
    });
    return ctx.markupStyleCreator.wrapRichTextStyle(valueList.join('  '), styles);
  }

  function retrieveVisualColorForTooltipMarker(series, dataIndex) {
    var style = series.getData().getItemVisual(dataIndex, 'style');
    var color = style[series.visualDrawType];
    return convertToColorString(color);
  }

  function getPaddingFromTooltipModel(model, renderMode) {
    var padding = model.get('padding');
    return padding != null ? padding : renderMode === 'richText' ? [8, 10] : 10;
  }

  var TooltipMarkupStyleCreator = function () {
    function TooltipMarkupStyleCreator() {
      this.richTextStyles = {};
      this._nextStyleNameId = getRandomIdBase();
    }

    TooltipMarkupStyleCreator.prototype._generateStyleName = function () {
      return '__EC_aUTo_' + this._nextStyleNameId++;
    };

    TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) {
      var markerId = renderMode === 'richText' ? this._generateStyleName() : null;
      var marker = getTooltipMarker({
        color: colorStr,
        type: markerType,
        renderMode: renderMode,
        markerId: markerId
      });

      if (isString(marker)) {
        return marker;
      } else {
        if (true) {
          assert(markerId);
        }

        this.richTextStyles[markerId] = marker.style;
        return marker.content;
      }
    };

    TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) {
      var finalStl = {};

      if (isArray(styles)) {
        each(styles, function (stl) {
          return extend(finalStl, stl);
        });
      } else {
        extend(finalStl, styles);
      }

      var styleName = this._generateStyleName();

      this.richTextStyles[styleName] = finalStl;
      return "{" + styleName + "|" + text + "}";
    };

    return TooltipMarkupStyleCreator;
  }();

  function defaultSeriesFormatTooltip(opt) {
    var series = opt.series;
    var dataIndex = opt.dataIndex;
    var multipleSeries = opt.multipleSeries;
    var data = series.getData();
    var tooltipDims = data.mapDimensionsAll('defaultedTooltip');
    var tooltipDimLen = tooltipDims.length;
    var value = series.getRawValue(dataIndex);
    var isValueArr = isArray(value);
    var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex);
    var inlineValue;
    var inlineValueType;
    var subBlocks;
    var sortParam;

    if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) {
      var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor);
      inlineValue = formatArrResult.inlineValues;
      inlineValueType = formatArrResult.inlineValueTypes;
      subBlocks = formatArrResult.blocks;
      sortParam = formatArrResult.inlineValues[0];
    } else if (tooltipDimLen) {
      var dimInfo = data.getDimensionInfo(tooltipDims[0]);
      sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]);
      inlineValueType = dimInfo.type;
    } else {
      sortParam = inlineValue = isValueArr ? value[0] : value;
    }

    var seriesNameSpecified = isNameSpecified(series);
    var seriesName = seriesNameSpecified && series.name || '';
    var itemName = data.getName(dataIndex);
    var inlineName = multipleSeries ? seriesName : itemName;
    return createTooltipMarkup('section', {
      header: seriesName,
      noHeader: multipleSeries || !seriesNameSpecified,
      sortParam: sortParam,
      blocks: [createTooltipMarkup('nameValue', {
        markerType: 'item',
        markerColor: markerColor,
        name: inlineName,
        noName: !trim(inlineName),
        value: inlineValue,
        valueType: inlineValueType
      })].concat(subBlocks || [])
    });
  }

  function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) {
    var data = series.getData();
    var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) {
      var dimItem = data.getDimensionInfo(idx);
      return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null;
    }, false);
    var inlineValues = [];
    var inlineValueTypes = [];
    var blocks = [];
    tooltipDims.length ? each(tooltipDims, function (dim) {
      setEachItem(retrieveRawValue(data, dataIndex, dim), dim);
    }) : each(value, setEachItem);

    function setEachItem(val, dim) {
      var dimInfo = data.getDimensionInfo(dim);

      if (!dimInfo || dimInfo.otherDims.tooltip === false) {
        return;
      }

      if (isValueMultipleLine) {
        blocks.push(createTooltipMarkup('nameValue', {
          markerType: 'subItem',
          markerColor: colorStr,
          name: dimInfo.displayName,
          value: val,
          valueType: dimInfo.type
        }));
      } else {
        inlineValues.push(val);
        inlineValueTypes.push(dimInfo.type);
      }
    }

    return {
      inlineValues: inlineValues,
      inlineValueTypes: inlineValueTypes,
      blocks: blocks
    };
  }

  var inner$1 = makeInner();

  function getSelectionKey(data, dataIndex) {
    return data.getName(dataIndex) || data.getId(dataIndex);
  }

  var SeriesModel = function (_super) {
    __extends(SeriesModel, _super);

    function SeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this._selectedDataIndicesMap = {};
      return _this;
    }

    SeriesModel.prototype.init = function (option, parentModel, ecModel) {
      this.seriesIndex = this.componentIndex;
      this.dataTask = createTask({
        count: dataTaskCount,
        reset: dataTaskReset
      });
      this.dataTask.context = {
        model: this
      };
      this.mergeDefaultAndTheme(option, ecModel);
      var sourceManager = inner$1(this).sourceManager = new SourceManager(this);
      sourceManager.prepareSource();
      var data = this.getInitialData(option, ecModel);
      wrapData(data, this);
      this.dataTask.context.data = data;

      if (true) {
        assert(data, 'getInitialData returned invalid data.');
      }

      inner$1(this).dataBeforeProcessed = data;
      autoSeriesName(this);

      this._initSelectedMapFromData(data);
    };

    SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
      var layoutMode = fetchLayoutMode(this);
      var inputPositionParams = layoutMode ? getLayoutParams(option) : {};
      var themeSubType = this.subType;

      if (ComponentModel.hasClass(themeSubType)) {
        themeSubType += 'Series';
      }

      merge(option, ecModel.getTheme().get(this.subType));
      merge(option, this.getDefaultOption());
      defaultEmphasis(option, 'label', ['show']);
      this.fillDataTextStyle(option.data);

      if (layoutMode) {
        mergeLayoutParam(option, inputPositionParams, layoutMode);
      }
    };

    SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) {
      newSeriesOption = merge(this.option, newSeriesOption, true);
      this.fillDataTextStyle(newSeriesOption.data);
      var layoutMode = fetchLayoutMode(this);

      if (layoutMode) {
        mergeLayoutParam(this.option, newSeriesOption, layoutMode);
      }

      var sourceManager = inner$1(this).sourceManager;
      sourceManager.dirty();
      sourceManager.prepareSource();
      var data = this.getInitialData(newSeriesOption, ecModel);
      wrapData(data, this);
      this.dataTask.dirty();
      this.dataTask.context.data = data;
      inner$1(this).dataBeforeProcessed = data;
      autoSeriesName(this);

      this._initSelectedMapFromData(data);
    };

    SeriesModel.prototype.fillDataTextStyle = function (data) {
      if (data && !isTypedArray(data)) {
        var props = ['show'];

        for (var i = 0; i < data.length; i++) {
          if (data[i] && data[i].label) {
            defaultEmphasis(data[i], 'label', props);
          }
        }
      }
    };

    SeriesModel.prototype.getInitialData = function (option, ecModel) {
      return;
    };

    SeriesModel.prototype.appendData = function (params) {
      var data = this.getRawData();
      data.appendData(params.data);
    };

    SeriesModel.prototype.getData = function (dataType) {
      var task = getCurrentTask(this);

      if (task) {
        var data = task.context.data;
        return dataType == null ? data : data.getLinkedData(dataType);
      } else {
        return inner$1(this).data;
      }
    };

    SeriesModel.prototype.getAllData = function () {
      var mainData = this.getData();
      return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{
        data: mainData
      }];
    };

    SeriesModel.prototype.setData = function (data) {
      var task = getCurrentTask(this);

      if (task) {
        var context = task.context;
        context.outputData = data;

        if (task !== this.dataTask) {
          context.data = data;
        }
      }

      inner$1(this).data = data;
    };

    SeriesModel.prototype.getSource = function () {
      return inner$1(this).sourceManager.getSource();
    };

    SeriesModel.prototype.getRawData = function () {
      return inner$1(this).dataBeforeProcessed;
    };

    SeriesModel.prototype.getBaseAxis = function () {
      var coordSys = this.coordinateSystem;
      return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
    };

    SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      return defaultSeriesFormatTooltip({
        series: this,
        dataIndex: dataIndex,
        multipleSeries: multipleSeries
      });
    };

    SeriesModel.prototype.isAnimationEnabled = function () {
      if (env.node) {
        return false;
      }

      var animationEnabled = this.getShallow('animation');

      if (animationEnabled) {
        if (this.getData().count() > this.getShallow('animationThreshold')) {
          animationEnabled = false;
        }
      }

      return !!animationEnabled;
    };

    SeriesModel.prototype.restoreData = function () {
      this.dataTask.dirty();
    };

    SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) {
      var ecModel = this.ecModel;
      var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum);

      if (!color) {
        color = ecModel.getColorFromPalette(name, scope, requestColorNum);
      }

      return color;
    };

    SeriesModel.prototype.coordDimToDataDim = function (coordDim) {
      return this.getRawData().mapDimensionsAll(coordDim);
    };

    SeriesModel.prototype.getProgressive = function () {
      return this.get('progressive');
    };

    SeriesModel.prototype.getProgressiveThreshold = function () {
      return this.get('progressiveThreshold');
    };

    SeriesModel.prototype.select = function (innerDataIndices, dataType) {
      this._innerSelect(this.getData(dataType), innerDataIndices);
    };

    SeriesModel.prototype.unselect = function (innerDataIndices, dataType) {
      var selectedMap = this.option.selectedMap;

      if (!selectedMap) {
        return;
      }

      var data = this.getData(dataType);

      for (var i = 0; i < innerDataIndices.length; i++) {
        var dataIndex = innerDataIndices[i];
        var nameOrId = getSelectionKey(data, dataIndex);
        selectedMap[nameOrId] = false;
        this._selectedDataIndicesMap[nameOrId] = -1;
      }
    };

    SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) {
      var tmpArr = [];

      for (var i = 0; i < innerDataIndices.length; i++) {
        tmpArr[0] = innerDataIndices[i];
        this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType);
      }
    };

    SeriesModel.prototype.getSelectedDataIndices = function () {
      var selectedDataIndicesMap = this._selectedDataIndicesMap;
      var nameOrIds = keys(selectedDataIndicesMap);
      var dataIndices = [];

      for (var i = 0; i < nameOrIds.length; i++) {
        var dataIndex = selectedDataIndicesMap[nameOrIds[i]];

        if (dataIndex >= 0) {
          dataIndices.push(dataIndex);
        }
      }

      return dataIndices;
    };

    SeriesModel.prototype.isSelected = function (dataIndex, dataType) {
      var selectedMap = this.option.selectedMap;

      if (!selectedMap) {
        return false;
      }

      var data = this.getData(dataType);
      var nameOrId = getSelectionKey(data, dataIndex);
      return selectedMap[nameOrId] || false;
    };

    SeriesModel.prototype._innerSelect = function (data, innerDataIndices) {
      var _a, _b;

      var selectedMode = this.option.selectedMode;
      var len = innerDataIndices.length;

      if (!selectedMode || !len) {
        return;
      }

      if (selectedMode === 'multiple') {
        var selectedMap = this.option.selectedMap || (this.option.selectedMap = {});

        for (var i = 0; i < len; i++) {
          var dataIndex = innerDataIndices[i];
          var nameOrId = getSelectionKey(data, dataIndex);
          selectedMap[nameOrId] = true;
          this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex);
        }
      } else if (selectedMode === 'single' || selectedMode === true) {
        var lastDataIndex = innerDataIndices[len - 1];
        var nameOrId = getSelectionKey(data, lastDataIndex);
        this.option.selectedMap = (_a = {}, _a[nameOrId] = true, _a);
        this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b);
      }
    };

    SeriesModel.prototype._initSelectedMapFromData = function (data) {
      if (this.option.selectedMap) {
        return;
      }

      var dataIndices = [];

      if (data.hasItemOption) {
        data.each(function (idx) {
          var rawItem = data.getRawDataItem(idx);

          if (typeof rawItem === 'object' && rawItem.selected) {
            dataIndices.push(idx);
          }
        });
      }

      if (dataIndices.length > 0) {
        this._innerSelect(data, dataIndices);
      }
    };

    SeriesModel.registerClass = function (clz) {
      return ComponentModel.registerClass(clz);
    };

    SeriesModel.protoInitialize = function () {
      var proto = SeriesModel.prototype;
      proto.type = 'series.__base__';
      proto.seriesIndex = 0;
      proto.useColorPaletteOnData = false;
      proto.ignoreStyleOnData = false;
      proto.hasSymbolVisual = false;
      proto.defaultSymbol = 'circle';
      proto.visualStyleAccessPath = 'itemStyle';
      proto.visualDrawType = 'fill';
    }();

    return SeriesModel;
  }(ComponentModel);

  mixin(SeriesModel, DataFormatMixin);
  mixin(SeriesModel, PaletteMixin);
  mountExtend(SeriesModel, ComponentModel);

  function autoSeriesName(seriesModel) {
    var name = seriesModel.name;

    if (!isNameSpecified(seriesModel)) {
      seriesModel.name = getSeriesAutoName(seriesModel) || name;
    }
  }

  function getSeriesAutoName(seriesModel) {
    var data = seriesModel.getRawData();
    var dataDims = data.mapDimensionsAll('seriesName');
    var nameArr = [];
    each(dataDims, function (dataDim) {
      var dimInfo = data.getDimensionInfo(dataDim);
      dimInfo.displayName && nameArr.push(dimInfo.displayName);
    });
    return nameArr.join(' ');
  }

  function dataTaskCount(context) {
    return context.model.getRawData().count();
  }

  function dataTaskReset(context) {
    var seriesModel = context.model;
    seriesModel.setData(seriesModel.getRawData().cloneShallow());
    return dataTaskProgress;
  }

  function dataTaskProgress(param, context) {
    if (context.outputData && param.end > context.outputData.count()) {
      context.model.getRawData().cloneShallow(context.outputData);
    }
  }

  function wrapData(data, seriesModel) {
    each(__spreadArrays(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) {
      data.wrapMethod(methodName, curry(onDataChange, seriesModel));
    });
  }

  function onDataChange(seriesModel, newList) {
    var task = getCurrentTask(seriesModel);

    if (task) {
      task.setOutputEnd((newList || this).count());
    }

    return newList;
  }

  function getCurrentTask(seriesModel) {
    var scheduler = (seriesModel.ecModel || {}).scheduler;
    var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid);

    if (pipeline) {
      var task = pipeline.currentTask;

      if (task) {
        var agentStubMap = task.agentStubMap;

        if (agentStubMap) {
          task = agentStubMap.get(seriesModel.uid);
        }
      }

      return task;
    }
  }

  var ComponentView = function () {
    function ComponentView() {
      this.group = new Group();
      this.uid = getUID('viewComponent');
    }

    ComponentView.prototype.init = function (ecModel, api) {};

    ComponentView.prototype.render = function (model, ecModel, api, payload) {};

    ComponentView.prototype.dispose = function (ecModel, api) {};

    ComponentView.prototype.updateView = function (model, ecModel, api, payload) {};

    ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {};

    ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {};

    ComponentView.prototype.blurSeries = function (seriesModels, ecModel) {};

    return ComponentView;
  }();

  enableClassExtend(ComponentView);
  enableClassManagement(ComponentView, {
    registerWhenExtend: true
  });

  function createRenderPlanner() {
    var inner = makeInner();
    return function (seriesModel) {
      var fields = inner(seriesModel);
      var pipelineContext = seriesModel.pipelineContext;
      var originalLarge = !!fields.large;
      var originalProgressive = !!fields.progressiveRender;
      var large = fields.large = !!(pipelineContext && pipelineContext.large);
      var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender);
      return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset';
    };
  }

  var inner$2 = makeInner();
  var renderPlanner = createRenderPlanner();

  var ChartView = function () {
    function ChartView() {
      this.group = new Group();
      this.uid = getUID('viewChart');
      this.renderTask = createTask({
        plan: renderTaskPlan,
        reset: renderTaskReset
      });
      this.renderTask.context = {
        view: this
      };
    }

    ChartView.prototype.init = function (ecModel, api) {};

    ChartView.prototype.render = function (seriesModel, ecModel, api, payload) {};

    ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) {
      toggleHighlight(seriesModel.getData(), payload, 'emphasis');
    };

    ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) {
      toggleHighlight(seriesModel.getData(), payload, 'normal');
    };

    ChartView.prototype.remove = function (ecModel, api) {
      this.group.removeAll();
    };

    ChartView.prototype.dispose = function (ecModel, api) {};

    ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) {
      this.render(seriesModel, ecModel, api, payload);
    };

    ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) {
      this.render(seriesModel, ecModel, api, payload);
    };

    ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) {
      this.render(seriesModel, ecModel, api, payload);
    };

    ChartView.markUpdateMethod = function (payload, methodName) {
      inner$2(payload).updateMethod = methodName;
    };

    ChartView.protoInitialize = function () {
      var proto = ChartView.prototype;
      proto.type = 'chart';
    }();

    return ChartView;
  }();

  function elSetState(el, state, highlightDigit) {
    if (el) {
      (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit);
    }
  }

  function toggleHighlight(data, payload, state) {
    var dataIndex = queryDataIndex(data, payload);
    var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null;

    if (dataIndex != null) {
      each(normalizeToArray(dataIndex), function (dataIdx) {
        elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit);
      });
    } else {
      data.eachItemGraphicEl(function (el) {
        elSetState(el, state, highlightDigit);
      });
    }
  }

  enableClassExtend(ChartView, ['dispose']);
  enableClassManagement(ChartView, {
    registerWhenExtend: true
  });

  function renderTaskPlan(context) {
    return renderPlanner(context.model);
  }

  function renderTaskReset(context) {
    var seriesModel = context.model;
    var ecModel = context.ecModel;
    var api = context.api;
    var payload = context.payload;
    var progressiveRender = seriesModel.pipelineContext.progressiveRender;
    var view = context.view;
    var updateMethod = payload && inner$2(payload).updateMethod;
    var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod : 'render';

    if (methodName !== 'render') {
      view[methodName](seriesModel, ecModel, api, payload);
    }

    return progressMethodMap[methodName];
  }

  var progressMethodMap = {
    incrementalPrepareRender: {
      progress: function (params, context) {
        context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload);
      }
    },
    render: {
      forceFirstProgress: true,
      progress: function (params, context) {
        context.view.render(context.model, context.ecModel, context.api, context.payload);
      }
    }
  };
  var ORIGIN_METHOD = '\0__throttleOriginMethod';
  var RATE = '\0__throttleRate';
  var THROTTLE_TYPE = '\0__throttleType';

  function throttle(fn, delay, debounce) {
    var currCall;
    var lastCall = 0;
    var lastExec = 0;
    var timer = null;
    var diff;
    var scope;
    var args;
    var debounceNextCall;
    delay = delay || 0;

    function exec() {
      lastExec = new Date().getTime();
      timer = null;
      fn.apply(scope, args || []);
    }

    var cb = function () {
      var cbArgs = [];

      for (var _i = 0; _i < arguments.length; _i++) {
        cbArgs[_i] = arguments[_i];
      }

      currCall = new Date().getTime();
      scope = this;
      args = cbArgs;
      var thisDelay = debounceNextCall || delay;
      var thisDebounce = debounceNextCall || debounce;
      debounceNextCall = null;
      diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;
      clearTimeout(timer);

      if (thisDebounce) {
        timer = setTimeout(exec, thisDelay);
      } else {
        if (diff >= 0) {
          exec();
        } else {
          timer = setTimeout(exec, -diff);
        }
      }

      lastCall = currCall;
    };

    cb.clear = function () {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
    };

    cb.debounceNextCall = function (debounceDelay) {
      debounceNextCall = debounceDelay;
    };

    return cb;
  }

  function createOrUpdate(obj, fnAttr, rate, throttleType) {
    var fn = obj[fnAttr];

    if (!fn) {
      return;
    }

    var originFn = fn[ORIGIN_METHOD] || fn;
    var lastThrottleType = fn[THROTTLE_TYPE];
    var lastRate = fn[RATE];

    if (lastRate !== rate || lastThrottleType !== throttleType) {
      if (rate == null || !throttleType) {
        return obj[fnAttr] = originFn;
      }

      fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce');
      fn[ORIGIN_METHOD] = originFn;
      fn[THROTTLE_TYPE] = throttleType;
      fn[RATE] = rate;
    }

    return fn;
  }

  function clear(obj, fnAttr) {
    var fn = obj[fnAttr];

    if (fn && fn[ORIGIN_METHOD]) {
      obj[fnAttr] = fn[ORIGIN_METHOD];
    }
  }

  var inner$3 = makeInner();
  var defaultStyleMappers = {
    itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true),
    lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true)
  };
  var defaultColorKey = {
    lineStyle: 'stroke',
    itemStyle: 'fill'
  };

  function getStyleMapper(seriesModel, stylePath) {
    var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath];

    if (!styleMapper) {
      console.warn("Unkown style type '" + stylePath + "'.");
      return defaultStyleMappers.itemStyle;
    }

    return styleMapper;
  }

  function getDefaultColorKey(seriesModel, stylePath) {
    var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath];

    if (!colorKey) {
      console.warn("Unkown style type '" + stylePath + "'.");
      return 'fill';
    }

    return colorKey;
  }

  var seriesStyleTask = {
    createOnAllSeries: true,
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
      var data = seriesModel.getData();
      var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle';
      var styleModel = seriesModel.getModel(stylePath);
      var getStyle = getStyleMapper(seriesModel, stylePath);
      var globalStyle = getStyle(styleModel);
      var decalOption = styleModel.getShallow('decal');

      if (decalOption) {
        data.setVisual('decal', decalOption);
        decalOption.dirty = true;
      }

      var colorKey = getDefaultColorKey(seriesModel, stylePath);
      var color = globalStyle[colorKey];
      var colorCallback = isFunction(color) ? color : null;

      if (!globalStyle[colorKey] || colorCallback) {
        globalStyle[colorKey] = seriesModel.getColorFromPalette(seriesModel.name, null, ecModel.getSeriesCount());
        data.setVisual('colorFromPalette', true);
      }

      data.setVisual('style', globalStyle);
      data.setVisual('drawType', colorKey);

      if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) {
        data.setVisual('colorFromPalette', false);
        return {
          dataEach: function (data, idx) {
            var dataParams = seriesModel.getDataParams(idx);
            var itemStyle = extend({}, globalStyle);
            itemStyle[colorKey] = colorCallback(dataParams);
            data.setItemVisual(idx, 'style', itemStyle);
          }
        };
      }
    }
  };
  var sharedModel = new Model();
  var dataStyleTask = {
    createOnAllSeries: true,
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
      if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      var data = seriesModel.getData();
      var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle';
      var getStyle = getStyleMapper(seriesModel, stylePath);
      var colorKey = data.getVisual('drawType');
      return {
        dataEach: data.hasItemOption ? function (data, idx) {
          var rawItem = data.getRawDataItem(idx);

          if (rawItem && rawItem[stylePath]) {
            sharedModel.option = rawItem[stylePath];
            var style = getStyle(sharedModel);
            var existsStyle = data.ensureUniqueItemVisual(idx, 'style');
            extend(existsStyle, style);

            if (sharedModel.option.decal) {
              data.setItemVisual(idx, 'decal', sharedModel.option.decal);
              sharedModel.option.decal.dirty = true;
            }

            if (colorKey in style) {
              data.setItemVisual(idx, 'colorFromPalette', false);
            }
          }
        } : null
      };
    }
  };
  var dataColorPaletteTask = {
    performRawSeries: true,
    overallReset: function (ecModel) {
      var paletteScopeGroupByType = createHashMap();
      ecModel.eachSeries(function (seriesModel) {
        if (!seriesModel.useColorPaletteOnData) {
          return;
        }

        var colorScope = paletteScopeGroupByType.get(seriesModel.type);

        if (!colorScope) {
          colorScope = {};
          paletteScopeGroupByType.set(seriesModel.type, colorScope);
        }

        inner$3(seriesModel).scope = colorScope;
      });
      ecModel.eachSeries(function (seriesModel) {
        if (!seriesModel.useColorPaletteOnData || ecModel.isSeriesFiltered(seriesModel)) {
          return;
        }

        var dataAll = seriesModel.getRawData();
        var idxMap = {};
        var data = seriesModel.getData();
        var colorScope = inner$3(seriesModel).scope;
        var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle';
        var colorKey = getDefaultColorKey(seriesModel, stylePath);
        data.each(function (idx) {
          var rawIdx = data.getRawIndex(idx);
          idxMap[rawIdx] = idx;
        });
        dataAll.each(function (rawIdx) {
          var idx = idxMap[rawIdx];
          var fromPalette = data.getItemVisual(idx, 'colorFromPalette');

          if (fromPalette) {
            var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
            var name_1 = dataAll.getName(rawIdx) || rawIdx + '';
            var dataCount = dataAll.count();
            itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount);
          }
        });
      });
    }
  };
  var PI$5 = Math.PI;

  function defaultLoading(api, opts) {
    opts = opts || {};
    defaults(opts, {
      text: 'loading',
      textColor: '#000',
      fontSize: '12px',
      maskColor: 'rgba(255, 255, 255, 0.8)',
      showSpinner: true,
      color: '#5470c6',
      spinnerRadius: 10,
      lineWidth: 5,
      zlevel: 0
    });
    var group = new Group();
    var mask = new Rect({
      style: {
        fill: opts.maskColor
      },
      zlevel: opts.zlevel,
      z: 10000
    });
    group.add(mask);
    var font = opts.fontSize + ' sans-serif';
    var labelRect = new Rect({
      style: {
        fill: 'none'
      },
      textContent: new ZRText({
        style: {
          text: opts.text,
          fill: opts.textColor,
          font: font
        }
      }),
      textConfig: {
        position: 'right',
        distance: 10
      },
      zlevel: opts.zlevel,
      z: 10001
    });
    group.add(labelRect);
    var arc;

    if (opts.showSpinner) {
      arc = new Arc({
        shape: {
          startAngle: -PI$5 / 2,
          endAngle: -PI$5 / 2 + 0.1,
          r: opts.spinnerRadius
        },
        style: {
          stroke: opts.color,
          lineCap: 'round',
          lineWidth: opts.lineWidth
        },
        zlevel: opts.zlevel,
        z: 10001
      });
      arc.animateShape(true).when(1000, {
        endAngle: PI$5 * 3 / 2
      }).start('circularInOut');
      arc.animateShape(true).when(1000, {
        startAngle: PI$5 * 3 / 2
      }).delay(300).start('circularInOut');
      group.add(arc);
    }

    group.resize = function () {
      var textWidth = getWidth(opts.text, font);
      var r = opts.showSpinner ? opts.spinnerRadius : 0;
      var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner ? 0 : textWidth / 2);
      var cy = api.getHeight() / 2;
      opts.showSpinner && arc.setShape({
        cx: cx,
        cy: cy
      });
      labelRect.setShape({
        x: cx - r,
        y: cy - r,
        width: r * 2,
        height: r * 2
      });
      mask.setShape({
        x: 0,
        y: 0,
        width: api.getWidth(),
        height: api.getHeight()
      });
    };

    group.resize();
    return group;
  }

  var Scheduler = function () {
    function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) {
      this._stageTaskMap = createHashMap();
      this.ecInstance = ecInstance;
      this.api = api;
      dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice();
      visualHandlers = this._visualHandlers = visualHandlers.slice();
      this._allHandlers = dataProcessorHandlers.concat(visualHandlers);
    }

    Scheduler.prototype.restoreData = function (ecModel, payload) {
      ecModel.restoreData(payload);

      this._stageTaskMap.each(function (taskRecord) {
        var overallTask = taskRecord.overallTask;
        overallTask && overallTask.dirty();
      });
    };

    Scheduler.prototype.getPerformArgs = function (task, isBlock) {
      if (!task.__pipeline) {
        return;
      }

      var pipeline = this._pipelineMap.get(task.__pipeline.id);

      var pCtx = pipeline.context;
      var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex;
      var step = incremental ? pipeline.step : null;
      var modDataCount = pCtx && pCtx.modDataCount;
      var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null;
      return {
        step: step,
        modBy: modBy,
        modDataCount: modDataCount
      };
    };

    Scheduler.prototype.getPipeline = function (pipelineId) {
      return this._pipelineMap.get(pipelineId);
    };

    Scheduler.prototype.updateStreamModes = function (seriesModel, view) {
      var pipeline = this._pipelineMap.get(seriesModel.uid);

      var data = seriesModel.getData();
      var dataLen = data.count();
      var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold;
      var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold');
      var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null;
      seriesModel.pipelineContext = pipeline.context = {
        progressiveRender: progressiveRender,
        modDataCount: modDataCount,
        large: large
      };
    };

    Scheduler.prototype.restorePipelines = function (ecModel) {
      var scheduler = this;
      var pipelineMap = scheduler._pipelineMap = createHashMap();
      ecModel.eachSeries(function (seriesModel) {
        var progressive = seriesModel.getProgressive();
        var pipelineId = seriesModel.uid;
        pipelineMap.set(pipelineId, {
          id: pipelineId,
          head: null,
          tail: null,
          threshold: seriesModel.getProgressiveThreshold(),
          progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()),
          blockIndex: -1,
          step: Math.round(progressive || 700),
          count: 0
        });

        scheduler._pipe(seriesModel, seriesModel.dataTask);
      });
    };

    Scheduler.prototype.prepareStageTasks = function () {
      var stageTaskMap = this._stageTaskMap;
      var ecModel = this.api.getModel();
      var api = this.api;
      each(this._allHandlers, function (handler) {
        var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {});
        var errMsg = '';

        if (true) {
          errMsg = '"reset" and "overallReset" must not be both specified.';
        }

        assert(!(handler.reset && handler.overallReset), errMsg);
        handler.reset && this._createSeriesStageTask(handler, record, ecModel, api);
        handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api);
      }, this);
    };

    Scheduler.prototype.prepareView = function (view, model, ecModel, api) {
      var renderTask = view.renderTask;
      var context = renderTask.context;
      context.model = model;
      context.ecModel = ecModel;
      context.api = api;
      renderTask.__block = !view.incrementalPrepareRender;

      this._pipe(model, renderTask);
    };

    Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) {
      this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, {
        block: true
      });
    };

    Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) {
      this._performStageTasks(this._visualHandlers, ecModel, payload, opt);
    };

    Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) {
      opt = opt || {};
      var unfinished = false;
      var scheduler = this;
      each(stageHandlers, function (stageHandler, idx) {
        if (opt.visualType && opt.visualType !== stageHandler.visualType) {
          return;
        }

        var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid);

        var seriesTaskMap = stageHandlerRecord.seriesTaskMap;
        var overallTask = stageHandlerRecord.overallTask;

        if (overallTask) {
          var overallNeedDirty_1;
          var agentStubMap = overallTask.agentStubMap;
          agentStubMap.each(function (stub) {
            if (needSetDirty(opt, stub)) {
              stub.dirty();
              overallNeedDirty_1 = true;
            }
          });
          overallNeedDirty_1 && overallTask.dirty();
          scheduler.updatePayload(overallTask, payload);
          var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block);
          agentStubMap.each(function (stub) {
            stub.perform(performArgs_1);
          });

          if (overallTask.perform(performArgs_1)) {
            unfinished = true;
          }
        } else if (seriesTaskMap) {
          seriesTaskMap.each(function (task, pipelineId) {
            if (needSetDirty(opt, task)) {
              task.dirty();
            }

            var performArgs = scheduler.getPerformArgs(task, opt.block);
            performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model);
            scheduler.updatePayload(task, payload);

            if (task.perform(performArgs)) {
              unfinished = true;
            }
          });
        }
      });

      function needSetDirty(opt, task) {
        return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id));
      }

      this.unfinished = unfinished || this.unfinished;
    };

    Scheduler.prototype.performSeriesTasks = function (ecModel) {
      var unfinished;
      ecModel.eachSeries(function (seriesModel) {
        unfinished = seriesModel.dataTask.perform() || unfinished;
      });
      this.unfinished = unfinished || this.unfinished;
    };

    Scheduler.prototype.plan = function () {
      this._pipelineMap.each(function (pipeline) {
        var task = pipeline.tail;

        do {
          if (task.__block) {
            pipeline.blockIndex = task.__idxInPipeline;
            break;
          }

          task = task.getUpstream();
        } while (task);
      });
    };

    Scheduler.prototype.updatePayload = function (task, payload) {
      payload !== 'remain' && (task.context.payload = payload);
    };

    Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
      var scheduler = this;
      var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap;
      var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap();
      var seriesType = stageHandler.seriesType;
      var getTargetSeries = stageHandler.getTargetSeries;

      if (stageHandler.createOnAllSeries) {
        ecModel.eachRawSeries(create);
      } else if (seriesType) {
        ecModel.eachRawSeriesByType(seriesType, create);
      } else if (getTargetSeries) {
        getTargetSeries(ecModel, api).each(create);
      }

      function create(seriesModel) {
        var pipelineId = seriesModel.uid;
        var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({
          plan: seriesTaskPlan,
          reset: seriesTaskReset,
          count: seriesTaskCount
        }));
        task.context = {
          model: seriesModel,
          ecModel: ecModel,
          api: api,
          useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
          plan: stageHandler.plan,
          reset: stageHandler.reset,
          scheduler: scheduler
        };

        scheduler._pipe(seriesModel, task);
      }
    };

    Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
      var scheduler = this;
      var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask || createTask({
        reset: overallTaskReset
      });
      overallTask.context = {
        ecModel: ecModel,
        api: api,
        overallReset: stageHandler.overallReset,
        scheduler: scheduler
      };
      var oldAgentStubMap = overallTask.agentStubMap;
      var newAgentStubMap = overallTask.agentStubMap = createHashMap();
      var seriesType = stageHandler.seriesType;
      var getTargetSeries = stageHandler.getTargetSeries;
      var overallProgress = true;
      var shouldOverallTaskDirty = false;
      var errMsg = '';

      if (true) {
        errMsg = '"createOnAllSeries" do not supported for "overallReset", ' + 'becuase it will block all streams.';
      }

      assert(!stageHandler.createOnAllSeries, errMsg);

      if (seriesType) {
        ecModel.eachRawSeriesByType(seriesType, createStub);
      } else if (getTargetSeries) {
        getTargetSeries(ecModel, api).each(createStub);
      } else {
        overallProgress = false;
        each(ecModel.getSeries(), createStub);
      }

      function createStub(seriesModel) {
        var pipelineId = seriesModel.uid;
        var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || (shouldOverallTaskDirty = true, createTask({
          reset: stubReset,
          onDirty: stubOnDirty
        })));
        stub.context = {
          model: seriesModel,
          overallProgress: overallProgress
        };
        stub.agent = overallTask;
        stub.__block = overallProgress;

        scheduler._pipe(seriesModel, stub);
      }

      if (shouldOverallTaskDirty) {
        overallTask.dirty();
      }
    };

    Scheduler.prototype._pipe = function (seriesModel, task) {
      var pipelineId = seriesModel.uid;

      var pipeline = this._pipelineMap.get(pipelineId);

      !pipeline.head && (pipeline.head = task);
      pipeline.tail && pipeline.tail.pipe(task);
      pipeline.tail = task;
      task.__idxInPipeline = pipeline.count++;
      task.__pipeline = pipeline;
    };

    Scheduler.wrapStageHandler = function (stageHandler, visualType) {
      if (isFunction(stageHandler)) {
        stageHandler = {
          overallReset: stageHandler,
          seriesType: detectSeriseType(stageHandler)
        };
      }

      stageHandler.uid = getUID('stageHandler');
      visualType && (stageHandler.visualType = visualType);
      return stageHandler;
    };

    return Scheduler;
  }();

  function overallTaskReset(context) {
    context.overallReset(context.ecModel, context.api, context.payload);
  }

  function stubReset(context) {
    return context.overallProgress && stubProgress;
  }

  function stubProgress() {
    this.agent.dirty();
    this.getDownstream().dirty();
  }

  function stubOnDirty() {
    this.agent && this.agent.dirty();
  }

  function seriesTaskPlan(context) {
    return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null;
  }

  function seriesTaskReset(context) {
    if (context.useClearVisual) {
      context.data.clearAllVisual();
    }

    var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload));
    return resetDefines.length > 1 ? map(resetDefines, function (v, idx) {
      return makeSeriesTaskProgress(idx);
    }) : singleSeriesTaskProgress;
  }

  var singleSeriesTaskProgress = makeSeriesTaskProgress(0);

  function makeSeriesTaskProgress(resetDefineIdx) {
    return function (params, context) {
      var data = context.data;
      var resetDefine = context.resetDefines[resetDefineIdx];

      if (resetDefine && resetDefine.dataEach) {
        for (var i = params.start; i < params.end; i++) {
          resetDefine.dataEach(data, i);
        }
      } else if (resetDefine && resetDefine.progress) {
        resetDefine.progress(params, data);
      }
    };
  }

  function seriesTaskCount(context) {
    return context.data.count();
  }

  function detectSeriseType(legacyFunc) {
    seriesType = null;

    try {
      legacyFunc(ecModelMock, apiMock);
    } catch (e) {}

    return seriesType;
  }

  var ecModelMock = {};
  var apiMock = {};
  var seriesType;
  mockMethods(ecModelMock, GlobalModel);
  mockMethods(apiMock, ExtensionAPI);

  ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) {
    seriesType = type;
  };

  ecModelMock.eachComponent = function (cond) {
    if (cond.mainType === 'series' && cond.subType) {
      seriesType = cond.subType;
    }
  };

  function mockMethods(target, Clz) {
    for (var name_1 in Clz.prototype) {
      target[name_1] = noop;
    }
  }

  var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'];
  var lightTheme = {
    color: colorAll,
    colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll]
  };
  var contrastColor = '#B9B8CE';
  var backgroundColor = '#100C2A';

  var axisCommon = function () {
    return {
      axisLine: {
        lineStyle: {
          color: contrastColor
        }
      },
      splitLine: {
        lineStyle: {
          color: '#484753'
        }
      },
      splitArea: {
        areaStyle: {
          color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)']
        }
      },
      minorSplitLine: {
        lineStyle: {
          color: '#20203B'
        }
      }
    };
  };

  var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff'];
  var theme = {
    darkMode: true,
    color: colorPalette,
    backgroundColor: backgroundColor,
    axisPointer: {
      lineStyle: {
        color: '#817f91'
      },
      crossStyle: {
        color: '#817f91'
      },
      label: {
        color: '#fff'
      }
    },
    legend: {
      textStyle: {
        color: contrastColor
      }
    },
    textStyle: {
      color: contrastColor
    },
    title: {
      textStyle: {
        color: '#EEF1FA'
      },
      subtextStyle: {
        color: '#B9B8CE'
      }
    },
    toolbox: {
      iconStyle: {
        borderColor: contrastColor
      }
    },
    dataZoom: {
      borderColor: '#71708A',
      textStyle: {
        color: contrastColor
      },
      brushStyle: {
        color: 'rgba(135,163,206,0.3)'
      },
      handleStyle: {
        color: '#353450',
        borderColor: '#C5CBE3'
      },
      moveHandleStyle: {
        color: '#B0B6C3',
        opacity: 0.3
      },
      fillerColor: 'rgba(135,163,206,0.2)',
      emphasis: {
        handleStyle: {
          borderColor: '#91B7F2',
          color: '#4D587D'
        },
        moveHandleStyle: {
          color: '#636D9A',
          opacity: 0.7
        }
      },
      dataBackground: {
        lineStyle: {
          color: '#71708A',
          width: 1
        },
        areaStyle: {
          color: '#71708A'
        }
      },
      selectedDataBackground: {
        lineStyle: {
          color: '#87A3CE'
        },
        areaStyle: {
          color: '#87A3CE'
        }
      }
    },
    visualMap: {
      textStyle: {
        color: contrastColor
      }
    },
    timeline: {
      lineStyle: {
        color: contrastColor
      },
      label: {
        color: contrastColor
      },
      controlStyle: {
        color: contrastColor,
        borderColor: contrastColor
      }
    },
    calendar: {
      itemStyle: {
        color: backgroundColor
      },
      dayLabel: {
        color: contrastColor
      },
      monthLabel: {
        color: contrastColor
      },
      yearLabel: {
        color: contrastColor
      }
    },
    timeAxis: axisCommon(),
    logAxis: axisCommon(),
    valueAxis: axisCommon(),
    categoryAxis: axisCommon(),
    line: {
      symbol: 'circle'
    },
    graph: {
      color: colorPalette
    },
    gauge: {
      title: {
        color: contrastColor
      },
      axisLine: {
        lineStyle: {
          color: [[1, 'rgba(207,212,219,0.2)']]
        }
      },
      axisLabel: {
        color: contrastColor
      },
      detail: {
        color: '#EEF1FA'
      }
    },
    candlestick: {
      itemStyle: {
        color: '#FD1050',
        color0: '#0CF49B',
        borderColor: '#FD1050',
        borderColor0: '#0CF49B'
      }
    }
  };
  theme.categoryAxis.splitLine.show = false;

  var DatasetModel = function (_super) {
    __extends(DatasetModel, _super);

    function DatasetModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'dataset';
      return _this;
    }

    DatasetModel.prototype.init = function (option, parentModel, ecModel) {
      _super.prototype.init.call(this, option, parentModel, ecModel);

      this._sourceManager = new SourceManager(this);
      disableTransformOptionMerge(this);
    };

    DatasetModel.prototype.mergeOption = function (newOption, ecModel) {
      _super.prototype.mergeOption.call(this, newOption, ecModel);

      disableTransformOptionMerge(this);
    };

    DatasetModel.prototype.optionUpdated = function () {
      this._sourceManager.dirty();
    };

    DatasetModel.prototype.getSourceManager = function () {
      return this._sourceManager;
    };

    DatasetModel.type = 'dataset';
    DatasetModel.defaultOption = {
      seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN
    };
    return DatasetModel;
  }(ComponentModel);

  ComponentModel.registerClass(DatasetModel);

  var DatasetView = function (_super) {
    __extends(DatasetView, _super);

    function DatasetView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'dataset';
      return _this;
    }

    DatasetView.type = 'dataset';
    return DatasetView;
  }(ComponentView);

  ComponentView.registerClass(DatasetView);
  var storage = createHashMap();
  var mapDataStorage = {
    registerMap: function (mapName, rawDef, rawSpecialAreas) {
      var records;

      if (isArray(rawDef)) {
        records = rawDef;
      } else if (rawDef.svg) {
        records = [{
          type: 'svg',
          source: rawDef.svg,
          specialAreas: rawDef.specialAreas
        }];
      } else {
        var geoSource = rawDef.geoJson || rawDef.geoJSON;

        if (geoSource && !rawDef.features) {
          rawSpecialAreas = rawDef.specialAreas;
          rawDef = geoSource;
        }

        records = [{
          type: 'geoJSON',
          source: rawDef,
          specialAreas: rawSpecialAreas
        }];
      }

      each(records, function (record) {
        var type = record.type;
        type === 'geoJson' && (type = record.type = 'geoJSON');
        var parse = parsers[type];

        if (true) {
          assert(parse, 'Illegal map type: ' + type);
        }

        parse(record);
      });
      return storage.set(mapName, records);
    },
    retrieveMap: function (mapName) {
      return storage.get(mapName);
    }
  };
  var parsers = {
    geoJSON: function (record) {
      var source = record.source;
      record.geoJSON = !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')();
    },
    svg: function (record) {
      record.svgXML = parseXML(record.source);
    }
  };

  var ECEventProcessor = function () {
    function ECEventProcessor() {}

    ECEventProcessor.prototype.normalizeQuery = function (query) {
      var cptQuery = {};
      var dataQuery = {};
      var otherQuery = {};

      if (isString(query)) {
        var condCptType = parseClassType(query);
        cptQuery.mainType = condCptType.main || null;
        cptQuery.subType = condCptType.sub || null;
      } else {
        var suffixes_1 = ['Index', 'Name', 'Id'];
        var dataKeys_1 = {
          name: 1,
          dataIndex: 1,
          dataType: 1
        };
        each(query, function (val, key) {
          var reserved = false;

          for (var i = 0; i < suffixes_1.length; i++) {
            var propSuffix = suffixes_1[i];
            var suffixPos = key.lastIndexOf(propSuffix);

            if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) {
              var mainType = key.slice(0, suffixPos);

              if (mainType !== 'data') {
                cptQuery.mainType = mainType;
                cptQuery[propSuffix.toLowerCase()] = val;
                reserved = true;
              }
            }
          }

          if (dataKeys_1.hasOwnProperty(key)) {
            dataQuery[key] = val;
            reserved = true;
          }

          if (!reserved) {
            otherQuery[key] = val;
          }
        });
      }

      return {
        cptQuery: cptQuery,
        dataQuery: dataQuery,
        otherQuery: otherQuery
      };
    };

    ECEventProcessor.prototype.filter = function (eventType, query) {
      var eventInfo = this.eventInfo;

      if (!eventInfo) {
        return true;
      }

      var targetEl = eventInfo.targetEl;
      var packedEvent = eventInfo.packedEvent;
      var model = eventInfo.model;
      var view = eventInfo.view;

      if (!model || !view) {
        return true;
      }

      var cptQuery = query.cptQuery;
      var dataQuery = query.dataQuery;
      return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent));

      function check(query, host, prop, propOnHost) {
        return query[prop] == null || host[propOnHost || prop] === query[prop];
      }
    };

    ECEventProcessor.prototype.afterTrigger = function () {
      this.eventInfo = null;
    };

    return ECEventProcessor;
  }();

  var seriesSymbolTask = {
    createOnAllSeries: true,
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
      var data = seriesModel.getData();

      if (seriesModel.legendSymbol) {
        data.setVisual('legendSymbol', seriesModel.legendSymbol);
      }

      if (!seriesModel.hasSymbolVisual) {
        return;
      }

      var symbolType = seriesModel.get('symbol');
      var symbolSize = seriesModel.get('symbolSize');
      var keepAspect = seriesModel.get('symbolKeepAspect');
      var symbolRotate = seriesModel.get('symbolRotate');
      var hasSymbolTypeCallback = isFunction(symbolType);
      var hasSymbolSizeCallback = isFunction(symbolSize);
      var hasSymbolRotateCallback = isFunction(symbolRotate);
      var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback;
      var seriesSymbol = !hasSymbolTypeCallback && symbolType ? symbolType : seriesModel.defaultSymbol;
      var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;
      var seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null;
      data.setVisual({
        legendSymbol: seriesModel.legendSymbol || seriesSymbol,
        symbol: seriesSymbol,
        symbolSize: seriesSymbolSize,
        symbolKeepAspect: keepAspect,
        symbolRotate: seriesSymbolRotate
      });

      if (ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      function dataEach(data, idx) {
        var rawValue = seriesModel.getRawValue(idx);
        var params = seriesModel.getDataParams(idx);
        hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params));
        hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
        hasSymbolRotateCallback && data.setItemVisual(idx, 'symbolRotate', symbolRotate(rawValue, params));
      }

      return {
        dataEach: hasCallback ? dataEach : null
      };
    }
  };
  var dataSymbolTask = {
    createOnAllSeries: true,
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
      if (!seriesModel.hasSymbolVisual) {
        return;
      }

      if (ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      var data = seriesModel.getData();

      function dataEach(data, idx) {
        var itemModel = data.getItemModel(idx);
        var itemSymbolType = itemModel.getShallow('symbol', true);
        var itemSymbolSize = itemModel.getShallow('symbolSize', true);
        var itemSymbolRotate = itemModel.getShallow('symbolRotate', true);
        var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true);

        if (itemSymbolType != null) {
          data.setItemVisual(idx, 'symbol', itemSymbolType);
        }

        if (itemSymbolSize != null) {
          data.setItemVisual(idx, 'symbolSize', itemSymbolSize);
        }

        if (itemSymbolRotate != null) {
          data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate);
        }

        if (itemSymbolKeepAspect != null) {
          data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
        }
      }

      return {
        dataEach: data.hasItemOption ? dataEach : null
      };
    }
  };

  function getItemVisualFromData(data, dataIndex, key) {
    switch (key) {
      case 'color':
        var style = data.getItemVisual(dataIndex, 'style');
        return style[data.getVisual('drawType')];

      case 'opacity':
        return data.getItemVisual(dataIndex, 'style').opacity;

      case 'symbol':
      case 'symbolSize':
      case 'liftZ':
        return data.getItemVisual(dataIndex, key);

      default:
        if (true) {
          console.warn("Unknown visual type " + key);
        }

    }
  }

  function getVisualFromData(data, key) {
    switch (key) {
      case 'color':
        var style = data.getVisual('style');
        return style[data.getVisual('drawType')];

      case 'opacity':
        return data.getVisual('style').opacity;

      case 'symbol':
      case 'symbolSize':
      case 'liftZ':
        return data.getVisual(key);

      default:
        if (true) {
          console.warn("Unknown visual type " + key);
        }

    }
  }

  function setItemVisualFromData(data, dataIndex, key, value) {
    switch (key) {
      case 'color':
        var style = data.ensureUniqueItemVisual(dataIndex, 'style');
        style[data.getVisual('drawType')] = value;
        data.setItemVisual(dataIndex, 'colorFromPalette', false);
        break;

      case 'opacity':
        data.ensureUniqueItemVisual(dataIndex, 'style').opacity = value;
        break;

      case 'symbol':
      case 'symbolSize':
      case 'liftZ':
        data.setItemVisual(dataIndex, key, value);
        break;

      default:
        if (true) {
          console.warn("Unknown visual type " + key);
        }

    }
  }

  var PI2$7 = Math.PI * 2;
  var CMD$4 = PathProxy.CMD;
  var DEFAULT_SEARCH_SPACE = ['top', 'right', 'bottom', 'left'];

  function getCandidateAnchor(pos, distance, rect, outPt, outDir) {
    var width = rect.width;
    var height = rect.height;

    switch (pos) {
      case 'top':
        outPt.set(rect.x + width / 2, rect.y - distance);
        outDir.set(0, -1);
        break;

      case 'bottom':
        outPt.set(rect.x + width / 2, rect.y + height + distance);
        outDir.set(0, 1);
        break;

      case 'left':
        outPt.set(rect.x - distance, rect.y + height / 2);
        outDir.set(-1, 0);
        break;

      case 'right':
        outPt.set(rect.x + width + distance, rect.y + height / 2);
        outDir.set(1, 0);
        break;
    }
  }

  function projectPointToArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y, out) {
    x -= cx;
    y -= cy;
    var d = Math.sqrt(x * x + y * y);
    x /= d;
    y /= d;
    var ox = x * r + cx;
    var oy = y * r + cy;

    if (Math.abs(startAngle - endAngle) % PI2$7 < 1e-4) {
      out[0] = ox;
      out[1] = oy;
      return d - r;
    }

    if (anticlockwise) {
      var tmp = startAngle;
      startAngle = normalizeRadian(endAngle);
      endAngle = normalizeRadian(tmp);
    } else {
      startAngle = normalizeRadian(startAngle);
      endAngle = normalizeRadian(endAngle);
    }

    if (startAngle > endAngle) {
      endAngle += PI2$7;
    }

    var angle = Math.atan2(y, x);

    if (angle < 0) {
      angle += PI2$7;
    }

    if (angle >= startAngle && angle <= endAngle || angle + PI2$7 >= startAngle && angle + PI2$7 <= endAngle) {
      out[0] = ox;
      out[1] = oy;
      return d - r;
    }

    var x1 = r * Math.cos(startAngle) + cx;
    var y1 = r * Math.sin(startAngle) + cy;
    var x2 = r * Math.cos(endAngle) + cx;
    var y2 = r * Math.sin(endAngle) + cy;
    var d1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y);
    var d2 = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y);

    if (d1 < d2) {
      out[0] = x1;
      out[1] = y1;
      return Math.sqrt(d1);
    } else {
      out[0] = x2;
      out[1] = y2;
      return Math.sqrt(d2);
    }
  }

  function projectPointToLine(x1, y1, x2, y2, x, y, out, limitToEnds) {
    var dx = x - x1;
    var dy = y - y1;
    var dx1 = x2 - x1;
    var dy1 = y2 - y1;
    var lineLen = Math.sqrt(dx1 * dx1 + dy1 * dy1);
    dx1 /= lineLen;
    dy1 /= lineLen;
    var projectedLen = dx * dx1 + dy * dy1;
    var t = projectedLen / lineLen;

    if (limitToEnds) {
      t = Math.min(Math.max(t, 0), 1);
    }

    t *= lineLen;
    var ox = out[0] = x1 + t * dx1;
    var oy = out[1] = y1 + t * dy1;
    return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y));
  }

  function projectPointToRect(x1, y1, width, height, x, y, out) {
    if (width < 0) {
      x1 = x1 + width;
      width = -width;
    }

    if (height < 0) {
      y1 = y1 + height;
      height = -height;
    }

    var x2 = x1 + width;
    var y2 = y1 + height;
    var ox = out[0] = Math.min(Math.max(x, x1), x2);
    var oy = out[1] = Math.min(Math.max(y, y1), y2);
    return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y));
  }

  var tmpPt = [];

  function nearestPointOnRect(pt, rect, out) {
    var dist = projectPointToRect(rect.x, rect.y, rect.width, rect.height, pt.x, pt.y, tmpPt);
    out.set(tmpPt[0], tmpPt[1]);
    return dist;
  }

  function nearestPointOnPath(pt, path, out) {
    var xi = 0;
    var yi = 0;
    var x0 = 0;
    var y0 = 0;
    var x1;
    var y1;
    var minDist = Infinity;
    var data = path.data;
    var x = pt.x;
    var y = pt.y;

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

      if (i === 1) {
        xi = data[i];
        yi = data[i + 1];
        x0 = xi;
        y0 = yi;
      }

      var d = minDist;

      switch (cmd) {
        case CMD$4.M:
          x0 = data[i++];
          y0 = data[i++];
          xi = x0;
          yi = y0;
          break;

        case CMD$4.L:
          d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true);
          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$4.C:
          d = cubicProjectPoint(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt);
          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$4.Q:
          d = quadraticProjectPoint(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt);
          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$4.A:
          var cx = data[i++];
          var cy = data[i++];
          var rx = data[i++];
          var ry = data[i++];
          var theta = data[i++];
          var dTheta = data[i++];
          i += 1;
          var anticlockwise = !!(1 - data[i++]);
          x1 = Math.cos(theta) * rx + cx;
          y1 = Math.sin(theta) * ry + cy;

          if (i <= 1) {
            x0 = x1;
            y0 = y1;
          }

          var _x = (x - cx) * ry / rx + cx;

          d = projectPointToArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y, tmpPt);
          xi = Math.cos(theta + dTheta) * rx + cx;
          yi = Math.sin(theta + dTheta) * ry + cy;
          break;

        case CMD$4.R:
          x0 = xi = data[i++];
          y0 = yi = data[i++];
          var width = data[i++];
          var height = data[i++];
          d = projectPointToRect(x0, y0, width, height, x, y, tmpPt);
          break;

        case CMD$4.Z:
          d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt, true);
          xi = x0;
          yi = y0;
          break;
      }

      if (d < minDist) {
        minDist = d;
        out.set(tmpPt[0], tmpPt[1]);
      }
    }

    return minDist;
  }

  var pt0 = new Point();
  var pt1 = new Point();
  var pt2 = new Point();
  var dir = new Point();
  var dir2 = new Point();

  function updateLabelLinePoints(target, labelLineModel) {
    if (!target) {
      return;
    }

    var labelLine = target.getTextGuideLine();
    var label = target.getTextContent();

    if (!(label && labelLine)) {
      return;
    }

    var labelGuideConfig = target.textGuideLineConfig || {};
    var points = [[0, 0], [0, 0], [0, 0]];
    var searchSpace = labelGuideConfig.candidates || DEFAULT_SEARCH_SPACE;
    var labelRect = label.getBoundingRect().clone();
    labelRect.applyTransform(label.getComputedTransform());
    var minDist = Infinity;
    var anchorPoint = labelGuideConfig.anchor;
    var targetTransform = target.getComputedTransform();
    var targetInversedTransform = targetTransform && invert([], targetTransform);
    var len = labelLineModel.get('length2') || 0;

    if (anchorPoint) {
      pt2.copy(anchorPoint);
    }

    for (var i = 0; i < searchSpace.length; i++) {
      var candidate = searchSpace[i];
      getCandidateAnchor(candidate, 0, labelRect, pt0, dir);
      Point.scaleAndAdd(pt1, pt0, dir, len);
      pt1.transform(targetInversedTransform);
      var boundingRect = target.getBoundingRect();
      var dist = anchorPoint ? anchorPoint.distance(pt1) : target instanceof Path ? nearestPointOnPath(pt1, target.path, pt2) : nearestPointOnRect(pt1, boundingRect, pt2);

      if (dist < minDist) {
        minDist = dist;
        pt1.transform(targetTransform);
        pt2.transform(targetTransform);
        pt2.toArray(points[0]);
        pt1.toArray(points[1]);
        pt0.toArray(points[2]);
      }
    }

    limitTurnAngle(points, labelLineModel.get('minTurnAngle'));
    labelLine.setShape({
      points: points
    });
  }

  var tmpArr$1 = [];
  var tmpProjPoint = new Point();

  function limitTurnAngle(linePoints, minTurnAngle) {
    if (!(minTurnAngle <= 180 && minTurnAngle > 0)) {
      return;
    }

    minTurnAngle = minTurnAngle / 180 * Math.PI;
    pt0.fromArray(linePoints[0]);
    pt1.fromArray(linePoints[1]);
    pt2.fromArray(linePoints[2]);
    Point.sub(dir, pt0, pt1);
    Point.sub(dir2, pt2, pt1);
    var len1 = dir.len();
    var len2 = dir2.len();

    if (len1 < 1e-3 || len2 < 1e-3) {
      return;
    }

    dir.scale(1 / len1);
    dir2.scale(1 / len2);
    var angleCos = dir.dot(dir2);
    var minTurnAngleCos = Math.cos(minTurnAngle);

    if (minTurnAngleCos < angleCos) {
      var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr$1, false);
      tmpProjPoint.fromArray(tmpArr$1);
      tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI - minTurnAngle));
      var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y);

      if (isNaN(t)) {
        return;
      }

      if (t < 0) {
        Point.copy(tmpProjPoint, pt1);
      } else if (t > 1) {
        Point.copy(tmpProjPoint, pt2);
      }

      tmpProjPoint.toArray(linePoints[1]);
    }
  }

  function limitSurfaceAngle(linePoints, surfaceNormal, maxSurfaceAngle) {
    if (!(maxSurfaceAngle <= 180 && maxSurfaceAngle > 0)) {
      return;
    }

    maxSurfaceAngle = maxSurfaceAngle / 180 * Math.PI;
    pt0.fromArray(linePoints[0]);
    pt1.fromArray(linePoints[1]);
    pt2.fromArray(linePoints[2]);
    Point.sub(dir, pt1, pt0);
    Point.sub(dir2, pt2, pt1);
    var len1 = dir.len();
    var len2 = dir2.len();

    if (len1 < 1e-3 || len2 < 1e-3) {
      return;
    }

    dir.scale(1 / len1);
    dir2.scale(1 / len2);
    var angleCos = dir.dot(surfaceNormal);
    var maxSurfaceAngleCos = Math.cos(maxSurfaceAngle);

    if (angleCos < maxSurfaceAngleCos) {
      var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr$1, false);
      tmpProjPoint.fromArray(tmpArr$1);
      var HALF_PI = Math.PI / 2;
      var angle2 = Math.acos(dir2.dot(surfaceNormal));
      var newAngle = HALF_PI + angle2 - maxSurfaceAngle;

      if (newAngle >= HALF_PI) {
        Point.copy(tmpProjPoint, pt2);
      } else {
        tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI / 2 - newAngle));
        var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y);

        if (isNaN(t)) {
          return;
        }

        if (t < 0) {
          Point.copy(tmpProjPoint, pt1);
        } else if (t > 1) {
          Point.copy(tmpProjPoint, pt2);
        }
      }

      tmpProjPoint.toArray(linePoints[1]);
    }
  }

  function setLabelLineState(labelLine, ignore, stateName, stateModel) {
    var isNormal = stateName === 'normal';
    var stateObj = isNormal ? labelLine : labelLine.ensureState(stateName);
    stateObj.ignore = ignore;
    var smooth = stateModel.get('smooth');

    if (smooth && smooth === true) {
      smooth = 0.3;
    }

    stateObj.shape = stateObj.shape || {};

    if (smooth > 0) {
      stateObj.shape.smooth = smooth;
    }

    var styleObj = stateModel.getModel('lineStyle').getLineStyle();
    isNormal ? labelLine.useStyle(styleObj) : stateObj.style = styleObj;
  }

  function buildLabelLinePath(path, shape) {
    var smooth = shape.smooth;
    var points = shape.points;

    if (!points) {
      return;
    }

    path.moveTo(points[0][0], points[0][1]);

    if (smooth > 0 && points.length >= 3) {
      var len1 = dist(points[0], points[1]);
      var len2 = dist(points[1], points[2]);

      if (!len1 || !len2) {
        path.lineTo(points[1][0], points[1][1]);
        path.lineTo(points[2][0], points[2][1]);
        return;
      }

      var moveLen = Math.min(len1, len2) * smooth;
      var midPoint0 = lerp([], points[1], points[0], moveLen / len1);
      var midPoint2 = lerp([], points[1], points[2], moveLen / len2);
      var midPoint1 = lerp([], midPoint0, midPoint2, 0.5);
      path.bezierCurveTo(midPoint0[0], midPoint0[1], midPoint0[0], midPoint0[1], midPoint1[0], midPoint1[1]);
      path.bezierCurveTo(midPoint2[0], midPoint2[1], midPoint2[0], midPoint2[1], points[2][0], points[2][1]);
    } else {
      for (var i = 1; i < points.length; i++) {
        path.lineTo(points[i][0], points[i][1]);
      }
    }
  }

  function setLabelLineStyle(targetEl, statesModels, defaultStyle) {
    var labelLine = targetEl.getTextGuideLine();
    var label = targetEl.getTextContent();

    if (!label) {
      if (labelLine) {
        targetEl.removeTextGuideLine();
      }

      return;
    }

    var normalModel = statesModels.normal;
    var showNormal = normalModel.get('show');
    var labelIgnoreNormal = label.ignore;

    for (var i = 0; i < DISPLAY_STATES.length; i++) {
      var stateName = DISPLAY_STATES[i];
      var stateModel = statesModels[stateName];
      var isNormal = stateName === 'normal';

      if (stateModel) {
        var stateShow = stateModel.get('show');
        var isLabelIgnored = isNormal ? labelIgnoreNormal : retrieve2(label.states[stateName] && label.states[stateName].ignore, labelIgnoreNormal);

        if (isLabelIgnored || !retrieve2(stateShow, showNormal)) {
          var stateObj = isNormal ? labelLine : labelLine && labelLine.states.normal;

          if (stateObj) {
            stateObj.ignore = true;
          }

          continue;
        }

        if (!labelLine) {
          labelLine = new Polyline();
          targetEl.setTextGuideLine(labelLine);

          if (!isNormal && (labelIgnoreNormal || !showNormal)) {
            setLabelLineState(labelLine, true, 'normal', statesModels.normal);
          }

          if (targetEl.stateProxy) {
            labelLine.stateProxy = targetEl.stateProxy;
          }
        }

        setLabelLineState(labelLine, false, stateName, stateModel);
      }
    }

    if (labelLine) {
      defaults(labelLine.style, defaultStyle);
      labelLine.style.fill = null;
      var showAbove = normalModel.get('showAbove');
      var labelLineConfig = targetEl.textGuideLineConfig = targetEl.textGuideLineConfig || {};
      labelLineConfig.showAbove = showAbove || false;
      labelLine.buildPath = buildLabelLinePath;
    }
  }

  function getLabelLineStatesModels(itemModel, labelLineName) {
    labelLineName = labelLineName || 'labelLine';
    var statesModels = {
      normal: itemModel.getModel(labelLineName)
    };

    for (var i = 0; i < SPECIAL_STATES.length; i++) {
      var stateName = SPECIAL_STATES[i];
      statesModels[stateName] = itemModel.getModel([stateName, labelLineName]);
    }

    return statesModels;
  }

  function prepareLayoutList(input) {
    var list = [];

    for (var i = 0; i < input.length; i++) {
      var rawItem = input[i];

      if (rawItem.defaultAttr.ignore) {
        continue;
      }

      var label = rawItem.label;
      var transform = label.getComputedTransform();
      var localRect = label.getBoundingRect();
      var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5;
      var minMargin = label.style.margin || 0;
      var globalRect = localRect.clone();
      globalRect.applyTransform(transform);
      globalRect.x -= minMargin / 2;
      globalRect.y -= minMargin / 2;
      globalRect.width += minMargin;
      globalRect.height += minMargin;
      var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
      list.push({
        label: label,
        labelLine: rawItem.labelLine,
        rect: globalRect,
        localRect: localRect,
        obb: obb,
        priority: rawItem.priority,
        defaultAttr: rawItem.defaultAttr,
        layoutOption: rawItem.computedLayoutOption,
        axisAligned: isAxisAligned,
        transform: transform
      });
    }

    return list;
  }

  function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) {
    var len = list.length;

    if (len < 2) {
      return;
    }

    list.sort(function (a, b) {
      return a.rect[xyDim] - b.rect[xyDim];
    });
    var lastPos = 0;
    var delta;
    var adjusted = false;
    var totalShifts = 0;

    for (var i = 0; i < len; i++) {
      var item = list[i];
      var rect = item.rect;
      delta = rect[xyDim] - lastPos;

      if (delta < 0) {
        rect[xyDim] -= delta;
        item.label[xyDim] -= delta;
        adjusted = true;
      }

      var shift = Math.max(-delta, 0);
      totalShifts += shift;
      lastPos = rect[xyDim] + rect[sizeDim];
    }

    if (totalShifts > 0 && balanceShift) {
      shiftList(-totalShifts / len, 0, len);
    }

    var first = list[0];
    var last = list[len - 1];
    var minGap;
    var maxGap;
    updateMinMaxGap();
    minGap < 0 && squeezeGaps(-minGap, 0.8);
    maxGap < 0 && squeezeGaps(maxGap, 0.8);
    updateMinMaxGap();
    takeBoundsGap(minGap, maxGap, 1);
    takeBoundsGap(maxGap, minGap, -1);
    updateMinMaxGap();

    if (minGap < 0) {
      squeezeWhenBailout(-minGap);
    }

    if (maxGap < 0) {
      squeezeWhenBailout(maxGap);
    }

    function updateMinMaxGap() {
      minGap = first.rect[xyDim] - minBound;
      maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim];
    }

    function takeBoundsGap(gapThisBound, gapOtherBound, moveDir) {
      if (gapThisBound < 0) {
        var moveFromMaxGap = Math.min(gapOtherBound, -gapThisBound);

        if (moveFromMaxGap > 0) {
          shiftList(moveFromMaxGap * moveDir, 0, len);
          var remained = moveFromMaxGap + gapThisBound;

          if (remained < 0) {
            squeezeGaps(-remained * moveDir, 1);
          }
        } else {
          squeezeGaps(-gapThisBound * moveDir, 1);
        }
      }
    }

    function shiftList(delta, start, end) {
      if (delta !== 0) {
        adjusted = true;
      }

      for (var i = start; i < end; i++) {
        var item = list[i];
        var rect = item.rect;
        rect[xyDim] += delta;
        item.label[xyDim] += delta;
      }
    }

    function squeezeGaps(delta, maxSqeezePercent) {
      var gaps = [];
      var totalGaps = 0;

      for (var i = 1; i < len; i++) {
        var prevItemRect = list[i - 1].rect;
        var gap = Math.max(list[i].rect[xyDim] - prevItemRect[xyDim] - prevItemRect[sizeDim], 0);
        gaps.push(gap);
        totalGaps += gap;
      }

      if (!totalGaps) {
        return;
      }

      var squeezePercent = Math.min(Math.abs(delta) / totalGaps, maxSqeezePercent);

      if (delta > 0) {
        for (var i = 0; i < len - 1; i++) {
          var movement = gaps[i] * squeezePercent;
          shiftList(movement, 0, i + 1);
        }
      } else {
        for (var i = len - 1; i > 0; i--) {
          var movement = gaps[i - 1] * squeezePercent;
          shiftList(-movement, i, len);
        }
      }
    }

    function squeezeWhenBailout(delta) {
      var dir = delta < 0 ? -1 : 1;
      delta = Math.abs(delta);
      var moveForEachLabel = Math.ceil(delta / (len - 1));

      for (var i = 0; i < len - 1; i++) {
        if (dir > 0) {
          shiftList(moveForEachLabel, 0, i + 1);
        } else {
          shiftList(-moveForEachLabel, len - i - 1, len);
        }

        delta -= moveForEachLabel;

        if (delta <= 0) {
          return;
        }
      }
    }

    return adjusted;
  }

  function shiftLayoutOnX(list, leftBound, rightBound, balanceShift) {
    return shiftLayout(list, 'x', 'width', leftBound, rightBound, balanceShift);
  }

  function shiftLayoutOnY(list, topBound, bottomBound, balanceShift) {
    return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift);
  }

  function hideOverlap(labelList) {
    var displayedLabels = [];
    labelList.sort(function (a, b) {
      return b.priority - a.priority;
    });
    var globalRect = new BoundingRect(0, 0, 0, 0);

    function hideEl(el) {
      if (!el.ignore) {
        var emphasisState = el.ensureState('emphasis');

        if (emphasisState.ignore == null) {
          emphasisState.ignore = false;
        }
      }

      el.ignore = true;
    }

    for (var i = 0; i < labelList.length; i++) {
      var labelItem = labelList[i];
      var isAxisAligned = labelItem.axisAligned;
      var localRect = labelItem.localRect;
      var transform = labelItem.transform;
      var label = labelItem.label;
      var labelLine = labelItem.labelLine;
      globalRect.copy(labelItem.rect);
      globalRect.width -= 0.1;
      globalRect.height -= 0.1;
      globalRect.x += 0.05;
      globalRect.y += 0.05;
      var obb = labelItem.obb;
      var overlapped = false;

      for (var j = 0; j < displayedLabels.length; j++) {
        var existsTextCfg = displayedLabels[j];

        if (!globalRect.intersect(existsTextCfg.rect)) {
          continue;
        }

        if (isAxisAligned && existsTextCfg.axisAligned) {
          overlapped = true;
          break;
        }

        if (!existsTextCfg.obb) {
          existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform);
        }

        if (!obb) {
          obb = new OrientedBoundingRect(localRect, transform);
        }

        if (obb.intersect(existsTextCfg.obb)) {
          overlapped = true;
          break;
        }
      }

      if (overlapped) {
        hideEl(label);
        labelLine && hideEl(labelLine);
      } else {
        label.attr('ignore', labelItem.defaultAttr.ignore);
        labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
        displayedLabels.push(labelItem);
      }
    }
  }

  function cloneArr(points) {
    if (points) {
      var newPoints = [];

      for (var i = 0; i < points.length; i++) {
        newPoints.push(points[i].slice());
      }

      return newPoints;
    }
  }

  function prepareLayoutCallbackParams(labelItem, hostEl) {
    var label = labelItem.label;
    var labelLine = hostEl && hostEl.getTextGuideLine();
    return {
      dataIndex: labelItem.dataIndex,
      dataType: labelItem.dataType,
      seriesIndex: labelItem.seriesModel.seriesIndex,
      text: labelItem.label.style.text,
      rect: labelItem.hostRect,
      labelRect: labelItem.rect,
      align: label.style.align,
      verticalAlign: label.style.verticalAlign,
      labelLinePoints: cloneArr(labelLine && labelLine.shape.points)
    };
  }

  var LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize'];
  var dummyTransformable = new Transformable();
  var labelLayoutInnerStore = makeInner();
  var labelLineAnimationStore = makeInner();

  function extendWithKeys(target, source, keys) {
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i];

      if (source[key] != null) {
        target[key] = source[key];
      }
    }
  }

  var LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation'];

  var LabelManager = function () {
    function LabelManager() {
      this._labelList = [];
      this._chartViewList = [];
    }

    LabelManager.prototype.clearLabels = function () {
      this._labelList = [];
      this._chartViewList = [];
    };

    LabelManager.prototype._addLabel = function (dataIndex, dataType, seriesModel, label, layoutOption) {
      var labelStyle = label.style;
      var hostEl = label.__hostTarget;
      var textConfig = hostEl.textConfig || {};
      var labelTransform = label.getComputedTransform();
      var labelRect = label.getBoundingRect().plain();
      BoundingRect.applyTransform(labelRect, labelRect, labelTransform);

      if (labelTransform) {
        dummyTransformable.setLocalTransform(labelTransform);
      } else {
        dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation = dummyTransformable.originX = dummyTransformable.originY = 0;
        dummyTransformable.scaleX = dummyTransformable.scaleY = 1;
      }

      var host = label.__hostTarget;
      var hostRect;

      if (host) {
        hostRect = host.getBoundingRect().plain();
        var transform = host.getComputedTransform();
        BoundingRect.applyTransform(hostRect, hostRect, transform);
      }

      var labelGuide = hostRect && host.getTextGuideLine();

      this._labelList.push({
        label: label,
        labelLine: labelGuide,
        seriesModel: seriesModel,
        dataIndex: dataIndex,
        dataType: dataType,
        layoutOption: layoutOption,
        computedLayoutOption: null,
        rect: labelRect,
        hostRect: hostRect,
        priority: hostRect ? hostRect.width * hostRect.height : 0,
        defaultAttr: {
          ignore: label.ignore,
          labelGuideIgnore: labelGuide && labelGuide.ignore,
          x: dummyTransformable.x,
          y: dummyTransformable.y,
          rotation: dummyTransformable.rotation,
          style: {
            x: labelStyle.x,
            y: labelStyle.y,
            align: labelStyle.align,
            verticalAlign: labelStyle.verticalAlign,
            width: labelStyle.width,
            height: labelStyle.height,
            fontSize: labelStyle.fontSize
          },
          cursor: label.cursor,
          attachedPos: textConfig.position,
          attachedRot: textConfig.rotation
        }
      });
    };

    LabelManager.prototype.addLabelsOfSeries = function (chartView) {
      var _this = this;

      this._chartViewList.push(chartView);

      var seriesModel = chartView.__model;
      var layoutOption = seriesModel.get('labelLayout');

      if (!(isFunction(layoutOption) || keys(layoutOption).length)) {
        return;
      }

      chartView.group.traverse(function (child) {
        if (child.ignore) {
          return true;
        }

        var textEl = child.getTextContent();
        var ecData = getECData(child);

        if (textEl && !textEl.disableLabelLayout) {
          _this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption);
        }
      });
    };

    LabelManager.prototype.updateLayoutConfig = function (api) {
      var width = api.getWidth();
      var height = api.getHeight();

      function createDragHandler(el, labelLineModel) {
        return function () {
          updateLabelLinePoints(el, labelLineModel);
        };
      }

      for (var i = 0; i < this._labelList.length; i++) {
        var labelItem = this._labelList[i];
        var label = labelItem.label;
        var hostEl = label.__hostTarget;
        var defaultLabelAttr = labelItem.defaultAttr;
        var layoutOption = void 0;

        if (typeof labelItem.layoutOption === 'function') {
          layoutOption = labelItem.layoutOption(prepareLayoutCallbackParams(labelItem, hostEl));
        } else {
          layoutOption = labelItem.layoutOption;
        }

        layoutOption = layoutOption || {};
        labelItem.computedLayoutOption = layoutOption;
        var degreeToRadian = Math.PI / 180;

        if (hostEl) {
          hostEl.setTextConfig({
            local: false,
            position: layoutOption.x != null || layoutOption.y != null ? null : defaultLabelAttr.attachedPos,
            rotation: layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot,
            offset: [layoutOption.dx || 0, layoutOption.dy || 0]
          });
        }

        var needsUpdateLabelLine = false;

        if (layoutOption.x != null) {
          label.x = parsePercent$2(layoutOption.x, width);
          label.setStyle('x', 0);
          needsUpdateLabelLine = true;
        } else {
          label.x = defaultLabelAttr.x;
          label.setStyle('x', defaultLabelAttr.style.x);
        }

        if (layoutOption.y != null) {
          label.y = parsePercent$2(layoutOption.y, height);
          label.setStyle('y', 0);
          needsUpdateLabelLine = true;
        } else {
          label.y = defaultLabelAttr.y;
          label.setStyle('y', defaultLabelAttr.style.y);
        }

        if (layoutOption.labelLinePoints) {
          var guideLine = hostEl.getTextGuideLine();

          if (guideLine) {
            guideLine.setShape({
              points: layoutOption.labelLinePoints
            });
            needsUpdateLabelLine = false;
          }
        }

        var labelLayoutStore = labelLayoutInnerStore(label);
        labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine;
        label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;

        for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
          var key = LABEL_OPTION_TO_STYLE_KEYS[k];
          label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]);
        }

        if (layoutOption.draggable) {
          label.draggable = true;
          label.cursor = 'move';

          if (hostEl) {
            var hostModel = labelItem.seriesModel;

            if (labelItem.dataIndex != null) {
              var data = labelItem.seriesModel.getData(labelItem.dataType);
              hostModel = data.getItemModel(labelItem.dataIndex);
            }

            label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine')));
          }
        } else {
          label.off('drag');
          label.cursor = defaultLabelAttr.cursor;
        }
      }
    };

    LabelManager.prototype.layout = function (api) {
      var width = api.getWidth();
      var height = api.getHeight();
      var labelList = prepareLayoutList(this._labelList);
      var labelsNeedsAdjustOnX = filter(labelList, function (item) {
        return item.layoutOption.moveOverlap === 'shiftX';
      });
      var labelsNeedsAdjustOnY = filter(labelList, function (item) {
        return item.layoutOption.moveOverlap === 'shiftY';
      });
      shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width);
      shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height);
      var labelsNeedsHideOverlap = filter(labelList, function (item) {
        return item.layoutOption.hideOverlap;
      });
      hideOverlap(labelsNeedsHideOverlap);
    };

    LabelManager.prototype.processLabelsOverall = function () {
      var _this = this;

      each(this._chartViewList, function (chartView) {
        var seriesModel = chartView.__model;
        var ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate;
        var animationEnabled = seriesModel.isAnimationEnabled();
        chartView.group.traverse(function (child) {
          if (child.ignore) {
            return true;
          }

          var needsUpdateLabelLine = !ignoreLabelLineUpdate;
          var label = child.getTextContent();

          if (!needsUpdateLabelLine && label) {
            needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine;
          }

          if (needsUpdateLabelLine) {
            _this._updateLabelLine(child, seriesModel);
          }

          if (animationEnabled) {
            _this._animateLabels(child, seriesModel);
          }
        });
      });
    };

    LabelManager.prototype._updateLabelLine = function (el, seriesModel) {
      var textEl = el.getTextContent();
      var ecData = getECData(el);
      var dataIndex = ecData.dataIndex;

      if (textEl && dataIndex != null) {
        var data = seriesModel.getData(ecData.dataType);
        var itemModel = data.getItemModel(dataIndex);
        var defaultStyle = {};
        var visualStyle = data.getItemVisual(dataIndex, 'style');
        var visualType = data.getVisual('drawType');
        defaultStyle.stroke = visualStyle[visualType];
        var labelLineModel = itemModel.getModel('labelLine');
        setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle);
        updateLabelLinePoints(el, labelLineModel);
      }
    };

    LabelManager.prototype._animateLabels = function (el, seriesModel) {
      var textEl = el.getTextContent();
      var guideLine = el.getTextGuideLine();

      if (textEl && !textEl.ignore && !textEl.invisible && !el.disableLabelAnimation && !isElementRemoved(el)) {
        var layoutStore = labelLayoutInnerStore(textEl);
        var oldLayout = layoutStore.oldLayout;
        var ecData = getECData(el);
        var dataIndex = ecData.dataIndex;
        var newProps = {
          x: textEl.x,
          y: textEl.y,
          rotation: textEl.rotation
        };
        var data = seriesModel.getData(ecData.dataType);

        if (!oldLayout) {
          textEl.attr(newProps);

          if (!labelInner(textEl).valueAnimation) {
            var oldOpacity = retrieve2(textEl.style.opacity, 1);
            textEl.style.opacity = 0;
            initProps(textEl, {
              style: {
                opacity: oldOpacity
              }
            }, seriesModel, dataIndex);
          }
        } else {
          textEl.attr(oldLayout);
          var prevStates = el.prevStates;

          if (prevStates) {
            if (indexOf(prevStates, 'select') >= 0) {
              textEl.attr(layoutStore.oldLayoutSelect);
            }

            if (indexOf(prevStates, 'emphasis') >= 0) {
              textEl.attr(layoutStore.oldLayoutEmphasis);
            }
          }

          updateProps(textEl, newProps, seriesModel, dataIndex);
        }

        layoutStore.oldLayout = newProps;

        if (textEl.states.select) {
          var layoutSelect = layoutStore.oldLayoutSelect = {};
          extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS);
          extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS);
        }

        if (textEl.states.emphasis) {
          var layoutEmphasis = layoutStore.oldLayoutEmphasis = {};
          extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS);
          extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS);
        }

        animateLabelValue(textEl, dataIndex, data, seriesModel);
      }

      if (guideLine && !guideLine.ignore && !guideLine.invisible) {
        var layoutStore = labelLineAnimationStore(guideLine);
        var oldLayout = layoutStore.oldLayout;
        var newLayout = {
          points: guideLine.shape.points
        };

        if (!oldLayout) {
          guideLine.setShape(newLayout);
          guideLine.style.strokePercent = 0;
          initProps(guideLine, {
            style: {
              strokePercent: 1
            }
          }, seriesModel);
        } else {
          guideLine.attr({
            shape: oldLayout
          });
          updateProps(guideLine, {
            shape: newLayout
          }, seriesModel);
        }

        layoutStore.oldLayout = newLayout;
      }
    };

    return LabelManager;
  }();

  function createLegacyDataSelectAction(seriesType, ecRegisterAction) {
    function getSeriesIndices(ecModel, payload) {
      var seriesIndices = [];
      ecModel.eachComponent({
        mainType: 'series',
        subType: seriesType,
        query: payload
      }, function (seriesModel) {
        seriesIndices.push(seriesModel.seriesIndex);
      });
      return seriesIndices;
    }

    each([[seriesType + 'ToggleSelect', 'toggleSelect'], [seriesType + 'Select', 'select'], [seriesType + 'UnSelect', 'unselect']], function (eventsMap) {
      ecRegisterAction(eventsMap[0], function (payload, ecModel, api) {
        payload = extend({}, payload);

        if (true) {
          deprecateReplaceLog(payload.type, eventsMap[1]);
        }

        api.dispatchAction(extend(payload, {
          type: eventsMap[1],
          seriesIndex: getSeriesIndices(ecModel, payload)
        }));
      });
    });
  }

  function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) {
    var legacyEventName = type + eventPostfix;

    if (!ecIns.isSilent(legacyEventName)) {
      if (true) {
        deprecateLog("event " + legacyEventName + " is deprecated.");
      }

      ecModel.eachComponent({
        mainType: 'series',
        subType: 'pie'
      }, function (seriesModel) {
        var seriesIndex = seriesModel.seriesIndex;
        var selected = payload.selected;

        for (var i = 0; i < selected.length; i++) {
          if (selected[i].seriesIndex === seriesIndex) {
            var data = seriesModel.getData();
            var dataIndex = queryDataIndex(data, payload.fromActionPayload);
            ecIns.trigger(legacyEventName, {
              type: legacyEventName,
              seriesId: seriesModel.id,
              name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex),
              selected: extend({}, seriesModel.option.selectedMap)
            });
          }
        }
      });
    }
  }

  function handleLegacySelectEvents(messageCenter, ecIns, ecModel) {
    messageCenter.on('selectchanged', function (params) {
      if (params.isFromClick) {
        handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params);
        handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params);
      } else if (params.fromAction === 'select') {
        handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params);
        handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params);
      } else if (params.fromAction === 'unselect') {
        handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params);
        handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params);
      }
    });
  }

  function createLinearGradient(ctx, obj, rect) {
    var x = obj.x == null ? 0 : obj.x;
    var x2 = obj.x2 == null ? 1 : obj.x2;
    var y = obj.y == null ? 0 : obj.y;
    var y2 = obj.y2 == null ? 0 : obj.y2;

    if (!obj.global) {
      x = x * rect.width + rect.x;
      x2 = x2 * rect.width + rect.x;
      y = y * rect.height + rect.y;
      y2 = y2 * rect.height + rect.y;
    }

    x = isNaN(x) ? 0 : x;
    x2 = isNaN(x2) ? 1 : x2;
    y = isNaN(y) ? 0 : y;
    y2 = isNaN(y2) ? 0 : y2;
    var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);
    return canvasGradient;
  }

  function createRadialGradient(ctx, obj, rect) {
    var width = rect.width;
    var height = rect.height;
    var min = Math.min(width, height);
    var x = obj.x == null ? 0.5 : obj.x;
    var y = obj.y == null ? 0.5 : obj.y;
    var r = obj.r == null ? 0.5 : obj.r;

    if (!obj.global) {
      x = x * width + rect.x;
      y = y * height + rect.y;
      r = r * min;
    }

    var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);
    return canvasGradient;
  }

  function getCanvasGradient(ctx, obj, rect) {
    var canvasGradient = obj.type === 'radial' ? createRadialGradient(ctx, obj, rect) : createLinearGradient(ctx, obj, rect);
    var colorStops = obj.colorStops;

    for (var i = 0; i < colorStops.length; i++) {
      canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color);
    }

    return canvasGradient;
  }

  function isClipPathChanged(clipPaths, prevClipPaths) {
    if (clipPaths === prevClipPaths || !clipPaths && !prevClipPaths) {
      return false;
    }

    if (!clipPaths || !prevClipPaths || clipPaths.length !== prevClipPaths.length) {
      return true;
    }

    for (var i = 0; i < clipPaths.length; i++) {
      if (clipPaths[i] !== prevClipPaths[i]) {
        return true;
      }
    }

    return false;
  }

  function normalizeLineDash(lineType, lineWidth) {
    if (!lineType || lineType === 'solid' || !(lineWidth > 0)) {
      return null;
    }

    lineWidth = lineWidth || 1;
    return lineType === 'dashed' ? [4 * lineWidth, 2 * lineWidth] : lineType === 'dotted' ? [lineWidth] : isNumber(lineType) ? [lineType] : isArray(lineType) ? lineType : null;
  }

  var pathProxyForDraw = new PathProxy(true);

  function styleHasStroke(style) {
    var stroke = style.stroke;
    return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
  }

  function styleHasFill(style) {
    var fill = style.fill;
    return fill != null && fill !== 'none';
  }

  function doFillPath(ctx, style) {
    if (style.fillOpacity != null && style.fillOpacity !== 1) {
      var originalGlobalAlpha = ctx.globalAlpha;
      ctx.globalAlpha = style.fillOpacity * style.opacity;
      ctx.fill();
      ctx.globalAlpha = originalGlobalAlpha;
    } else {
      ctx.fill();
    }
  }

  function doStrokePath(ctx, style) {
    if (style.strokeOpacity != null && style.strokeOpacity !== 1) {
      var originalGlobalAlpha = ctx.globalAlpha;
      ctx.globalAlpha = style.strokeOpacity * style.opacity;
      ctx.stroke();
      ctx.globalAlpha = originalGlobalAlpha;
    } else {
      ctx.stroke();
    }
  }

  function createCanvasPattern(ctx, pattern, el) {
    var image = createOrUpdateImage(pattern.image, pattern.__image, el);

    if (isImageReady(image)) {
      var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat');

      if (typeof DOMMatrix === 'function') {
        var matrix = new DOMMatrix();
        matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180);
        matrix.scaleSelf(pattern.scaleX || 1, pattern.scaleY || 1);
        matrix.translateSelf(pattern.x || 0, pattern.y || 0);
        canvasPattern.setTransform(matrix);
      }

      return canvasPattern;
    }
  }

  function brushPath(ctx, el, style, inBatch) {
    var hasStroke = styleHasStroke(style);
    var hasFill = styleHasFill(style);
    var strokePercent = style.strokePercent;
    var strokePart = strokePercent < 1;
    var firstDraw = !el.path;

    if ((!el.silent || strokePart) && firstDraw) {
      el.createPathProxy();
    }

    var path = el.path || pathProxyForDraw;

    if (!inBatch) {
      var fill = style.fill;
      var stroke = style.stroke;
      var hasFillGradient = hasFill && !!fill.colorStops;
      var hasStrokeGradient = hasStroke && !!stroke.colorStops;
      var hasFillPattern = hasFill && !!fill.image;
      var hasStrokePattern = hasStroke && !!stroke.image;
      var fillGradient = void 0;
      var strokeGradient = void 0;
      var fillPattern = void 0;
      var strokePattern = void 0;
      var rect = void 0;

      if (hasFillGradient || hasStrokeGradient) {
        rect = el.getBoundingRect();
      }

      if (hasFillGradient) {
        fillGradient = el.__dirty ? getCanvasGradient(ctx, fill, rect) : el.__canvasFillGradient;
        el.__canvasFillGradient = fillGradient;
      }

      if (hasStrokeGradient) {
        strokeGradient = el.__dirty ? getCanvasGradient(ctx, stroke, rect) : el.__canvasStrokeGradient;
        el.__canvasStrokeGradient = strokeGradient;
      }

      if (hasFillPattern) {
        fillPattern = el.__dirty || !el.__canvasFillPattern ? createCanvasPattern(ctx, fill, el) : el.__canvasFillPattern;
        el.__canvasFillPattern = fillPattern;
      }

      if (hasStrokePattern) {
        strokePattern = el.__dirty || !el.__canvasStrokePattern ? createCanvasPattern(ctx, stroke, el) : el.__canvasStrokePattern;
        el.__canvasStrokePattern = fillPattern;
      }

      if (hasFillGradient) {
        ctx.fillStyle = fillGradient;
      } else if (hasFillPattern) {
        if (fillPattern) {
          ctx.fillStyle = fillPattern;
        } else {
          hasFill = false;
        }
      }

      if (hasStrokeGradient) {
        ctx.strokeStyle = strokeGradient;
      } else if (hasStrokePattern) {
        if (strokePattern) {
          ctx.strokeStyle = strokePattern;
        } else {
          hasStroke = false;
        }
      }
    }

    var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth);
    var lineDashOffset = style.lineDashOffset;
    var ctxLineDash = !!ctx.setLineDash;
    var scale = el.getGlobalScale();
    path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold);

    if (lineDash) {
      var lineScale_1 = style.strokeNoScale && el.getLineScale ? el.getLineScale() : 1;

      if (lineScale_1 && lineScale_1 !== 1) {
        lineDash = map(lineDash, function (rawVal) {
          return rawVal / lineScale_1;
        });
        lineDashOffset /= lineScale_1;
      }
    }

    var needsRebuild = true;

    if (firstDraw || el.__dirty & Path.SHAPE_CHANGED_BIT || lineDash && !ctxLineDash && hasStroke) {
      path.setDPR(ctx.dpr);

      if (strokePart) {
        path.setContext(null);
      } else {
        path.setContext(ctx);
        needsRebuild = false;
      }

      path.reset();

      if (lineDash && !ctxLineDash) {
        path.setLineDash(lineDash);
        path.setLineDashOffset(lineDashOffset);
      }

      el.buildPath(path, el.shape, inBatch);
      path.toStatic();
      el.pathUpdated();
    }

    if (needsRebuild) {
      path.rebuildPath(ctx, strokePart ? strokePercent : 1);
    }

    if (lineDash && ctxLineDash) {
      ctx.setLineDash(lineDash);
      ctx.lineDashOffset = lineDashOffset;
    }

    if (!inBatch) {
      if (style.strokeFirst) {
        if (hasStroke) {
          doStrokePath(ctx, style);
        }

        if (hasFill) {
          doFillPath(ctx, style);
        }
      } else {
        if (hasFill) {
          doFillPath(ctx, style);
        }

        if (hasStroke) {
          doStrokePath(ctx, style);
        }
      }
    }

    if (lineDash && ctxLineDash) {
      ctx.setLineDash([]);
    }
  }

  function brushImage(ctx, el, style) {
    var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload);

    if (!image || !isImageReady(image)) {
      return;
    }

    var x = style.x || 0;
    var y = style.y || 0;
    var width = el.getWidth();
    var height = el.getHeight();
    var aspect = image.width / image.height;

    if (width == null && height != null) {
      width = height * aspect;
    } else if (height == null && width != null) {
      height = width / aspect;
    } else if (width == null && height == null) {
      width = image.width;
      height = image.height;
    }

    if (style.sWidth && style.sHeight) {
      var sx = style.sx || 0;
      var sy = style.sy || 0;
      ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height);
    } else if (style.sx && style.sy) {
      var sx = style.sx;
      var sy = style.sy;
      var sWidth = width - sx;
      var sHeight = height - sy;
      ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height);
    } else {
      ctx.drawImage(image, x, y, width, height);
    }
  }

  function brushText(ctx, el, style) {
    var text = style.text;
    text != null && (text += '');

    if (text) {
      ctx.font = style.font || DEFAULT_FONT;
      ctx.textAlign = style.textAlign;
      ctx.textBaseline = style.textBaseline;
      var hasLineDash = void 0;

      if (ctx.setLineDash) {
        var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth);
        var lineDashOffset = style.lineDashOffset;

        if (lineDash) {
          var lineScale_2 = style.strokeNoScale && el.getLineScale ? el.getLineScale() : 1;

          if (lineScale_2 && lineScale_2 !== 1) {
            lineDash = map(lineDash, function (rawVal) {
              return rawVal / lineScale_2;
            });
            lineDashOffset /= lineScale_2;
          }

          ctx.setLineDash(lineDash);
          ctx.lineDashOffset = lineDashOffset;
          hasLineDash = true;
        }
      }

      if (style.strokeFirst) {
        if (styleHasStroke(style)) {
          ctx.strokeText(text, style.x, style.y);
        }

        if (styleHasFill(style)) {
          ctx.fillText(text, style.x, style.y);
        }
      } else {
        if (styleHasFill(style)) {
          ctx.fillText(text, style.x, style.y);
        }

        if (styleHasStroke(style)) {
          ctx.strokeText(text, style.x, style.y);
        }
      }

      if (hasLineDash) {
        ctx.setLineDash([]);
      }
    }
  }

  var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];
  var STROKE_PROPS = [['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]];

  function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) {
    var styleChanged = false;

    if (!forceSetAll) {
      prevStyle = prevStyle || {};

      if (style === prevStyle) {
        return false;
      }
    }

    if (forceSetAll || style.opacity !== prevStyle.opacity) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.globalAlpha = style.opacity == null ? DEFAULT_COMMON_STYLE.opacity : style.opacity;
    }

    if (forceSetAll || style.blend !== prevStyle.blend) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend;
    }

    for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) {
      var propName = SHADOW_NUMBER_PROPS[i];

      if (forceSetAll || style[propName] !== prevStyle[propName]) {
        if (!styleChanged) {
          flushPathDrawn(ctx, scope);
          styleChanged = true;
        }

        ctx[propName] = ctx.dpr * (style[propName] || 0);
      }
    }

    if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor;
    }

    return styleChanged;
  }

  function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) {
    var style = getStyle(el, scope.inHover);
    var prevStyle = forceSetAll ? null : prevEl && getStyle(prevEl, scope.inHover) || {};

    if (style === prevStyle) {
      return false;
    }

    var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope);

    if (forceSetAll || style.fill !== prevStyle.fill) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.fillStyle = style.fill;
    }

    if (forceSetAll || style.stroke !== prevStyle.stroke) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.strokeStyle = style.stroke;
    }

    if (forceSetAll || style.opacity !== prevStyle.opacity) {
      if (!styleChanged) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
      }

      ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
    }

    if (el.hasStroke()) {
      var lineWidth = style.lineWidth;
      var newLineWidth = lineWidth / (style.strokeNoScale && el && el.getLineScale ? el.getLineScale() : 1);

      if (ctx.lineWidth !== newLineWidth) {
        if (!styleChanged) {
          flushPathDrawn(ctx, scope);
          styleChanged = true;
        }

        ctx.lineWidth = newLineWidth;
      }
    }

    for (var i = 0; i < STROKE_PROPS.length; i++) {
      var prop = STROKE_PROPS[i];
      var propName = prop[0];

      if (forceSetAll || style[propName] !== prevStyle[propName]) {
        if (!styleChanged) {
          flushPathDrawn(ctx, scope);
          styleChanged = true;
        }

        ctx[propName] = style[propName] || prop[1];
      }
    }

    return styleChanged;
  }

  function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) {
    return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope);
  }

  function setContextTransform(ctx, el) {
    var m = el.transform;
    var dpr = ctx.dpr || 1;

    if (m) {
      ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
    } else {
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
  }

  function updateClipStatus(clipPaths, ctx, scope) {
    var allClipped = false;

    for (var i = 0; i < clipPaths.length; i++) {
      var clipPath = clipPaths[i];
      allClipped = allClipped || clipPath.isZeroArea();
      setContextTransform(ctx, clipPath);
      ctx.beginPath();
      clipPath.buildPath(ctx, clipPath.shape);
      ctx.clip();
    }

    scope.allClipped = allClipped;
  }

  function isTransformChanged(m0, m1) {
    if (m0 && m1) {
      return m0[0] !== m1[0] || m0[1] !== m1[1] || m0[2] !== m1[2] || m0[3] !== m1[3] || m0[4] !== m1[4] || m0[5] !== m1[5];
    } else if (!m0 && !m1) {
      return false;
    }

    return true;
  }

  var DRAW_TYPE_PATH = 1;
  var DRAW_TYPE_IMAGE = 2;
  var DRAW_TYPE_TEXT = 3;
  var DRAW_TYPE_INCREMENTAL = 4;

  function canPathBatch(style) {
    var hasFill = styleHasFill(style);
    var hasStroke = styleHasStroke(style);
    return !(style.lineDash || !(+hasFill ^ +hasStroke) || hasFill && typeof style.fill !== 'string' || hasStroke && typeof style.stroke !== 'string' || style.strokePercent < 1 || style.strokeOpacity < 1 || style.fillOpacity < 1);
  }

  function flushPathDrawn(ctx, scope) {
    scope.batchFill && ctx.fill();
    scope.batchStroke && ctx.stroke();
    scope.batchFill = '';
    scope.batchStroke = '';
  }

  function getStyle(el, inHover) {
    return inHover ? el.__hoverStyle || el.style : el.style;
  }

  function brushSingle(ctx, el) {
    brush(ctx, el, {
      inHover: false,
      viewWidth: 0,
      viewHeight: 0
    }, true);
  }

  function brush(ctx, el, scope, isLast) {
    var m = el.transform;

    if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
      el.__dirty &= ~Element.REDARAW_BIT;
      el.__isRendered = false;
      return;
    }

    var clipPaths = el.__clipPaths;
    var prevElClipPaths = scope.prevElClipPaths;
    var forceSetTransform = false;
    var forceSetStyle = false;

    if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) {
      if (prevElClipPaths && prevElClipPaths.length) {
        flushPathDrawn(ctx, scope);
        ctx.restore();
        forceSetStyle = forceSetTransform = true;
        scope.prevElClipPaths = null;
        scope.allClipped = false;
        scope.prevEl = null;
      }

      if (clipPaths && clipPaths.length) {
        flushPathDrawn(ctx, scope);
        ctx.save();
        updateClipStatus(clipPaths, ctx, scope);
        forceSetTransform = true;
      }

      scope.prevElClipPaths = clipPaths;
    }

    if (scope.allClipped) {
      el.__isRendered = false;
      return;
    }

    el.beforeBrush && el.beforeBrush();
    el.innerBeforeBrush();
    var prevEl = scope.prevEl;

    if (!prevEl) {
      forceSetStyle = forceSetTransform = true;
    }

    var canBatchPath = el instanceof Path && el.autoBatch && canPathBatch(el.style);

    if (forceSetTransform || isTransformChanged(m, prevEl.transform)) {
      flushPathDrawn(ctx, scope);
      setContextTransform(ctx, el);
    } else if (!canBatchPath) {
      flushPathDrawn(ctx, scope);
    }

    var style = getStyle(el, scope.inHover);

    if (el instanceof Path) {
      if (scope.lastDrawType !== DRAW_TYPE_PATH) {
        forceSetStyle = true;
        scope.lastDrawType = DRAW_TYPE_PATH;
      }

      bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);

      if (!canBatchPath || !scope.batchFill && !scope.batchStroke) {
        ctx.beginPath();
      }

      brushPath(ctx, el, style, canBatchPath);

      if (canBatchPath) {
        scope.batchFill = style.fill || '';
        scope.batchStroke = style.stroke || '';
      }
    } else {
      if (el instanceof TSpan) {
        if (scope.lastDrawType !== DRAW_TYPE_TEXT) {
          forceSetStyle = true;
          scope.lastDrawType = DRAW_TYPE_TEXT;
        }

        bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);
        brushText(ctx, el, style);
      } else if (el instanceof ZRImage) {
        if (scope.lastDrawType !== DRAW_TYPE_IMAGE) {
          forceSetStyle = true;
          scope.lastDrawType = DRAW_TYPE_IMAGE;
        }

        bindImageStyle(ctx, el, prevEl, forceSetStyle, scope);
        brushImage(ctx, el, style);
      } else if (el instanceof IncrementalDisplayble) {
        if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) {
          forceSetStyle = true;
          scope.lastDrawType = DRAW_TYPE_INCREMENTAL;
        }

        brushIncremental(ctx, el, scope);
      }
    }

    if (canBatchPath && isLast) {
      flushPathDrawn(ctx, scope);
    }

    el.innerAfterBrush();
    el.afterBrush && el.afterBrush();
    scope.prevEl = el;
    el.__dirty = 0;
    el.__isRendered = true;
  }

  function brushIncremental(ctx, el, scope) {
    var displayables = el.getDisplayables();
    var temporalDisplayables = el.getTemporalDisplayables();
    ctx.save();
    var innerScope = {
      prevElClipPaths: null,
      prevEl: null,
      allClipped: false,
      viewWidth: scope.viewWidth,
      viewHeight: scope.viewHeight,
      inHover: scope.inHover
    };
    var i;
    var len;

    for (i = el.getCursor(), len = displayables.length; i < len; i++) {
      var displayable = displayables[i];
      displayable.beforeBrush && displayable.beforeBrush();
      displayable.innerBeforeBrush();
      brush(ctx, displayable, innerScope, i === len - 1);
      displayable.innerAfterBrush();
      displayable.afterBrush && displayable.afterBrush();
      innerScope.prevEl = displayable;
    }

    for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) {
      var displayable = temporalDisplayables[i_1];
      displayable.beforeBrush && displayable.beforeBrush();
      displayable.innerBeforeBrush();
      brush(ctx, displayable, innerScope, i_1 === len_1 - 1);
      displayable.innerAfterBrush();
      displayable.afterBrush && displayable.afterBrush();
      innerScope.prevEl = displayable;
    }

    el.clearTemporalDisplayables();
    el.notClear = true;
    ctx.restore();
  }

  function returnFalse() {
    return false;
  }

  function createDom(id, painter, dpr) {
    var newDom = createCanvas();
    var width = painter.getWidth();
    var height = painter.getHeight();
    var newDomStyle = newDom.style;

    if (newDomStyle) {
      newDomStyle.position = 'absolute';
      newDomStyle.left = '0';
      newDomStyle.top = '0';
      newDomStyle.width = width + 'px';
      newDomStyle.height = height + 'px';
      newDom.setAttribute('data-zr-dom-id', id);
    }

    newDom.width = width * dpr;
    newDom.height = height * dpr;
    return newDom;
  }

  var Layer = function (_super) {
    __extends(Layer, _super);

    function Layer(id, painter, dpr) {
      var _this = _super.call(this) || this;

      _this.motionBlur = false;
      _this.lastFrameAlpha = 0.7;
      _this.dpr = 1;
      _this.virtual = false;
      _this.config = {};
      _this.incremental = false;
      _this.zlevel = 0;
      _this.maxRepaintRectCount = 5;
      _this.__dirty = true;
      _this.__firstTimePaint = true;
      _this.__used = false;
      _this.__drawIndex = 0;
      _this.__startIndex = 0;
      _this.__endIndex = 0;
      _this.__prevStartIndex = null;
      _this.__prevEndIndex = null;
      var dom;
      dpr = dpr || devicePixelRatio;

      if (typeof id === 'string') {
        dom = createDom(id, painter, dpr);
      } else if (isObject(id)) {
        dom = id;
        id = dom.id;
      }

      _this.id = id;
      _this.dom = dom;
      var domStyle = dom.style;

      if (domStyle) {
        dom.onselectstart = returnFalse;
        domStyle.webkitUserSelect = 'none';
        domStyle.userSelect = 'none';
        domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)';
        domStyle['-webkit-touch-callout'] = 'none';
        domStyle.padding = '0';
        domStyle.margin = '0';
        domStyle.borderWidth = '0';
      }

      _this.domBack = null;
      _this.ctxBack = null;
      _this.painter = painter;
      _this.config = null;
      _this.dpr = dpr;
      return _this;
    }

    Layer.prototype.getElementCount = function () {
      return this.__endIndex - this.__startIndex;
    };

    Layer.prototype.afterBrush = function () {
      this.__prevStartIndex = this.__startIndex;
      this.__prevEndIndex = this.__endIndex;
    };

    Layer.prototype.initContext = function () {
      this.ctx = this.dom.getContext('2d');
      this.ctx.dpr = this.dpr;
    };

    Layer.prototype.setUnpainted = function () {
      this.__firstTimePaint = true;
    };

    Layer.prototype.createBackBuffer = function () {
      var dpr = this.dpr;
      this.domBack = createDom('back-' + this.id, this.painter, dpr);
      this.ctxBack = this.domBack.getContext('2d');

      if (dpr !== 1) {
        this.ctxBack.scale(dpr, dpr);
      }
    };

    Layer.prototype.createRepaintRects = function (displayList, prevList, viewWidth, viewHeight) {
      if (this.__firstTimePaint) {
        this.__firstTimePaint = false;
        return null;
      }

      var mergedRepaintRects = [];
      var maxRepaintRectCount = this.maxRepaintRectCount;
      var full = false;
      var pendingRect = new BoundingRect(0, 0, 0, 0);

      function addRectToMergePool(rect) {
        if (!rect.isFinite() || rect.isZero()) {
          return;
        }

        if (mergedRepaintRects.length === 0) {
          var boundingRect = new BoundingRect(0, 0, 0, 0);
          boundingRect.copy(rect);
          mergedRepaintRects.push(boundingRect);
        } else {
          var isMerged = false;
          var minDeltaArea = Infinity;
          var bestRectToMergeIdx = 0;

          for (var i = 0; i < mergedRepaintRects.length; ++i) {
            var mergedRect = mergedRepaintRects[i];

            if (mergedRect.intersect(rect)) {
              var pendingRect_1 = new BoundingRect(0, 0, 0, 0);
              pendingRect_1.copy(mergedRect);
              pendingRect_1.union(rect);
              mergedRepaintRects[i] = pendingRect_1;
              isMerged = true;
              break;
            } else if (full) {
              pendingRect.copy(rect);
              pendingRect.union(mergedRect);
              var aArea = rect.width * rect.height;
              var bArea = mergedRect.width * mergedRect.height;
              var pendingArea = pendingRect.width * pendingRect.height;
              var deltaArea = pendingArea - aArea - bArea;

              if (deltaArea < minDeltaArea) {
                minDeltaArea = minDeltaArea;
                bestRectToMergeIdx = i;
              }
            }
          }

          if (full) {
            mergedRepaintRects[bestRectToMergeIdx].union(rect);
            isMerged = true;
          }

          if (!isMerged) {
            var boundingRect = new BoundingRect(0, 0, 0, 0);
            boundingRect.copy(rect);
            mergedRepaintRects.push(boundingRect);
          }

          if (!full) {
            full = mergedRepaintRects.length >= maxRepaintRectCount;
          }
        }
      }

      for (var i = this.__startIndex; i < this.__endIndex; ++i) {
        var el = displayList[i];

        if (el) {
          var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
          var prevRect = el.__isRendered && (el.__dirty & Element.REDARAW_BIT || !shouldPaint) ? el.getPrevPaintRect() : null;

          if (prevRect) {
            addRectToMergePool(prevRect);
          }

          var curRect = shouldPaint && (el.__dirty & Element.REDARAW_BIT || !el.__isRendered) ? el.getPaintRect() : null;

          if (curRect) {
            addRectToMergePool(curRect);
          }
        }
      }

      for (var i = this.__prevStartIndex; i < this.__prevEndIndex; ++i) {
        var el = prevList[i];
        var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);

        if (el && (!shouldPaint || !el.__zr) && el.__isRendered) {
          var prevRect = el.getPrevPaintRect();

          if (prevRect) {
            addRectToMergePool(prevRect);
          }
        }
      }

      var hasIntersections;

      do {
        hasIntersections = false;

        for (var i = 0; i < mergedRepaintRects.length;) {
          if (mergedRepaintRects[i].isZero()) {
            mergedRepaintRects.splice(i, 1);
            continue;
          }

          for (var j = i + 1; j < mergedRepaintRects.length;) {
            if (mergedRepaintRects[i].intersect(mergedRepaintRects[j])) {
              hasIntersections = true;
              mergedRepaintRects[i].union(mergedRepaintRects[j]);
              mergedRepaintRects.splice(j, 1);
            } else {
              j++;
            }
          }

          i++;
        }
      } while (hasIntersections);

      this._paintRects = mergedRepaintRects;
      return mergedRepaintRects;
    };

    Layer.prototype.debugGetPaintRects = function () {
      return (this._paintRects || []).slice();
    };

    Layer.prototype.resize = function (width, height) {
      var dpr = this.dpr;
      var dom = this.dom;
      var domStyle = dom.style;
      var domBack = this.domBack;

      if (domStyle) {
        domStyle.width = width + 'px';
        domStyle.height = height + 'px';
      }

      dom.width = width * dpr;
      dom.height = height * dpr;

      if (domBack) {
        domBack.width = width * dpr;
        domBack.height = height * dpr;

        if (dpr !== 1) {
          this.ctxBack.scale(dpr, dpr);
        }
      }
    };

    Layer.prototype.clear = function (clearAll, clearColor, repaintRects) {
      var dom = this.dom;
      var ctx = this.ctx;
      var width = dom.width;
      var height = dom.height;
      clearColor = clearColor || this.clearColor;
      var haveMotionBLur = this.motionBlur && !clearAll;
      var lastFrameAlpha = this.lastFrameAlpha;
      var dpr = this.dpr;
      var self = this;

      if (haveMotionBLur) {
        if (!this.domBack) {
          this.createBackBuffer();
        }

        this.ctxBack.globalCompositeOperation = 'copy';
        this.ctxBack.drawImage(dom, 0, 0, width / dpr, height / dpr);
      }

      var domBack = this.domBack;

      function doClear(x, y, width, height) {
        ctx.clearRect(x, y, width, height);

        if (clearColor && clearColor !== 'transparent') {
          var clearColorGradientOrPattern = void 0;

          if (isGradientObject(clearColor)) {
            clearColorGradientOrPattern = clearColor.__canvasGradient || getCanvasGradient(ctx, clearColor, {
              x: 0,
              y: 0,
              width: width,
              height: height
            });
            clearColor.__canvasGradient = clearColorGradientOrPattern;
          } else if (isPatternObject(clearColor)) {
            clearColorGradientOrPattern = createCanvasPattern(ctx, clearColor, {
              dirty: function () {
                self.setUnpainted();

                self.__painter.refresh();
              }
            });
          }

          ctx.save();
          ctx.fillStyle = clearColorGradientOrPattern || clearColor;
          ctx.fillRect(x, y, width, height);
          ctx.restore();
        }

        if (haveMotionBLur) {
          ctx.save();
          ctx.globalAlpha = lastFrameAlpha;
          ctx.drawImage(domBack, x, y, width, height);
          ctx.restore();
        }
      }

      if (!repaintRects || haveMotionBLur) {
        doClear(0, 0, width, height);
      } else if (repaintRects.length) {
        each(repaintRects, function (rect) {
          doClear(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr);
        });
      }
    };

    return Layer;
  }(Eventful);

  var HOVER_LAYER_ZLEVEL = 1e5;
  var CANVAS_ZLEVEL = 314159;
  var EL_AFTER_INCREMENTAL_INC = 0.01;
  var INCREMENTAL_INC = 0.001;

  function parseInt10(val) {
    return parseInt(val, 10);
  }

  function isLayerValid(layer) {
    if (!layer) {
      return false;
    }

    if (layer.__builtin__) {
      return true;
    }

    if (typeof layer.resize !== 'function' || typeof layer.refresh !== 'function') {
      return false;
    }

    return true;
  }

  function createRoot(width, height) {
    var domRoot = document.createElement('div');
    domRoot.style.cssText = ['position:relative', 'width:' + width + 'px', 'height:' + height + 'px', 'padding:0', 'margin:0', 'border-width:0'].join(';') + ';';
    return domRoot;
  }

  var CanvasPainter = function () {
    function CanvasPainter(root, storage, opts, id) {
      this.type = 'canvas';
      this._zlevelList = [];
      this._prevDisplayList = [];
      this._layers = {};
      this._layerConfig = {};
      this._needsManuallyCompositing = false;
      this.type = 'canvas';
      var singleCanvas = !root.nodeName || root.nodeName.toUpperCase() === 'CANVAS';
      this._opts = opts = extend({}, opts || {});
      this.dpr = opts.devicePixelRatio || devicePixelRatio;
      this._singleCanvas = singleCanvas;
      this.root = root;
      var rootStyle = root.style;

      if (rootStyle) {
        rootStyle.webkitTapHighlightColor = 'transparent';
        rootStyle.webkitUserSelect = 'none';
        rootStyle.userSelect = 'none';
        rootStyle['-webkit-touch-callout'] = 'none';
        root.innerHTML = '';
      }

      this.storage = storage;
      var zlevelList = this._zlevelList;
      this._prevDisplayList = [];
      var layers = this._layers;

      if (!singleCanvas) {
        this._width = this._getSize(0);
        this._height = this._getSize(1);
        var domRoot = this._domRoot = createRoot(this._width, this._height);
        root.appendChild(domRoot);
      } else {
        var rootCanvas = root;
        var width = rootCanvas.width;
        var height = rootCanvas.height;

        if (opts.width != null) {
          width = opts.width;
        }

        if (opts.height != null) {
          height = opts.height;
        }

        this.dpr = opts.devicePixelRatio || 1;
        rootCanvas.width = width * this.dpr;
        rootCanvas.height = height * this.dpr;
        this._width = width;
        this._height = height;
        var mainLayer = new Layer(rootCanvas, this, this.dpr);
        mainLayer.__builtin__ = true;
        mainLayer.initContext();
        layers[CANVAS_ZLEVEL] = mainLayer;
        mainLayer.zlevel = CANVAS_ZLEVEL;
        zlevelList.push(CANVAS_ZLEVEL);
        this._domRoot = root;
      }
    }

    CanvasPainter.prototype.getType = function () {
      return 'canvas';
    };

    CanvasPainter.prototype.isSingleCanvas = function () {
      return this._singleCanvas;
    };

    CanvasPainter.prototype.getViewportRoot = function () {
      return this._domRoot;
    };

    CanvasPainter.prototype.getViewportRootOffset = function () {
      var viewportRoot = this.getViewportRoot();

      if (viewportRoot) {
        return {
          offsetLeft: viewportRoot.offsetLeft || 0,
          offsetTop: viewportRoot.offsetTop || 0
        };
      }
    };

    CanvasPainter.prototype.refresh = function (paintAll) {
      var list = this.storage.getDisplayList(true);
      var prevList = this._prevDisplayList;
      var zlevelList = this._zlevelList;
      this._redrawId = Math.random();

      this._paintList(list, prevList, paintAll, this._redrawId);

      for (var i = 0; i < zlevelList.length; i++) {
        var z = zlevelList[i];
        var layer = this._layers[z];

        if (!layer.__builtin__ && layer.refresh) {
          var clearColor = i === 0 ? this._backgroundColor : null;
          layer.refresh(clearColor);
        }
      }

      if (this._opts.useDirtyRect) {
        this._prevDisplayList = list.slice();
      }

      return this;
    };

    CanvasPainter.prototype.refreshHover = function () {
      this._paintHoverList(this.storage.getDisplayList(false));
    };

    CanvasPainter.prototype._paintHoverList = function (list) {
      var len = list.length;
      var hoverLayer = this._hoverlayer;
      hoverLayer && hoverLayer.clear();

      if (!len) {
        return;
      }

      var scope = {
        inHover: true,
        viewWidth: this._width,
        viewHeight: this._height
      };
      var ctx;

      for (var i = 0; i < len; i++) {
        var el = list[i];

        if (el.__inHover) {
          if (!hoverLayer) {
            hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL);
          }

          if (!ctx) {
            ctx = hoverLayer.ctx;
            ctx.save();
          }

          brush(ctx, el, scope, i === len - 1);
        }
      }

      if (ctx) {
        ctx.restore();
      }
    };

    CanvasPainter.prototype.getHoverLayer = function () {
      return this.getLayer(HOVER_LAYER_ZLEVEL);
    };

    CanvasPainter.prototype.paintOne = function (ctx, el) {
      brushSingle(ctx, el);
    };

    CanvasPainter.prototype._paintList = function (list, prevList, paintAll, redrawId) {
      if (this._redrawId !== redrawId) {
        return;
      }

      paintAll = paintAll || false;

      this._updateLayerStatus(list);

      var _a = this._doPaintList(list, prevList, paintAll),
          finished = _a.finished,
          needsRefreshHover = _a.needsRefreshHover;

      if (this._needsManuallyCompositing) {
        this._compositeManually();
      }

      if (needsRefreshHover) {
        this._paintHoverList(list);
      }

      if (!finished) {
        var self_1 = this;
        requestAnimationFrame$1(function () {
          self_1._paintList(list, prevList, paintAll, redrawId);
        });
      } else {
        this.eachLayer(function (layer) {
          layer.afterBrush && layer.afterBrush();
        });
      }
    };

    CanvasPainter.prototype._compositeManually = function () {
      var ctx = this.getLayer(CANVAS_ZLEVEL).ctx;
      var width = this._domRoot.width;
      var height = this._domRoot.height;
      ctx.clearRect(0, 0, width, height);
      this.eachBuiltinLayer(function (layer) {
        if (layer.virtual) {
          ctx.drawImage(layer.dom, 0, 0, width, height);
        }
      });
    };

    CanvasPainter.prototype._doPaintList = function (list, prevList, paintAll) {
      var _this = this;

      var layerList = [];
      var useDirtyRect = this._opts.useDirtyRect;

      for (var zi = 0; zi < this._zlevelList.length; zi++) {
        var zlevel = this._zlevelList[zi];
        var layer = this._layers[zlevel];

        if (layer.__builtin__ && layer !== this._hoverlayer && (layer.__dirty || paintAll)) {
          layerList.push(layer);
        }
      }

      var finished = true;
      var needsRefreshHover = false;

      var _loop_1 = function (k) {
        var layer = layerList[k];
        var ctx = layer.ctx;
        var repaintRects = useDirtyRect && layer.createRepaintRects(list, prevList, this_1._width, this_1._height);
        ctx.save();
        var start = paintAll ? layer.__startIndex : layer.__drawIndex;
        var useTimer = !paintAll && layer.incremental && Date.now;
        var startTime = useTimer && Date.now();
        var clearColor = layer.zlevel === this_1._zlevelList[0] ? this_1._backgroundColor : null;

        if (layer.__startIndex === layer.__endIndex) {
          layer.clear(false, clearColor, repaintRects);
        } else if (start === layer.__startIndex) {
          var firstEl = list[start];

          if (!firstEl.incremental || !firstEl.notClear || paintAll) {
            layer.clear(false, clearColor, repaintRects);
          }
        }

        if (start === -1) {
          console.error('For some unknown reason. drawIndex is -1');
          start = layer.__startIndex;
        }

        var i;

        var repaint = function (repaintRect) {
          var scope = {
            inHover: false,
            allClipped: false,
            prevEl: null,
            viewWidth: _this._width,
            viewHeight: _this._height
          };

          for (i = start; i < layer.__endIndex; i++) {
            var el = list[i];

            if (el.__inHover) {
              needsRefreshHover = true;
            }

            _this._doPaintEl(el, layer, useDirtyRect, repaintRect, scope, i === layer.__endIndex - 1);

            if (useTimer) {
              var dTime = Date.now() - startTime;

              if (dTime > 15) {
                break;
              }
            }
          }

          if (scope.prevElClipPaths) {
            ctx.restore();
          }
        };

        if (repaintRects) {
          if (repaintRects.length === 0) {
            i = layer.__endIndex;
          } else {
            var dpr = this_1.dpr;

            for (var r = 0; r < repaintRects.length; ++r) {
              var rect = repaintRects[r];
              ctx.save();
              ctx.beginPath();
              ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr);
              ctx.clip();
              repaint(rect);
              ctx.restore();
            }
          }
        } else {
          ctx.save();
          repaint();
          ctx.restore();
        }

        layer.__drawIndex = i;

        if (layer.__drawIndex < layer.__endIndex) {
          finished = false;
        }
      };

      var this_1 = this;

      for (var k = 0; k < layerList.length; k++) {
        _loop_1(k);
      }

      if (env.wxa) {
        each(this._layers, function (layer) {
          if (layer && layer.ctx && layer.ctx.draw) {
            layer.ctx.draw();
          }
        });
      }

      return {
        finished: finished,
        needsRefreshHover: needsRefreshHover
      };
    };

    CanvasPainter.prototype._doPaintEl = function (el, currentLayer, useDirtyRect, repaintRect, scope, isLast) {
      var ctx = currentLayer.ctx;

      if (useDirtyRect) {
        var paintRect = el.getPaintRect();

        if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) {
          brush(ctx, el, scope, isLast);
          el.setPrevPaintRect(paintRect);
        }
      } else {
        brush(ctx, el, scope, isLast);
      }
    };

    CanvasPainter.prototype.getLayer = function (zlevel, virtual) {
      if (this._singleCanvas && !this._needsManuallyCompositing) {
        zlevel = CANVAS_ZLEVEL;
      }

      var layer = this._layers[zlevel];

      if (!layer) {
        layer = new Layer('zr_' + zlevel, this, this.dpr);
        layer.zlevel = zlevel;
        layer.__builtin__ = true;

        if (this._layerConfig[zlevel]) {
          merge(layer, this._layerConfig[zlevel], true);
        } else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) {
          merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true);
        }

        if (virtual) {
          layer.virtual = virtual;
        }

        this.insertLayer(zlevel, layer);
        layer.initContext();
      }

      return layer;
    };

    CanvasPainter.prototype.insertLayer = function (zlevel, layer) {
      var layersMap = this._layers;
      var zlevelList = this._zlevelList;
      var len = zlevelList.length;
      var domRoot = this._domRoot;
      var prevLayer = null;
      var i = -1;

      if (layersMap[zlevel]) {
        logError('ZLevel ' + zlevel + ' has been used already');
        return;
      }

      if (!isLayerValid(layer)) {
        logError('Layer of zlevel ' + zlevel + ' is not valid');
        return;
      }

      if (len > 0 && zlevel > zlevelList[0]) {
        for (i = 0; i < len - 1; i++) {
          if (zlevelList[i] < zlevel && zlevelList[i + 1] > zlevel) {
            break;
          }
        }

        prevLayer = layersMap[zlevelList[i]];
      }

      zlevelList.splice(i + 1, 0, zlevel);
      layersMap[zlevel] = layer;

      if (!layer.virtual) {
        if (prevLayer) {
          var prevDom = prevLayer.dom;

          if (prevDom.nextSibling) {
            domRoot.insertBefore(layer.dom, prevDom.nextSibling);
          } else {
            domRoot.appendChild(layer.dom);
          }
        } else {
          if (domRoot.firstChild) {
            domRoot.insertBefore(layer.dom, domRoot.firstChild);
          } else {
            domRoot.appendChild(layer.dom);
          }
        }
      }

      layer.__painter = this;
    };

    CanvasPainter.prototype.eachLayer = function (cb, context) {
      var zlevelList = this._zlevelList;

      for (var i = 0; i < zlevelList.length; i++) {
        var z = zlevelList[i];
        cb.call(context, this._layers[z], z);
      }
    };

    CanvasPainter.prototype.eachBuiltinLayer = function (cb, context) {
      var zlevelList = this._zlevelList;

      for (var i = 0; i < zlevelList.length; i++) {
        var z = zlevelList[i];
        var layer = this._layers[z];

        if (layer.__builtin__) {
          cb.call(context, layer, z);
        }
      }
    };

    CanvasPainter.prototype.eachOtherLayer = function (cb, context) {
      var zlevelList = this._zlevelList;

      for (var i = 0; i < zlevelList.length; i++) {
        var z = zlevelList[i];
        var layer = this._layers[z];

        if (!layer.__builtin__) {
          cb.call(context, layer, z);
        }
      }
    };

    CanvasPainter.prototype.getLayers = function () {
      return this._layers;
    };

    CanvasPainter.prototype._updateLayerStatus = function (list) {
      this.eachBuiltinLayer(function (layer, z) {
        layer.__dirty = layer.__used = false;
      });

      function updatePrevLayer(idx) {
        if (prevLayer) {
          if (prevLayer.__endIndex !== idx) {
            prevLayer.__dirty = true;
          }

          prevLayer.__endIndex = idx;
        }
      }

      if (this._singleCanvas) {
        for (var i_1 = 1; i_1 < list.length; i_1++) {
          var el = list[i_1];

          if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) {
            this._needsManuallyCompositing = true;
            break;
          }
        }
      }

      var prevLayer = null;
      var incrementalLayerCount = 0;
      var prevZlevel;
      var i;

      for (i = 0; i < list.length; i++) {
        var el = list[i];
        var zlevel = el.zlevel;
        var layer = void 0;

        if (prevZlevel !== zlevel) {
          prevZlevel = zlevel;
          incrementalLayerCount = 0;
        }

        if (el.incremental) {
          layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing);
          layer.incremental = true;
          incrementalLayerCount = 1;
        } else {
          layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing);
        }

        if (!layer.__builtin__) {
          logError('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id);
        }

        if (layer !== prevLayer) {
          layer.__used = true;

          if (layer.__startIndex !== i) {
            layer.__dirty = true;
          }

          layer.__startIndex = i;

          if (!layer.incremental) {
            layer.__drawIndex = i;
          } else {
            layer.__drawIndex = -1;
          }

          updatePrevLayer(i);
          prevLayer = layer;
        }

        if (el.__dirty & Element.REDARAW_BIT && !el.__inHover) {
          layer.__dirty = true;

          if (layer.incremental && layer.__drawIndex < 0) {
            layer.__drawIndex = i;
          }
        }
      }

      updatePrevLayer(i);
      this.eachBuiltinLayer(function (layer, z) {
        if (!layer.__used && layer.getElementCount() > 0) {
          layer.__dirty = true;
          layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0;
        }

        if (layer.__dirty && layer.__drawIndex < 0) {
          layer.__drawIndex = layer.__startIndex;
        }
      });
    };

    CanvasPainter.prototype.clear = function () {
      this.eachBuiltinLayer(this._clearLayer);
      return this;
    };

    CanvasPainter.prototype._clearLayer = function (layer) {
      layer.clear();
    };

    CanvasPainter.prototype.setBackgroundColor = function (backgroundColor) {
      this._backgroundColor = backgroundColor;
      each(this._layers, function (layer) {
        layer.setUnpainted();
      });
    };

    CanvasPainter.prototype.configLayer = function (zlevel, config) {
      if (config) {
        var layerConfig = this._layerConfig;

        if (!layerConfig[zlevel]) {
          layerConfig[zlevel] = config;
        } else {
          merge(layerConfig[zlevel], config, true);
        }

        for (var i = 0; i < this._zlevelList.length; i++) {
          var _zlevel = this._zlevelList[i];

          if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) {
            var layer = this._layers[_zlevel];
            merge(layer, layerConfig[zlevel], true);
          }
        }
      }
    };

    CanvasPainter.prototype.delLayer = function (zlevel) {
      var layers = this._layers;
      var zlevelList = this._zlevelList;
      var layer = layers[zlevel];

      if (!layer) {
        return;
      }

      layer.dom.parentNode.removeChild(layer.dom);
      delete layers[zlevel];
      zlevelList.splice(indexOf(zlevelList, zlevel), 1);
    };

    CanvasPainter.prototype.resize = function (width, height) {
      if (!this._domRoot.style) {
        if (width == null || height == null) {
          return;
        }

        this._width = width;
        this._height = height;
        this.getLayer(CANVAS_ZLEVEL).resize(width, height);
      } else {
        var domRoot = this._domRoot;
        domRoot.style.display = 'none';
        var opts = this._opts;
        width != null && (opts.width = width);
        height != null && (opts.height = height);
        width = this._getSize(0);
        height = this._getSize(1);
        domRoot.style.display = '';

        if (this._width !== width || height !== this._height) {
          domRoot.style.width = width + 'px';
          domRoot.style.height = height + 'px';

          for (var id in this._layers) {
            if (this._layers.hasOwnProperty(id)) {
              this._layers[id].resize(width, height);
            }
          }

          this.refresh(true);
        }

        this._width = width;
        this._height = height;
      }

      return this;
    };

    CanvasPainter.prototype.clearLayer = function (zlevel) {
      var layer = this._layers[zlevel];

      if (layer) {
        layer.clear();
      }
    };

    CanvasPainter.prototype.dispose = function () {
      this.root.innerHTML = '';
      this.root = this.storage = this._domRoot = this._layers = null;
    };

    CanvasPainter.prototype.getRenderedCanvas = function (opts) {
      opts = opts || {};

      if (this._singleCanvas && !this._compositeManually) {
        return this._layers[CANVAS_ZLEVEL].dom;
      }

      var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr);
      var ctx = imageLayer.ctx;
      imageLayer.initContext();
      imageLayer.clear(false, opts.backgroundColor || this._backgroundColor);

      if (opts.pixelRatio <= this.dpr) {
        this.refresh();
        var width_1 = imageLayer.dom.width;
        var height_1 = imageLayer.dom.height;
        var ctx_1 = imageLayer.ctx;
        this.eachLayer(function (layer) {
          if (layer.__builtin__) {
            ctx_1.drawImage(layer.dom, 0, 0, width_1, height_1);
          } else if (layer.renderToCanvas) {
            imageLayer.ctx.save();
            layer.renderToCanvas(imageLayer.ctx);
            imageLayer.ctx.restore();
          }
        });
      } else {
        var scope = {
          inHover: false,
          viewWidth: this._width,
          viewHeight: this._height
        };
        var displayList = this.storage.getDisplayList(true);

        for (var i = 0, len = displayList.length; i < len; i++) {
          var el = displayList[i];
          brush(ctx, el, scope, i === len - 1);
        }
      }

      return imageLayer.dom;
    };

    CanvasPainter.prototype.getWidth = function () {
      return this._width;
    };

    CanvasPainter.prototype.getHeight = function () {
      return this._height;
    };

    CanvasPainter.prototype._getSize = function (whIdx) {
      var opts = this._opts;
      var wh = ['width', 'height'][whIdx];
      var cwh = ['clientWidth', 'clientHeight'][whIdx];
      var plt = ['paddingLeft', 'paddingTop'][whIdx];
      var prb = ['paddingRight', 'paddingBottom'][whIdx];

      if (opts[wh] != null && opts[wh] !== 'auto') {
        return parseFloat(opts[wh]);
      }

      var root = this.root;
      var stl = document.defaultView.getComputedStyle(root);
      return (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) - (parseInt10(stl[plt]) || 0) - (parseInt10(stl[prb]) || 0) | 0;
    };

    CanvasPainter.prototype.pathToImage = function (path, dpr) {
      dpr = dpr || this.dpr;
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      var rect = path.getBoundingRect();
      var style = path.style;
      var shadowBlurSize = style.shadowBlur * dpr;
      var shadowOffsetX = style.shadowOffsetX * dpr;
      var shadowOffsetY = style.shadowOffsetY * dpr;
      var lineWidth = path.hasStroke() ? style.lineWidth : 0;
      var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize);
      var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize);
      var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize);
      var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize);
      var width = rect.width + leftMargin + rightMargin;
      var height = rect.height + topMargin + bottomMargin;
      canvas.width = width * dpr;
      canvas.height = height * dpr;
      ctx.scale(dpr, dpr);
      ctx.clearRect(0, 0, width, height);
      ctx.dpr = dpr;
      var pathTransform = {
        x: path.x,
        y: path.y,
        scaleX: path.scaleX,
        scaleY: path.scaleY,
        rotation: path.rotation,
        originX: path.originX,
        originY: path.originY
      };
      path.x = leftMargin - rect.x;
      path.y = topMargin - rect.y;
      path.rotation = 0;
      path.scaleX = 1;
      path.scaleY = 1;
      path.updateTransform();

      if (path) {
        brush(ctx, path, {
          inHover: false,
          viewWidth: this._width,
          viewHeight: this._height
        }, true);
      }

      var imgShape = new ZRImage({
        style: {
          x: 0,
          y: 0,
          image: canvas
        }
      });
      extend(path, pathTransform);
      return imgShape;
    };

    return CanvasPainter;
  }();

  registerPainter('canvas', CanvasPainter);

  function findEventDispatcher(target, det, returnFirstMatch) {
    var found;

    while (target) {
      if (det(target)) {
        found = target;

        if (returnFirstMatch) {
          break;
        }
      }

      target = target.__hostTarget || target.parent;
    }

    return found;
  }

  var wmUniqueIndex = Math.round(Math.random() * 9);

  var WeakMap = function () {
    function WeakMap() {
      this._id = '__ec_inner_' + wmUniqueIndex++;
    }

    WeakMap.prototype.get = function (key) {
      return this._guard(key)[this._id];
    };

    WeakMap.prototype.set = function (key, value) {
      var target = this._guard(key);

      if (typeof Object.defineProperty === 'function') {
        Object.defineProperty(target, this._id, {
          value: value,
          enumerable: false,
          configurable: true
        });
      } else {
        target[this._id] = value;
      }

      return this;
    };

    WeakMap.prototype["delete"] = function (key) {
      if (this.has(key)) {
        delete this._guard(key)[this._id];
        return true;
      }

      return false;
    };

    WeakMap.prototype.has = function (key) {
      return !!this._guard(key)[this._id];
    };

    WeakMap.prototype._guard = function (key) {
      if (key !== Object(key)) {
        throw TypeError('Value of WeakMap is not a non-null object.');
      }

      return key;
    };

    return WeakMap;
  }();

  var Triangle = Path.extend({
    type: 'triangle',
    shape: {
      cx: 0,
      cy: 0,
      width: 0,
      height: 0
    },
    buildPath: function (path, shape) {
      var cx = shape.cx;
      var cy = shape.cy;
      var width = shape.width / 2;
      var height = shape.height / 2;
      path.moveTo(cx, cy - height);
      path.lineTo(cx + width, cy + height);
      path.lineTo(cx - width, cy + height);
      path.closePath();
    }
  });
  var Diamond = Path.extend({
    type: 'diamond',
    shape: {
      cx: 0,
      cy: 0,
      width: 0,
      height: 0
    },
    buildPath: function (path, shape) {
      var cx = shape.cx;
      var cy = shape.cy;
      var width = shape.width / 2;
      var height = shape.height / 2;
      path.moveTo(cx, cy - height);
      path.lineTo(cx + width, cy);
      path.lineTo(cx, cy + height);
      path.lineTo(cx - width, cy);
      path.closePath();
    }
  });
  var Pin = Path.extend({
    type: 'pin',
    shape: {
      x: 0,
      y: 0,
      width: 0,
      height: 0
    },
    buildPath: function (path, shape) {
      var x = shape.x;
      var y = shape.y;
      var w = shape.width / 5 * 3;
      var h = Math.max(w, shape.height);
      var r = w / 2;
      var dy = r * r / (h - r);
      var cy = y - h + r + dy;
      var angle = Math.asin(dy / r);
      var dx = Math.cos(angle) * r;
      var tanX = Math.sin(angle);
      var tanY = Math.cos(angle);
      var cpLen = r * 0.6;
      var cpLen2 = r * 0.7;
      path.moveTo(x - dx, cy + dy);
      path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle);
      path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y);
      path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy);
      path.closePath();
    }
  });
  var Arrow = Path.extend({
    type: 'arrow',
    shape: {
      x: 0,
      y: 0,
      width: 0,
      height: 0
    },
    buildPath: function (ctx, shape) {
      var height = shape.height;
      var width = shape.width;
      var x = shape.x;
      var y = shape.y;
      var dx = width / 3 * 2;
      ctx.moveTo(x, y);
      ctx.lineTo(x + dx, y + height);
      ctx.lineTo(x, y + height / 4 * 3);
      ctx.lineTo(x - dx, y + height);
      ctx.lineTo(x, y);
      ctx.closePath();
    }
  });
  var symbolCtors = {
    line: Rect,
    rect: Rect,
    roundRect: Rect,
    square: Rect,
    circle: Circle,
    diamond: Diamond,
    pin: Pin,
    arrow: Arrow,
    triangle: Triangle
  };
  var symbolShapeMakers = {
    line: function (x, y, w, h, shape) {
      var thickness = 2;
      shape.x = x;
      shape.y = y + h / 2 - thickness / 2;
      shape.width = w;
      shape.height = thickness;
    },
    rect: function (x, y, w, h, shape) {
      shape.x = x;
      shape.y = y;
      shape.width = w;
      shape.height = h;
    },
    roundRect: function (x, y, w, h, shape) {
      shape.x = x;
      shape.y = y;
      shape.width = w;
      shape.height = h;
      shape.r = Math.min(w, h) / 4;
    },
    square: function (x, y, w, h, shape) {
      var size = Math.min(w, h);
      shape.x = x;
      shape.y = y;
      shape.width = size;
      shape.height = size;
    },
    circle: function (x, y, w, h, shape) {
      shape.cx = x + w / 2;
      shape.cy = y + h / 2;
      shape.r = Math.min(w, h) / 2;
    },
    diamond: function (x, y, w, h, shape) {
      shape.cx = x + w / 2;
      shape.cy = y + h / 2;
      shape.width = w;
      shape.height = h;
    },
    pin: function (x, y, w, h, shape) {
      shape.x = x + w / 2;
      shape.y = y + h / 2;
      shape.width = w;
      shape.height = h;
    },
    arrow: function (x, y, w, h, shape) {
      shape.x = x + w / 2;
      shape.y = y + h / 2;
      shape.width = w;
      shape.height = h;
    },
    triangle: function (x, y, w, h, shape) {
      shape.cx = x + w / 2;
      shape.cy = y + h / 2;
      shape.width = w;
      shape.height = h;
    }
  };
  var symbolBuildProxies = {};
  each(symbolCtors, function (Ctor, name) {
    symbolBuildProxies[name] = new Ctor();
  });
  var SymbolClz = Path.extend({
    type: 'symbol',
    shape: {
      symbolType: '',
      x: 0,
      y: 0,
      width: 0,
      height: 0
    },
    calculateTextPosition: function (out, config, rect) {
      var res = calculateTextPosition(out, config, rect);
      var shape = this.shape;

      if (shape && shape.symbolType === 'pin' && config.position === 'inside') {
        res.y = rect.y + rect.height * 0.4;
      }

      return res;
    },
    buildPath: function (ctx, shape, inBundle) {
      var symbolType = shape.symbolType;

      if (symbolType !== 'none') {
        var proxySymbol = symbolBuildProxies[symbolType];

        if (!proxySymbol) {
          symbolType = 'rect';
          proxySymbol = symbolBuildProxies[symbolType];
        }

        symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape);
        proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
      }
    }
  });

  function symbolPathSetColor(color, innerColor) {
    if (this.type !== 'image') {
      var symbolStyle = this.style;

      if (this.__isEmptyBrush) {
        symbolStyle.stroke = color;
        symbolStyle.fill = innerColor || '#fff';
        symbolStyle.lineWidth = 2;
      } else {
        symbolStyle.fill = color;
      }

      this.markRedraw();
    }
  }

  function createSymbol(symbolType, x, y, w, h, color, keepAspect) {
    var isEmpty = symbolType.indexOf('empty') === 0;

    if (isEmpty) {
      symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
    }

    var symbolPath;

    if (symbolType.indexOf('image://') === 0) {
      symbolPath = makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
    } else if (symbolType.indexOf('path://') === 0) {
      symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
    } else {
      symbolPath = new SymbolClz({
        shape: {
          symbolType: symbolType,
          x: x,
          y: y,
          width: w,
          height: h
        }
      });
    }

    symbolPath.__isEmptyBrush = isEmpty;
    symbolPath.setColor = symbolPathSetColor;

    if (color) {
      symbolPath.setColor(color);
    }

    return symbolPath;
  }

  var decalMap = new WeakMap();
  var decalCache = new LRU(100);
  var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'dashLineOffset', 'maxTileWidth', 'maxTileHeight'];

  function createOrUpdatePatternFromDecal(decalObject, api) {
    if (decalObject === 'none') {
      return null;
    }

    var dpr = api.getDevicePixelRatio();
    var zr = api.getZr();
    var isSVG = zr.painter.type === 'svg';

    if (decalObject.dirty) {
      decalMap["delete"](decalObject);
    }

    var oldPattern = decalMap.get(decalObject);

    if (oldPattern) {
      return oldPattern;
    }

    var decalOpt = defaults(decalObject, {
      symbol: 'rect',
      symbolSize: 1,
      symbolKeepAspect: true,
      color: 'rgba(0, 0, 0, 0.2)',
      backgroundColor: null,
      dashArrayX: 5,
      dashArrayY: 5,
      dashLineOffset: 0,
      rotation: 0,
      maxTileWidth: 512,
      maxTileHeight: 512
    });

    if (decalOpt.backgroundColor === 'none') {
      decalOpt.backgroundColor = null;
    }

    var pattern = {
      repeat: 'repeat'
    };
    setPatternnSource(pattern);
    pattern.rotation = decalOpt.rotation;
    pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr;
    decalMap.set(decalObject, pattern);
    decalObject.dirty = false;
    return pattern;

    function setPatternnSource(pattern) {
      var keys = [dpr];
      var isValidKey = true;

      for (var i = 0; i < decalKeys.length; ++i) {
        var value = decalOpt[decalKeys[i]];
        var valueType = typeof value;

        if (value != null && !isArray(value) && valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') {
          isValidKey = false;
          break;
        }

        keys.push(value);
      }

      var cacheKey;

      if (isValidKey) {
        cacheKey = keys.join(',') + (isSVG ? '-svg' : '');
        var cache = decalCache.get(cacheKey);

        if (cache) {
          isSVG ? pattern.svgElement = cache : pattern.image = cache;
        }
      }

      var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX);
      var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY);
      var symbolArray = normalizeSymbolArray(decalOpt.symbol);
      var lineBlockLengthsX = getLineBlockLengthX(dashArrayX);
      var lineBlockLengthY = getLineBlockLengthY(dashArrayY);
      var canvas = !isSVG && createCanvas();
      var svgRoot = isSVG && zr.painter.createSVGElement('g');
      var pSize = getPatternSize();
      var ctx;

      if (canvas) {
        canvas.width = pSize.width * dpr;
        canvas.height = pSize.height * dpr;
        ctx = canvas.getContext('2d');
      }

      brushDecal();

      if (isValidKey) {
        decalCache.put(cacheKey, canvas || svgRoot);
      }

      pattern.image = canvas;
      pattern.svgElement = svgRoot;
      pattern.svgWidth = pSize.width;
      pattern.svgHeight = pSize.height;

      function getPatternSize() {
        var width = 1;

        for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) {
          width = getLeastCommonMultiple(width, lineBlockLengthsX[i]);
        }

        var symbolRepeats = 1;

        for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) {
          symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length);
        }

        width *= symbolRepeats;
        var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length;

        if (true) {
          var warn = function (attrName) {
            console.warn("Calculated decal size is greater than " + attrName + " due to decal option settings so " + attrName + " is used for the decal size. Please consider changing the decal option to make a smaller decal or set " + attrName + " to be larger to avoid incontinuity.");
          };

          if (width > decalOpt.maxTileWidth) {
            warn('maxTileWidth');
          }

          if (height > decalOpt.maxTileHeight) {
            warn('maxTileHeight');
          }
        }

        return {
          width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)),
          height: Math.max(1, Math.min(height, decalOpt.maxTileHeight))
        };
      }

      function brushDecal() {
        if (ctx) {
          ctx.clearRect(0, 0, canvas.width, canvas.height);

          if (decalOpt.backgroundColor) {
            ctx.fillStyle = decalOpt.backgroundColor;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
          }
        }

        var ySum = 0;

        for (var i = 0; i < dashArrayY.length; ++i) {
          ySum += dashArrayY[i];
        }

        if (ySum <= 0) {
          return;
        }

        var y = -lineBlockLengthY;
        var yId = 0;
        var yIdTotal = 0;
        var xId0 = 0;

        while (y < pSize.height) {
          if (yId % 2 === 0) {
            var symbolYId = yIdTotal / 2 % symbolArray.length;
            var x = 0;
            var xId1 = 0;
            var xId1Total = 0;

            while (x < pSize.width * 2) {
              var xSum = 0;

              for (var i = 0; i < dashArrayX[xId0].length; ++i) {
                xSum += dashArrayX[xId0][i];
              }

              if (xSum <= 0) {
                break;
              }

              if (xId1 % 2 === 0) {
                var size = (1 - decalOpt.symbolSize) * 0.5;
                var left = x + dashArrayX[xId0][xId1] * size;
                var top_1 = y + dashArrayY[yId] * size;
                var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize;
                var height = dashArrayY[yId] * decalOpt.symbolSize;
                var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length;
                brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]);
              }

              x += dashArrayX[xId0][xId1];
              ++xId1Total;
              ++xId1;

              if (xId1 === dashArrayX[xId0].length) {
                xId1 = 0;
              }
            }

            ++xId0;

            if (xId0 === dashArrayX.length) {
              xId0 = 0;
            }
          }

          y += dashArrayY[yId];
          ++yIdTotal;
          ++yId;

          if (yId === dashArrayY.length) {
            yId = 0;
          }
        }

        function brushSymbol(x, y, width, height, symbolType) {
          var scale = isSVG ? 1 : dpr;
          var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect);

          if (isSVG) {
            svgRoot.appendChild(zr.painter.paintOne(symbol));
          } else {
            brushSingle(ctx, symbol);
          }
        }
      }
    }
  }

  function normalizeSymbolArray(symbol) {
    if (!symbol || symbol.length === 0) {
      return [['rect']];
    }

    if (typeof symbol === 'string') {
      return [[symbol]];
    }

    var isAllString = true;

    for (var i = 0; i < symbol.length; ++i) {
      if (typeof symbol[i] !== 'string') {
        isAllString = false;
        break;
      }
    }

    if (isAllString) {
      return normalizeSymbolArray([symbol]);
    }

    var result = [];

    for (var i = 0; i < symbol.length; ++i) {
      if (typeof symbol[i] === 'string') {
        result.push([symbol[i]]);
      } else {
        result.push(symbol[i]);
      }
    }

    return result;
  }

  function normalizeDashArrayX(dash) {
    if (!dash || dash.length === 0) {
      return [[0, 0]];
    }

    if (typeof dash === 'number') {
      var dashValue = Math.ceil(dash);
      return [[dashValue, dashValue]];
    }

    var isAllNumber = true;

    for (var i = 0; i < dash.length; ++i) {
      if (typeof dash[i] !== 'number') {
        isAllNumber = false;
        break;
      }
    }

    if (isAllNumber) {
      return normalizeDashArrayX([dash]);
    }

    var result = [];

    for (var i = 0; i < dash.length; ++i) {
      if (typeof dash[i] === 'number') {
        var dashValue = Math.ceil(dash[i]);
        result.push([dashValue, dashValue]);
      } else {
        var dashValue = map(dash[i], function (n) {
          return Math.ceil(n);
        });

        if (dashValue.length % 2 === 1) {
          result.push(dashValue.concat(dashValue));
        } else {
          result.push(dashValue);
        }
      }
    }

    return result;
  }

  function normalizeDashArrayY(dash) {
    if (!dash || typeof dash === 'object' && dash.length === 0) {
      return [0, 0];
    }

    if (typeof dash === 'number') {
      var dashValue_1 = Math.ceil(dash);
      return [dashValue_1, dashValue_1];
    }

    var dashValue = map(dash, function (n) {
      return Math.ceil(n);
    });
    return dash.length % 2 ? dashValue.concat(dashValue) : dashValue;
  }

  function getLineBlockLengthX(dash) {
    return map(dash, function (line) {
      return getLineBlockLengthY(line);
    });
  }

  function getLineBlockLengthY(dash) {
    var blockLength = 0;

    for (var i = 0; i < dash.length; ++i) {
      blockLength += dash[i];
    }

    if (dash.length % 2 === 1) {
      return blockLength * 2;
    }

    return blockLength;
  }

  function decalVisual(ecModel, api) {
    ecModel.eachRawSeries(function (seriesModel) {
      if (ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      var data = seriesModel.getData();

      if (data.hasItemVisual()) {
        data.each(function (idx) {
          var decal = data.getItemVisual(idx, 'decal');

          if (decal) {
            var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
            itemStyle.decal = createOrUpdatePatternFromDecal(decal, api);
          }
        });
      }

      var decal = data.getVisual('decal');

      if (decal) {
        var style = data.getVisual('style');
        style.decal = createOrUpdatePatternFromDecal(decal, api);
      }
    });
  }

  var assert$1 = assert;
  var each$3 = each;
  var isFunction$1 = isFunction;
  var isObject$2 = isObject;
  var version$1 = '5.0.0';
  var dependencies = {
    zrender: '5.0.1'
  };
  var TEST_FRAME_REMAIN_TIME = 1;
  var PRIORITY_PROCESSOR_SERIES_FILTER = 800;
  var PRIORITY_PROCESSOR_DATASTACK = 900;
  var PRIORITY_PROCESSOR_FILTER = 1000;
  var PRIORITY_PROCESSOR_DEFAULT = 2000;
  var PRIORITY_PROCESSOR_STATISTIC = 5000;
  var PRIORITY_VISUAL_LAYOUT = 1000;
  var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
  var PRIORITY_VISUAL_GLOBAL = 2000;
  var PRIORITY_VISUAL_CHART = 3000;
  var PRIORITY_VISUAL_COMPONENT = 4000;
  var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500;
  var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
  var PRIORITY_VISUAL_BRUSH = 5000;
  var PRIORITY_VISUAL_ARIA = 6000;
  var PRIORITY_VISUAL_DECAL = 7000;
  var PRIORITY = {
    PROCESSOR: {
      FILTER: PRIORITY_PROCESSOR_FILTER,
      SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
      STATISTIC: PRIORITY_PROCESSOR_STATISTIC
    },
    VISUAL: {
      LAYOUT: PRIORITY_VISUAL_LAYOUT,
      PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
      GLOBAL: PRIORITY_VISUAL_GLOBAL,
      CHART: PRIORITY_VISUAL_CHART,
      POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
      COMPONENT: PRIORITY_VISUAL_COMPONENT,
      BRUSH: PRIORITY_VISUAL_BRUSH,
      CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
      ARIA: PRIORITY_VISUAL_ARIA,
      DECAL: PRIORITY_VISUAL_DECAL
    }
  };
  var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
  var OPTION_UPDATED_KEY = '__optionUpdated';
  var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
  var ACTION_REG = /^[a-zA-Z0-9_]+$/;
  var CONNECT_STATUS_KEY = '__connectUpdateStatus';
  var CONNECT_STATUS_PENDING = 0;
  var CONNECT_STATUS_UPDATING = 1;
  var CONNECT_STATUS_UPDATED = 2;

  function createRegisterEventWithLowercaseECharts(method) {
    return function () {
      var args = [];

      for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
      }

      if (this.isDisposed()) {
        disposedWarning(this.id);
        return;
      }

      return toLowercaseNameAndCallEventful(this, method, args);
    };
  }

  function createRegisterEventWithLowercaseMessageCenter(method) {
    return function () {
      var args = [];

      for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
      }

      return toLowercaseNameAndCallEventful(this, method, args);
    };
  }

  function toLowercaseNameAndCallEventful(host, method, args) {
    args[0] = args[0] && args[0].toLowerCase();
    return Eventful.prototype[method].apply(host, args);
  }

  var MessageCenter = function (_super) {
    __extends(MessageCenter, _super);

    function MessageCenter() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    return MessageCenter;
  }(Eventful);

  var messageCenterProto = MessageCenter.prototype;
  messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
  messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off');
  var prepare;
  var prepareView;
  var updateDirectly;
  var updateMethods;
  var doConvertPixel;
  var updateStreamModes;
  var doDispatchAction;
  var flushPendingActions;
  var triggerUpdatedEvent;
  var bindRenderedEvent;
  var bindMouseEvent;
  var clearColorPalette;
  var render;
  var renderComponents;
  var renderSeries;
  var performPostUpdateFuncs;
  var createExtensionAPI;
  var enableConnect;
  var setTransitionOpt;
  var markStatusToUpdate;
  var applyChangedStates;

  var ECharts = function (_super) {
    __extends(ECharts, _super);

    function ECharts(dom, theme, opts) {
      var _this = _super.call(this, new ECEventProcessor()) || this;

      _this._chartsViews = [];
      _this._chartsMap = {};
      _this._componentsViews = [];
      _this._componentsMap = {};
      _this._pendingActions = [];
      opts = opts || {};

      if (typeof theme === 'string') {
        theme = themeStorage[theme];
      }

      _this._dom = dom;
      var root = typeof window === 'undefined' ? global : window;
      var defaultRenderer = 'canvas';
      var defaultUseDirtyRect = false;

      if (true) {
        defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;
        var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__;
        defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect;
      }

      var zr = _this._zr = init(dom, {
        renderer: opts.renderer || defaultRenderer,
        devicePixelRatio: opts.devicePixelRatio,
        width: opts.width,
        height: opts.height,
        useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
      });
      _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
      theme = clone(theme);
      theme && globalBackwardCompat(theme, true);
      _this._theme = theme;
      _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
      _this._coordSysMgr = new CoordinateSystemManager();
      var api = _this._api = createExtensionAPI(_this);

      function prioritySortFunc(a, b) {
        return a.__prio - b.__prio;
      }

      sort(visualFuncs, prioritySortFunc);
      sort(dataProcessorFuncs, prioritySortFunc);
      _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs);
      _this._messageCenter = new MessageCenter();
      _this._labelManager = new LabelManager();

      _this._initEvents();

      _this.resize = bind(_this.resize, _this);
      zr.animation.on('frame', _this._onframe, _this);
      bindRenderedEvent(zr, _this);
      bindMouseEvent(zr, _this);
      setAsPrimitive(_this);
      return _this;
    }

    ECharts.prototype._onframe = function () {
      if (this._disposed) {
        return;
      }

      applyChangedStates(this);
      var scheduler = this._scheduler;

      if (this[OPTION_UPDATED_KEY]) {
        var silent = this[OPTION_UPDATED_KEY].silent;
        this[IN_MAIN_PROCESS_KEY] = true;
        prepare(this);
        updateMethods.update.call(this);

        this._zr.flush();

        this[IN_MAIN_PROCESS_KEY] = false;
        this[OPTION_UPDATED_KEY] = false;
        flushPendingActions.call(this, silent);
        triggerUpdatedEvent.call(this, silent);
      } else if (scheduler.unfinished) {
        var remainTime = TEST_FRAME_REMAIN_TIME;
        var ecModel = this._model;
        var api = this._api;
        scheduler.unfinished = false;

        do {
          var startTime = +new Date();
          scheduler.performSeriesTasks(ecModel);
          scheduler.performDataProcessorTasks(ecModel);
          updateStreamModes(this, ecModel);
          scheduler.performVisualTasks(ecModel);
          renderSeries(this, this._model, api, 'remain');
          remainTime -= +new Date() - startTime;
        } while (remainTime > 0 && scheduler.unfinished);

        if (!scheduler.unfinished) {
          this._zr.flush();
        }
      }
    };

    ECharts.prototype.getDom = function () {
      return this._dom;
    };

    ECharts.prototype.getId = function () {
      return this.id;
    };

    ECharts.prototype.getZr = function () {
      return this._zr;
    };

    ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
      if (true) {
        assert$1(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.');
      }

      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      var silent;
      var replaceMerge;
      var transitionOpt;

      if (isObject$2(notMerge)) {
        lazyUpdate = notMerge.lazyUpdate;
        silent = notMerge.silent;
        replaceMerge = notMerge.replaceMerge;
        transitionOpt = notMerge.transition;
        notMerge = notMerge.notMerge;
      }

      this[IN_MAIN_PROCESS_KEY] = true;

      if (!this._model || notMerge) {
        var optionManager = new OptionManager(this._api);
        var theme = this._theme;
        var ecModel = this._model = new GlobalModel();
        ecModel.scheduler = this._scheduler;
        ecModel.init(null, null, null, theme, this._locale, optionManager);
      }

      this._model.setOption(option, {
        replaceMerge: replaceMerge
      }, optionPreprocessorFuncs);

      setTransitionOpt(this, transitionOpt);

      if (lazyUpdate) {
        this[OPTION_UPDATED_KEY] = {
          silent: silent
        };
        this[IN_MAIN_PROCESS_KEY] = false;
        this.getZr().wakeUp();
      } else {
        prepare(this);
        updateMethods.update.call(this);

        this._zr.flush();

        this[OPTION_UPDATED_KEY] = false;
        this[IN_MAIN_PROCESS_KEY] = false;
        flushPendingActions.call(this, silent);
        triggerUpdatedEvent.call(this, silent);
      }
    };

    ECharts.prototype.setTheme = function () {
      console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
    };

    ECharts.prototype.getModel = function () {
      return this._model;
    };

    ECharts.prototype.getOption = function () {
      return this._model && this._model.getOption();
    };

    ECharts.prototype.getWidth = function () {
      return this._zr.getWidth();
    };

    ECharts.prototype.getHeight = function () {
      return this._zr.getHeight();
    };

    ECharts.prototype.getDevicePixelRatio = function () {
      return this._zr.painter.dpr || window.devicePixelRatio || 1;
    };

    ECharts.prototype.getRenderedCanvas = function (opts) {
      if (!env.canvasSupported) {
        return;
      }

      opts = extend({}, opts || {});
      opts.pixelRatio = opts.pixelRatio || 1;
      opts.backgroundColor = opts.backgroundColor || this._model.get('backgroundColor');
      var zr = this._zr;
      return zr.painter.getRenderedCanvas(opts);
    };

    ECharts.prototype.getSvgDataURL = function () {
      if (!env.svgSupported) {
        return;
      }

      var zr = this._zr;
      var list = zr.storage.getDisplayList();
      each(list, function (el) {
        el.stopAnimation(null, true);
      });
      return zr.painter.toDataURL();
    };

    ECharts.prototype.getDataURL = function (opts) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      opts = opts || {};
      var excludeComponents = opts.excludeComponents;
      var ecModel = this._model;
      var excludesComponentViews = [];
      var self = this;
      each$3(excludeComponents, function (componentType) {
        ecModel.eachComponent({
          mainType: componentType
        }, function (component) {
          var view = self._componentsMap[component.__viewId];

          if (!view.group.ignore) {
            excludesComponentViews.push(view);
            view.group.ignore = true;
          }
        });
      });
      var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.getRenderedCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
      each$3(excludesComponentViews, function (view) {
        view.group.ignore = false;
      });
      return url;
    };

    ECharts.prototype.getConnectedDataURL = function (opts) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      if (!env.canvasSupported) {
        return;
      }

      var isSvg = opts.type === 'svg';
      var groupId = this.group;
      var mathMin = Math.min;
      var mathMax = Math.max;
      var MAX_NUMBER = Infinity;

      if (connectedGroups[groupId]) {
        var left_1 = MAX_NUMBER;
        var top_1 = MAX_NUMBER;
        var right_1 = -MAX_NUMBER;
        var bottom_1 = -MAX_NUMBER;
        var canvasList_1 = [];
        var dpr_1 = opts && opts.pixelRatio || 1;
        each(instances$1, function (chart, id) {
          if (chart.group === groupId) {
            var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.getRenderedCanvas(clone(opts));
            var boundingRect = chart.getDom().getBoundingClientRect();
            left_1 = mathMin(boundingRect.left, left_1);
            top_1 = mathMin(boundingRect.top, top_1);
            right_1 = mathMax(boundingRect.right, right_1);
            bottom_1 = mathMax(boundingRect.bottom, bottom_1);
            canvasList_1.push({
              dom: canvas,
              left: boundingRect.left,
              top: boundingRect.top
            });
          }
        });
        left_1 *= dpr_1;
        top_1 *= dpr_1;
        right_1 *= dpr_1;
        bottom_1 *= dpr_1;
        var width = right_1 - left_1;
        var height = bottom_1 - top_1;
        var targetCanvas = createCanvas();
        var zr_1 = init(targetCanvas, {
          renderer: isSvg ? 'svg' : 'canvas'
        });
        zr_1.resize({
          width: width,
          height: height
        });

        if (isSvg) {
          var content_1 = '';
          each$3(canvasList_1, function (item) {
            var x = item.left - left_1;
            var y = item.top - top_1;
            content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
          });
          zr_1.painter.getSvgRoot().innerHTML = content_1;

          if (opts.connectedBackgroundColor) {
            zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
          }

          zr_1.refreshImmediately();
          return zr_1.painter.toDataURL();
        } else {
          if (opts.connectedBackgroundColor) {
            zr_1.add(new Rect({
              shape: {
                x: 0,
                y: 0,
                width: width,
                height: height
              },
              style: {
                fill: opts.connectedBackgroundColor
              }
            }));
          }

          each$3(canvasList_1, function (item) {
            var img = new ZRImage({
              style: {
                x: item.left * dpr_1 - left_1,
                y: item.top * dpr_1 - top_1,
                image: item.dom
              }
            });
            zr_1.add(img);
          });
          zr_1.refreshImmediately();
          return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
        }
      } else {
        return this.getDataURL(opts);
      }
    };

    ECharts.prototype.convertToPixel = function (finder, value) {
      return doConvertPixel(this, 'convertToPixel', finder, value);
    };

    ECharts.prototype.convertFromPixel = function (finder, value) {
      return doConvertPixel(this, 'convertFromPixel', finder, value);
    };

    ECharts.prototype.containPixel = function (finder, value) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      var ecModel = this._model;
      var result;
      var findResult = parseFinder(ecModel, finder);
      each(findResult, function (models, key) {
        key.indexOf('Models') >= 0 && each(models, function (model) {
          var coordSys = model.coordinateSystem;

          if (coordSys && coordSys.containPoint) {
            result = result || !!coordSys.containPoint(value);
          } else if (key === 'seriesModels') {
            var view = this._chartsMap[model.__viewId];

            if (view && view.containPoint) {
              result = result || view.containPoint(value, model);
            } else {
              if (true) {
                console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.'));
              }
            }
          } else {
            if (true) {
              console.warn(key + ': containPoint is not supported');
            }
          }
        }, this);
      }, this);
      return !!result;
    };

    ECharts.prototype.getVisual = function (finder, visualType) {
      var ecModel = this._model;
      var parsedFinder = parseFinder(ecModel, finder, {
        defaultMainType: 'series'
      });
      var seriesModel = parsedFinder.seriesModel;

      if (true) {
        if (!seriesModel) {
          console.warn('There is no specified seires model');
        }
      }

      var data = seriesModel.getData();
      var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
      return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
    };

    ECharts.prototype.getViewOfComponentModel = function (componentModel) {
      return this._componentsMap[componentModel.__viewId];
    };

    ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
      return this._chartsMap[seriesModel.__viewId];
    };

    ECharts.prototype._initEvents = function () {
      var _this = this;

      each$3(MOUSE_EVENT_NAMES, function (eveName) {
        var handler = function (e) {
          var ecModel = _this.getModel();

          var el = e.target;
          var params;
          var isGlobalOut = eveName === 'globalout';

          if (isGlobalOut) {
            params = {};
          } else {
            el && findEventDispatcher(el, function (parent) {
              var ecData = getECData(parent);

              if (ecData && ecData.dataIndex != null) {
                var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
                params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {};
                return true;
              } else if (ecData.eventData) {
                params = extend({}, ecData.eventData);
                return true;
              }
            }, true);
          }

          if (params) {
            var componentType = params.componentType;
            var componentIndex = params.componentIndex;

            if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
              componentType = 'series';
              componentIndex = params.seriesIndex;
            }

            var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
            var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];

            if (true) {
              if (!isGlobalOut && !(model && view)) {
                console.warn('model or view can not be found by params');
              }
            }

            params.event = e;
            params.type = eveName;
            _this._$eventProcessor.eventInfo = {
              targetEl: el,
              packedEvent: params,
              model: model,
              view: view
            };

            _this.trigger(eveName, params);
          }
        };

        handler.zrEventfulCallAtLast = true;

        _this._zr.on(eveName, handler, _this);
      });
      each$3(eventActionMap, function (actionType, eventType) {
        _this._messageCenter.on(eventType, function (event) {
          this.trigger(eventType, event);
        }, _this);
      });
      each$3(['selectchanged'], function (eventType) {
        _this._messageCenter.on(eventType, function (event) {
          this.trigger(eventType, event);
        }, _this);
      });
      handleLegacySelectEvents(this._messageCenter, this, this._model);
    };

    ECharts.prototype.isDisposed = function () {
      return this._disposed;
    };

    ECharts.prototype.clear = function () {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      this.setOption({
        series: []
      }, true);
    };

    ECharts.prototype.dispose = function () {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      this._disposed = true;
      setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
      var api = this._api;
      var ecModel = this._model;
      each$3(this._componentsViews, function (component) {
        component.dispose(ecModel, api);
      });
      each$3(this._chartsViews, function (chart) {
        chart.dispose(ecModel, api);
      });

      this._zr.dispose();

      delete instances$1[this.id];
    };

    ECharts.prototype.resize = function (opts) {
      if (true) {
        assert$1(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
      }

      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      this._zr.resize(opts);

      var ecModel = this._model;
      this._loadingFX && this._loadingFX.resize();

      if (!ecModel) {
        return;
      }

      var optionChanged = ecModel.resetOption('media');
      var silent = opts && opts.silent;
      this[IN_MAIN_PROCESS_KEY] = true;
      optionChanged && prepare(this);
      updateMethods.update.call(this, {
        type: 'resize',
        animation: {
          duration: 0
        }
      });
      this[IN_MAIN_PROCESS_KEY] = false;
      flushPendingActions.call(this, silent);
      triggerUpdatedEvent.call(this, silent);
    };

    ECharts.prototype.showLoading = function (name, cfg) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      if (isObject$2(name)) {
        cfg = name;
        name = '';
      }

      name = name || 'default';
      this.hideLoading();

      if (!loadingEffects[name]) {
        if (true) {
          console.warn('Loading effects ' + name + ' not exists.');
        }

        return;
      }

      var el = loadingEffects[name](this._api, cfg);
      var zr = this._zr;
      this._loadingFX = el;
      zr.add(el);
    };

    ECharts.prototype.hideLoading = function () {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      this._loadingFX && this._zr.remove(this._loadingFX);
      this._loadingFX = null;
    };

    ECharts.prototype.makeActionFromEvent = function (eventObj) {
      var payload = extend({}, eventObj);
      payload.type = eventActionMap[eventObj.type];
      return payload;
    };

    ECharts.prototype.dispatchAction = function (payload, opt) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      if (!isObject$2(opt)) {
        opt = {
          silent: !!opt
        };
      }

      if (!actions[payload.type]) {
        return;
      }

      if (!this._model) {
        return;
      }

      if (this[IN_MAIN_PROCESS_KEY]) {
        this._pendingActions.push(payload);

        return;
      }

      var silent = opt.silent;
      doDispatchAction.call(this, payload, silent);
      var flush = opt.flush;

      if (flush) {
        this._zr.flush();
      } else if (flush !== false && env.browser.weChat) {
        this._throttledZrFlush();
      }

      flushPendingActions.call(this, silent);
      triggerUpdatedEvent.call(this, silent);
    };

    ECharts.prototype.updateLabelLayout = function () {
      var labelManager = this._labelManager;
      labelManager.updateLayoutConfig(this._api);
      labelManager.layout(this._api);
      labelManager.processLabelsOverall();
    };

    ECharts.prototype.appendData = function (params) {
      if (this._disposed) {
        disposedWarning(this.id);
        return;
      }

      var seriesIndex = params.seriesIndex;
      var ecModel = this.getModel();
      var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

      if (true) {
        assert$1(params.data && seriesModel);
      }

      seriesModel.appendData(params);
      this._scheduler.unfinished = true;
      this.getZr().wakeUp();
    };

    ECharts.internalField = function () {
      prepare = function (ecIns) {
        var scheduler = ecIns._scheduler;
        scheduler.restorePipelines(ecIns._model);
        scheduler.prepareStageTasks();
        prepareView(ecIns, true);
        prepareView(ecIns, false);
        scheduler.plan();
      };

      prepareView = function (ecIns, isComponent) {
        var ecModel = ecIns._model;
        var scheduler = ecIns._scheduler;
        var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
        var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
        var zr = ecIns._zr;
        var api = ecIns._api;

        for (var i = 0; i < viewList.length; i++) {
          viewList[i].__alive = false;
        }

        isComponent ? ecModel.eachComponent(function (componentType, model) {
          componentType !== 'series' && doPrepare(model);
        }) : ecModel.eachSeries(doPrepare);

        function doPrepare(model) {
          var requireNewView = model.__requireNewView;
          model.__requireNewView = false;
          var viewId = '_ec_' + model.id + '_' + model.type;
          var view = !requireNewView && viewMap[viewId];

          if (!view) {
            var classType = parseClassType(model.type);
            var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : ChartView.getClass(classType.sub);

            if (true) {
              assert$1(Clazz, classType.sub + ' does not exist.');
            }

            view = new Clazz();
            view.init(ecModel, api);
            viewMap[viewId] = view;
            viewList.push(view);
            zr.add(view.group);
          }

          model.__viewId = view.__id = viewId;
          view.__alive = true;
          view.__model = model;
          view.group.__ecComponentInfo = {
            mainType: model.mainType,
            index: model.componentIndex
          };
          !isComponent && scheduler.prepareView(view, model, ecModel, api);
        }

        for (var i = 0; i < viewList.length;) {
          var view = viewList[i];

          if (!view.__alive) {
            !isComponent && view.renderTask.dispose();
            zr.remove(view.group);
            view.dispose(ecModel, api);
            viewList.splice(i, 1);

            if (viewMap[view.__id] === view) {
              delete viewMap[view.__id];
            }

            view.__id = view.group.__ecComponentInfo = null;
          } else {
            i++;
          }
        }
      };

      updateDirectly = function (ecIns, method, payload, mainType, subType) {
        var ecModel = ecIns._model;
        ecModel.setUpdatePayload(payload);

        if (!mainType) {
          each$3([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
          return;
        }

        var query = {};
        query[mainType + 'Id'] = payload[mainType + 'Id'];
        query[mainType + 'Index'] = payload[mainType + 'Index'];
        query[mainType + 'Name'] = payload[mainType + 'Name'];
        var condition = {
          mainType: mainType,
          query: query
        };
        subType && (condition.subType = subType);
        var excludeSeriesId = payload.excludeSeriesId;
        var excludeSeriesIdMap;

        if (excludeSeriesId != null) {
          excludeSeriesIdMap = createHashMap();
          each$3(normalizeToArray(excludeSeriesId), function (id) {
            var modelId = convertOptionIdName(id, null);

            if (modelId != null) {
              excludeSeriesIdMap.set(modelId, true);
            }
          });
        }

        ecModel && ecModel.eachComponent(condition, function (model) {
          if (!excludeSeriesIdMap || excludeSeriesIdMap.get(model.id) == null) {
            if (isHighDownPayload(payload) && !payload.notBlur) {
              if (model instanceof SeriesModel) {
                toggleSeriesBlurStateFromPayload(model, payload, ecIns._api);
              }
            } else if (isSelectChangePayload(payload)) {
              if (model instanceof SeriesModel) {
                toggleSelectionFromPayload(model, payload, ecIns._api);
                updateSeriesElementSelection(model);
                markStatusToUpdate(ecIns);
              }
            }

            callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]);
          }
        }, ecIns);

        function callView(view) {
          view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload);
        }
      };

      updateMethods = {
        prepareAndUpdate: function (payload) {
          prepare(this);
          updateMethods.update.call(this, payload);
        },
        update: function (payload) {
          var ecModel = this._model;
          var api = this._api;
          var zr = this._zr;
          var coordSysMgr = this._coordSysMgr;
          var scheduler = this._scheduler;

          if (!ecModel) {
            return;
          }

          ecModel.setUpdatePayload(payload);
          scheduler.restoreData(ecModel, payload);
          scheduler.performSeriesTasks(ecModel);
          coordSysMgr.create(ecModel, api);
          scheduler.performDataProcessorTasks(ecModel, payload);
          updateStreamModes(this, ecModel);
          coordSysMgr.update(ecModel, api);
          clearColorPalette(ecModel);
          scheduler.performVisualTasks(ecModel, payload);
          render(this, ecModel, api, payload);
          var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
          var darkMode = ecModel.get('darkMode');

          if (!env.canvasSupported) {
            var colorArr = parse(backgroundColor);
            backgroundColor = stringify(colorArr, 'rgb');

            if (colorArr[3] === 0) {
              backgroundColor = 'transparent';
            }
          } else {
            zr.setBackgroundColor(backgroundColor);

            if (darkMode != null && darkMode !== 'auto') {
              zr.setDarkMode(darkMode);
            }
          }

          performPostUpdateFuncs(ecModel, api);
        },
        updateTransform: function (payload) {
          var _this = this;

          var ecModel = this._model;
          var api = this._api;

          if (!ecModel) {
            return;
          }

          ecModel.setUpdatePayload(payload);
          var componentDirtyList = [];
          ecModel.eachComponent(function (componentType, componentModel) {
            if (componentType === 'series') {
              return;
            }

            var componentView = _this.getViewOfComponentModel(componentModel);

            if (componentView && componentView.__alive) {
              if (componentView.updateTransform) {
                var result = componentView.updateTransform(componentModel, ecModel, api, payload);
                result && result.update && componentDirtyList.push(componentView);
              } else {
                componentDirtyList.push(componentView);
              }
            }
          });
          var seriesDirtyMap = createHashMap();
          ecModel.eachSeries(function (seriesModel) {
            var chartView = _this._chartsMap[seriesModel.__viewId];

            if (chartView.updateTransform) {
              var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
              result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
            } else {
              seriesDirtyMap.set(seriesModel.uid, 1);
            }
          });
          clearColorPalette(ecModel);

          this._scheduler.performVisualTasks(ecModel, payload, {
            setDirty: true,
            dirtyMap: seriesDirtyMap
          });

          renderSeries(this, ecModel, api, payload, seriesDirtyMap);
          performPostUpdateFuncs(ecModel, this._api);
        },
        updateView: function (payload) {
          var ecModel = this._model;

          if (!ecModel) {
            return;
          }

          ecModel.setUpdatePayload(payload);
          ChartView.markUpdateMethod(payload, 'updateView');
          clearColorPalette(ecModel);

          this._scheduler.performVisualTasks(ecModel, payload, {
            setDirty: true
          });

          render(this, this._model, this._api, payload);
          performPostUpdateFuncs(ecModel, this._api);
        },
        updateVisual: function (payload) {
          var _this = this;

          var ecModel = this._model;

          if (!ecModel) {
            return;
          }

          ecModel.setUpdatePayload(payload);
          ecModel.eachSeries(function (seriesModel) {
            seriesModel.getData().clearAllVisual();
          });
          ChartView.markUpdateMethod(payload, 'updateVisual');
          clearColorPalette(ecModel);

          this._scheduler.performVisualTasks(ecModel, payload, {
            visualType: 'visual',
            setDirty: true
          });

          ecModel.eachComponent(function (componentType, componentModel) {
            if (componentType !== 'series') {
              var componentView = _this.getViewOfComponentModel(componentModel);

              componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload);
            }
          });
          ecModel.eachSeries(function (seriesModel) {
            var chartView = _this._chartsMap[seriesModel.__viewId];
            chartView.updateVisual(seriesModel, ecModel, _this._api, payload);
          });
          performPostUpdateFuncs(ecModel, this._api);
        },
        updateLayout: function (payload) {
          updateMethods.update.call(this, payload);
        }
      };

      doConvertPixel = function (ecIns, methodName, finder, value) {
        if (ecIns._disposed) {
          disposedWarning(ecIns.id);
          return;
        }

        var ecModel = ecIns._model;

        var coordSysList = ecIns._coordSysMgr.getCoordinateSystems();

        var result;
        var parsedFinder = parseFinder(ecModel, finder);

        for (var i = 0; i < coordSysList.length; i++) {
          var coordSys = coordSysList[i];

          if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) {
            return result;
          }
        }

        if (true) {
          console.warn('No coordinate system that supports ' + methodName + ' found by the given finder.');
        }
      };

      updateStreamModes = function (ecIns, ecModel) {
        var chartsMap = ecIns._chartsMap;
        var scheduler = ecIns._scheduler;
        ecModel.eachSeries(function (seriesModel) {
          scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
        });
      };

      doDispatchAction = function (payload, silent) {
        var _this = this;

        var ecModel = this.getModel();
        var payloadType = payload.type;
        var escapeConnect = payload.escapeConnect;
        var actionWrap = actions[payloadType];
        var actionInfo = actionWrap.actionInfo;
        var cptTypeTmp = (actionInfo.update || 'update').split(':');
        var updateMethod = cptTypeTmp.pop();
        var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
        this[IN_MAIN_PROCESS_KEY] = true;
        var payloads = [payload];
        var batched = false;

        if (payload.batch) {
          batched = true;
          payloads = map(payload.batch, function (item) {
            item = defaults(extend({}, item), payload);
            item.batch = null;
            return item;
          });
        }

        var eventObjBatch = [];
        var eventObj;
        var isSelectChange = isSelectChangePayload(payload);
        var isStatusChange = isHighDownPayload(payload) || isSelectChange;
        each$3(payloads, function (batchItem) {
          eventObj = actionWrap.action(batchItem, _this._model, _this._api);
          eventObj = eventObj || extend({}, batchItem);
          eventObj.type = actionInfo.event || eventObj.type;
          eventObjBatch.push(eventObj);

          if (isStatusChange) {
            updateDirectly(_this, updateMethod, batchItem, 'series');
            markStatusToUpdate(_this);
          } else if (cptType) {
            updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
          }
        });

        if (updateMethod !== 'none' && !isStatusChange && !cptType) {
          if (this[OPTION_UPDATED_KEY]) {
            prepare(this);
            updateMethods.update.call(this, payload);
            this[OPTION_UPDATED_KEY] = false;
          } else {
            updateMethods[updateMethod].call(this, payload);
          }
        }

        if (batched) {
          eventObj = {
            type: actionInfo.event || payloadType,
            escapeConnect: escapeConnect,
            batch: eventObjBatch
          };
        } else {
          eventObj = eventObjBatch[0];
        }

        this[IN_MAIN_PROCESS_KEY] = false;

        if (!silent) {
          var messageCenter = this._messageCenter;
          messageCenter.trigger(eventObj.type, eventObj);

          if (isSelectChange) {
            var newObj = {
              type: 'selectchanged',
              escapeConnect: escapeConnect,
              selected: getAllSelectedIndices(ecModel),
              isFromClick: payload.isFromClick || false,
              fromAction: payload.type,
              fromActionPayload: payload
            };
            messageCenter.trigger(newObj.type, newObj);
          }
        }
      };

      flushPendingActions = function (silent) {
        var pendingActions = this._pendingActions;

        while (pendingActions.length) {
          var payload = pendingActions.shift();
          doDispatchAction.call(this, payload, silent);
        }
      };

      triggerUpdatedEvent = function (silent) {
        !silent && this.trigger('updated');
      };

      bindRenderedEvent = function (zr, ecIns) {
        zr.on('rendered', function (params) {
          ecIns.trigger('rendered', params);

          if (zr.animation.isFinished() && !ecIns[OPTION_UPDATED_KEY] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) {
            ecIns.trigger('finished');
          }
        });
      };

      bindMouseEvent = function (zr, ecIns) {
        zr.on('mouseover', function (e) {
          var el = e.target;
          var dispatcher = findEventDispatcher(el, isHighDownDispatcher);

          if (dispatcher) {
            var ecData = getECData(dispatcher);
            toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, true);
            enterEmphasisWhenMouseOver(dispatcher, e);
            markStatusToUpdate(ecIns);
          }
        }).on('mouseout', function (e) {
          var el = e.target;
          var dispatcher = findEventDispatcher(el, isHighDownDispatcher);

          if (dispatcher) {
            var ecData = getECData(dispatcher);
            toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, false);
            leaveEmphasisWhenMouseOut(dispatcher, e);
            markStatusToUpdate(ecIns);
          }
        }).on('click', function (e) {
          var el = e.target;
          var dispatcher = findEventDispatcher(el, function (target) {
            return getECData(target).dataIndex != null;
          }, true);

          if (dispatcher) {
            var actionType = dispatcher.selected ? 'unselect' : 'select';
            var ecData = getECData(dispatcher);

            ecIns._api.dispatchAction({
              type: actionType,
              dataType: ecData.dataType,
              dataIndexInside: ecData.dataIndex,
              seriesIndex: ecData.seriesIndex,
              isFromClick: true
            });
          }
        });
      };

      clearColorPalette = function (ecModel) {
        ecModel.clearColorPalette();
        ecModel.eachSeries(function (seriesModel) {
          seriesModel.clearColorPalette();
        });
      };

      render = function (ecIns, ecModel, api, payload) {
        renderComponents(ecIns, ecModel, api, payload);
        each$3(ecIns._chartsViews, function (chart) {
          chart.__alive = false;
        });
        renderSeries(ecIns, ecModel, api, payload);
        each$3(ecIns._chartsViews, function (chart) {
          if (!chart.__alive) {
            chart.remove(ecModel, api);
          }
        });
      };

      renderComponents = function (ecIns, ecModel, api, payload, dirtyList) {
        each$3(dirtyList || ecIns._componentsViews, function (componentView) {
          var componentModel = componentView.__model;
          clearStates(componentModel, componentView);
          componentView.render(componentModel, ecModel, api, payload);
          updateZ(componentModel, componentView);
          updateStates(componentModel, componentView);
        });
      };

      renderSeries = function (ecIns, ecModel, api, payload, dirtyMap) {
        var scheduler = ecIns._scheduler;
        var labelManager = ecIns._labelManager;
        labelManager.clearLabels();
        var unfinished = false;
        ecModel.eachSeries(function (seriesModel) {
          var chartView = ecIns._chartsMap[seriesModel.__viewId];
          chartView.__alive = true;
          var renderTask = chartView.renderTask;
          scheduler.updatePayload(renderTask, payload);
          clearStates(seriesModel, chartView);

          if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
            renderTask.dirty();
          }

          if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
            unfinished = true;
          }

          seriesModel.__transientTransitionOpt = null;
          chartView.group.silent = !!seriesModel.get('silent');
          updateBlend(seriesModel, chartView);
          updateSeriesElementSelection(seriesModel);
          labelManager.addLabelsOfSeries(chartView);
        });
        scheduler.unfinished = unfinished || scheduler.unfinished;
        labelManager.updateLayoutConfig(api);
        labelManager.layout(api);
        labelManager.processLabelsOverall();
        ecModel.eachSeries(function (seriesModel) {
          var chartView = ecIns._chartsMap[seriesModel.__viewId];
          updateZ(seriesModel, chartView);
          updateStates(seriesModel, chartView);
        });
        updateHoverLayerStatus(ecIns, ecModel);
      };

      performPostUpdateFuncs = function (ecModel, api) {
        each$3(postUpdateFuncs, function (func) {
          func(ecModel, api);
        });
      };

      markStatusToUpdate = function (ecIns) {
        ecIns[STATUS_NEEDS_UPDATE_KEY] = true;
        ecIns.getZr().wakeUp();
      };

      applyChangedStates = function (ecIns) {
        if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
          return;
        }

        ecIns.getZr().storage.traverse(function (el) {
          if (isElementRemoved(el)) {
            return;
          }

          applyElementStates(el);
        });
        ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
      };

      function applyElementStates(el) {
        var newStates = [];
        var oldStates = el.currentStates;

        for (var i = 0; i < oldStates.length; i++) {
          var stateName = oldStates[i];

          if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
            newStates.push(stateName);
          }
        }

        if (el.selected && el.states.select) {
          newStates.push('select');
        }

        if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
          newStates.push('emphasis');
        } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
          newStates.push('blur');
        }

        el.useStates(newStates);
      }

      function updateHoverLayerStatus(ecIns, ecModel) {
        var zr = ecIns._zr;
        var storage = zr.storage;
        var elCount = 0;
        storage.traverse(function (el) {
          if (!el.isGroup) {
            elCount++;
          }
        });

        if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) {
          ecModel.eachSeries(function (seriesModel) {
            if (seriesModel.preventUsingHoverLayer) {
              return;
            }

            var chartView = ecIns._chartsMap[seriesModel.__viewId];

            if (chartView.__alive) {
              chartView.group.traverse(function (el) {
                if (el.states.emphasis) {
                  el.states.emphasis.hoverLayer = true;
                }
              });
            }
          });
        }
      }

      function updateBlend(seriesModel, chartView) {
        var blendMode = seriesModel.get('blendMode') || null;

        if (true) {
          if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
            console.warn('Only canvas support blendMode');
          }
        }

        chartView.group.traverse(function (el) {
          if (!el.isGroup) {
            el.style.blend = blendMode;
          }

          if (el.eachPendingDisplayable) {
            el.eachPendingDisplayable(function (displayable) {
              displayable.style.blend = blendMode;
            });
          }
        });
      }

      function updateZ(model, view) {
        if (model.preventAutoZ) {
          return;
        }

        var z = model.get('z');
        var zlevel = model.get('zlevel');
        view.group.traverse(function (el) {
          if (!el.isGroup) {
            z != null && (el.z = z);
            zlevel != null && (el.zlevel = zlevel);
            var label = el.getTextContent();
            var labelLine = el.getTextGuideLine();

            if (label) {
              label.z = el.z;
              label.zlevel = el.zlevel;
              label.z2 = el.z2 + 2;
            }

            if (labelLine) {
              var showAbove = el.textGuideLineConfig && el.textGuideLineConfig.showAbove;
              labelLine.z = el.z;
              labelLine.zlevel = el.zlevel;
              labelLine.z2 = el.z2 + (showAbove ? 1 : -1);
            }
          }
        });
      }

      function clearStates(model, view) {
        view.group.traverse(function (el) {
          if (isElementRemoved(el)) {
            return;
          }

          var textContent = el.getTextContent();
          var textGuide = el.getTextGuideLine();

          if (el.stateTransition) {
            el.stateTransition = null;
          }

          if (textContent && textContent.stateTransition) {
            textContent.stateTransition = null;
          }

          if (textGuide && textGuide.stateTransition) {
            textGuide.stateTransition = null;
          }

          if (el.hasState()) {
            el.prevStates = el.currentStates;
            el.clearStates();
          } else if (el.prevStates) {
            el.prevStates = null;
          }
        });
      }

      function updateStates(model, view) {
        var stateAnimationModel = model.getModel('stateAnimation');
        var enableAnimation = model.isAnimationEnabled();
        var duration = stateAnimationModel.get('duration');
        var stateTransition = duration > 0 ? {
          duration: duration,
          delay: stateAnimationModel.get('delay'),
          easing: stateAnimationModel.get('easing')
        } : null;
        view.group.traverse(function (el) {
          if (el.states && el.states.emphasis) {
            if (isElementRemoved(el)) {
              return;
            }

            if (el instanceof Path) {
              savePathStates(el);
            }

            if (el.__dirty) {
              var prevStates = el.prevStates;

              if (prevStates) {
                el.useStates(prevStates);
              }
            }

            if (enableAnimation) {
              el.stateTransition = stateTransition;
              var textContent = el.getTextContent();
              var textGuide = el.getTextGuideLine();

              if (textContent) {
                textContent.stateTransition = stateTransition;
              }

              if (textGuide) {
                textGuide.stateTransition = stateTransition;
              }
            }

            if (el.__dirty) {
              applyElementStates(el);
            }
          }
        });
      }

      createExtensionAPI = function (ecIns) {
        return new (function (_super) {
          __extends(class_1, _super);

          function class_1() {
            return _super !== null && _super.apply(this, arguments) || this;
          }

          class_1.prototype.getCoordinateSystems = function () {
            return ecIns._coordSysMgr.getCoordinateSystems();
          };

          class_1.prototype.getComponentByElement = function (el) {
            while (el) {
              var modelInfo = el.__ecComponentInfo;

              if (modelInfo != null) {
                return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
              }

              el = el.parent;
            }
          };

          class_1.prototype.enterEmphasis = function (el, highlightDigit) {
            enterEmphasis(el, highlightDigit);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.leaveEmphasis = function (el, highlightDigit) {
            leaveEmphasis(el, highlightDigit);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.enterBlur = function (el) {
            enterBlur(el);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.leaveBlur = function (el) {
            leaveBlur(el);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.enterSelect = function (el) {
            enterSelect(el);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.leaveSelect = function (el) {
            leaveSelect(el);
            markStatusToUpdate(ecIns);
          };

          class_1.prototype.getModel = function () {
            return ecIns.getModel();
          };

          class_1.prototype.getViewOfComponentModel = function (componentModel) {
            return ecIns.getViewOfComponentModel(componentModel);
          };

          class_1.prototype.getViewOfSeriesModel = function (seriesModel) {
            return ecIns.getViewOfSeriesModel(seriesModel);
          };

          return class_1;
        }(ExtensionAPI))(ecIns);
      };

      enableConnect = function (chart) {
        function updateConnectedChartsStatus(charts, status) {
          for (var i = 0; i < charts.length; i++) {
            var otherChart = charts[i];
            otherChart[CONNECT_STATUS_KEY] = status;
          }
        }

        each$3(eventActionMap, function (actionType, eventType) {
          chart._messageCenter.on(eventType, function (event) {
            if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
              if (event && event.escapeConnect) {
                return;
              }

              var action_1 = chart.makeActionFromEvent(event);
              var otherCharts_1 = [];
              each$3(instances$1, function (otherChart) {
                if (otherChart !== chart && otherChart.group === chart.group) {
                  otherCharts_1.push(otherChart);
                }
              });
              updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING);
              each$3(otherCharts_1, function (otherChart) {
                if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
                  otherChart.dispatchAction(action_1);
                }
              });
              updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED);
            }
          });
        });
      };

      setTransitionOpt = function (chart, transitionOpt) {
        var ecModel = chart._model;
        each(normalizeToArray(transitionOpt), function (transOpt) {
          var errMsg;
          var fromOpt = transOpt.from;
          var toOpt = transOpt.to;

          if (toOpt == null) {
            if (true) {
              errMsg = '`transition.to` must be specified.';
            }

            throwError(errMsg);
          }

          var finderOpt = {
            includeMainTypes: ['series'],
            enableAll: false,
            enableNone: false
          };
          var fromResult = fromOpt ? parseFinder(ecModel, fromOpt, finderOpt) : null;
          var toResult = parseFinder(ecModel, toOpt, finderOpt);
          var toSeries = toResult.seriesModel;

          if (toSeries == null) {
            errMsg = '';

            if (true) {
              errMsg = '`transition` is only supported on series.';
            }
          }

          if (fromResult && fromResult.seriesModel !== toSeries) {
            errMsg = '';

            if (true) {
              errMsg = '`transition.from` and `transition.to` must be specified to the same series.';
            }
          }

          if (errMsg != null) {
            throwError(errMsg);
          }

          toSeries.__transientTransitionOpt = {
            from: fromOpt ? fromOpt.dimension : null,
            to: toOpt.dimension,
            dividingMethod: transOpt.dividingMethod
          };
        });
      };
    }();

    return ECharts;
  }(Eventful);

  var echartsProto = ECharts.prototype;
  echartsProto.on = createRegisterEventWithLowercaseECharts('on');
  echartsProto.off = createRegisterEventWithLowercaseECharts('off');

  echartsProto.one = function (eventName, cb, ctx) {
    var self = this;
    deprecateLog('ECharts#one is deprecated.');

    function wrapped() {
      var args2 = [];

      for (var _i = 0; _i < arguments.length; _i++) {
        args2[_i] = arguments[_i];
      }

      cb && cb.apply && cb.apply(this, args2);
      self.off(eventName, wrapped);
    }

    this.on.call(this, eventName, wrapped, ctx);
  };

  var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu'];

  function disposedWarning(id) {
    if (true) {
      console.warn('Instance ' + id + ' has been disposed');
    }
  }

  var actions = {};
  var eventActionMap = {};
  var dataProcessorFuncs = [];
  var optionPreprocessorFuncs = [];
  var postInitFuncs = [];
  var postUpdateFuncs = [];
  var visualFuncs = [];
  var themeStorage = {};
  var loadingEffects = {};
  var instances$1 = {};
  var connectedGroups = {};
  var idBase = +new Date() - 0;
  var groupIdBase = +new Date() - 0;
  var DOM_ATTRIBUTE_KEY = '_echarts_instance_';

  function init$1(dom, theme, opts) {
    if (true) {
      if (!dom) {
        throw new Error('Initialize failed: invalid dom.');
      }
    }

    var existInstance = getInstanceByDom(dom);

    if (existInstance) {
      if (true) {
        console.warn('There is a chart instance already initialized on the dom.');
      }

      return existInstance;
    }

    if (true) {
      if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) {
        console.warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.');
      }
    }

    var chart = new ECharts(dom, theme, opts);
    chart.id = 'ec_' + idBase++;
    instances$1[chart.id] = chart;
    setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
    enableConnect(chart);
    each$3(postInitFuncs, function (postInitFunc) {
      postInitFunc(chart);
    });
    return chart;
  }

  function connect(groupId) {
    if (isArray(groupId)) {
      var charts = groupId;
      groupId = null;
      each$3(charts, function (chart) {
        if (chart.group != null) {
          groupId = chart.group;
        }
      });
      groupId = groupId || 'g_' + groupIdBase++;
      each$3(charts, function (chart) {
        chart.group = groupId;
      });
    }

    connectedGroups[groupId] = true;
    return groupId;
  }

  function disConnect(groupId) {
    connectedGroups[groupId] = false;
  }

  var disconnect = disConnect;

  function dispose$1(chart) {
    if (typeof chart === 'string') {
      chart = instances$1[chart];
    } else if (!(chart instanceof ECharts)) {
      chart = getInstanceByDom(chart);
    }

    if (chart instanceof ECharts && !chart.isDisposed()) {
      chart.dispose();
    }
  }

  function getInstanceByDom(dom) {
    return instances$1[getAttribute(dom, DOM_ATTRIBUTE_KEY)];
  }

  function getInstanceById(key) {
    return instances$1[key];
  }

  function registerTheme(name, theme) {
    themeStorage[name] = theme;
  }

  function registerPreprocessor(preprocessorFunc) {
    optionPreprocessorFuncs.push(preprocessorFunc);
  }

  function registerProcessor(priority, processor) {
    normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
  }

  function registerPostInit(postInitFunc) {
    postInitFunc && postInitFuncs.push(postInitFunc);
  }

  function registerPostUpdate(postUpdateFunc) {
    postUpdateFunc && postUpdateFuncs.push(postUpdateFunc);
  }

  function registerAction(actionInfo, eventName, action) {
    if (typeof eventName === 'function') {
      action = eventName;
      eventName = '';
    }

    var actionType = isObject$2(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = {
      event: eventName
    }][0];
    actionInfo.event = (actionInfo.event || actionType).toLowerCase();
    eventName = actionInfo.event;
    assert$1(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));

    if (!actions[actionType]) {
      actions[actionType] = {
        action: action,
        actionInfo: actionInfo
      };
    }

    eventActionMap[eventName] = actionType;
  }

  function registerCoordinateSystem(type, coordSysCreator) {
    CoordinateSystemManager.register(type, coordSysCreator);
  }

  function getCoordinateSystemDimensions(type) {
    var coordSysCreator = CoordinateSystemManager.get(type);

    if (coordSysCreator) {
      return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice();
    }
  }

  function registerLayout(priority, layoutTask) {
    normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
  }

  function registerVisual(priority, visualTask) {
    normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
  }

  function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
    if (isFunction$1(priority) || isObject$2(priority)) {
      fn = priority;
      priority = defaultPriority;
    }

    if (true) {
      if (isNaN(priority) || priority == null) {
        throw new Error('Illegal priority');
      }

      each$3(targetList, function (wrap) {
        assert$1(wrap.__raw !== fn);
      });
    }

    var stageHandler = Scheduler.wrapStageHandler(fn, visualType);
    stageHandler.__prio = priority;
    stageHandler.__raw = fn;
    targetList.push(stageHandler);
  }

  function registerLoading(name, loadingFx) {
    loadingEffects[name] = loadingFx;
  }

  function extendComponentModel(proto) {
    return ComponentModel.extend(proto);
  }

  function extendComponentView(proto) {
    return ComponentView.extend(proto);
  }

  function extendSeriesModel(proto) {
    return SeriesModel.extend(proto);
  }

  function extendChartView(proto) {
    return ChartView.extend(proto);
  }

  function setCanvasCreator(creator) {
    $override('createCanvas', creator);
  }

  function registerMap(mapName, geoJson, specialAreas) {
    mapDataStorage.registerMap(mapName, geoJson, specialAreas);
  }

  function getMap(mapName) {
    var records = mapDataStorage.retrieveMap(mapName);
    return records && records[0] && {
      geoJson: records[0].geoJSON,
      specialAreas: records[0].specialAreas
    };
  }

  var registerTransform = registerExternalTransform;
  registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask);
  registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask);
  registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask);
  registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask);
  registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask);
  registerVisual(PRIORITY_VISUAL_DECAL, decalVisual);
  registerPreprocessor(globalBackwardCompat);
  registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
  registerLoading('default', defaultLoading);
  registerAction({
    type: HIGHLIGHT_ACTION_TYPE,
    event: HIGHLIGHT_ACTION_TYPE,
    update: HIGHLIGHT_ACTION_TYPE
  }, noop);
  registerAction({
    type: DOWNPLAY_ACTION_TYPE,
    event: DOWNPLAY_ACTION_TYPE,
    update: DOWNPLAY_ACTION_TYPE
  }, noop);
  registerAction({
    type: SELECT_ACTION_TYPE,
    event: SELECT_ACTION_TYPE,
    update: SELECT_ACTION_TYPE
  }, noop);
  registerAction({
    type: UNSELECT_ACTION_TYPE,
    event: UNSELECT_ACTION_TYPE,
    update: UNSELECT_ACTION_TYPE
  }, noop);
  registerAction({
    type: TOGGLE_SELECT_ACTION_TYPE,
    event: TOGGLE_SELECT_ACTION_TYPE,
    update: TOGGLE_SELECT_ACTION_TYPE
  }, noop);
  registerTheme('light', lightTheme);
  registerTheme('dark', theme);
  var dataTool = {};

  function dataIndexMapValueLength(valNumOrArrLengthMoreThan2) {
    return valNumOrArrLengthMoreThan2 == null ? 0 : valNumOrArrLengthMoreThan2.length || 1;
  }

  function defaultKeyGetter(item) {
    return item;
  }

  var DataDiffer = function () {
    function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context, diffMode) {
      this._old = oldArr;
      this._new = newArr;
      this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;
      this._newKeyGetter = newKeyGetter || defaultKeyGetter;
      this.context = context;
      this._diffModeMultiple = diffMode === 'multiple';
    }

    DataDiffer.prototype.add = function (func) {
      this._add = func;
      return this;
    };

    DataDiffer.prototype.update = function (func) {
      this._update = func;
      return this;
    };

    DataDiffer.prototype.updateManyToOne = function (func) {
      this._updateManyToOne = func;
      return this;
    };

    DataDiffer.prototype.updateOneToMany = function (func) {
      this._updateOneToMany = func;
      return this;
    };

    DataDiffer.prototype.remove = function (func) {
      this._remove = func;
      return this;
    };

    DataDiffer.prototype.execute = function () {
      this[this._diffModeMultiple ? '_executeMultiple' : '_executeOneToOne']();
    };

    DataDiffer.prototype._executeOneToOne = function () {
      var oldArr = this._old;
      var newArr = this._new;
      var newDataIndexMap = {};
      var oldDataKeyArr = new Array(oldArr.length);
      var newDataKeyArr = new Array(newArr.length);

      this._initIndexMap(oldArr, null, oldDataKeyArr, '_oldKeyGetter');

      this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter');

      for (var i = 0; i < oldArr.length; i++) {
        var oldKey = oldDataKeyArr[i];
        var newIdxMapVal = newDataIndexMap[oldKey];
        var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal);

        if (newIdxMapValLen > 1) {
          var newIdx = newIdxMapVal.shift();

          if (newIdxMapVal.length === 1) {
            newDataIndexMap[oldKey] = newIdxMapVal[0];
          }

          this._update && this._update(newIdx, i);
        } else if (newIdxMapValLen === 1) {
          newDataIndexMap[oldKey] = null;
          this._update && this._update(newIdxMapVal, i);
        } else {
          this._remove && this._remove(i);
        }
      }

      this._performRestAdd(newDataKeyArr, newDataIndexMap);
    };

    DataDiffer.prototype._executeMultiple = function () {
      var oldArr = this._old;
      var newArr = this._new;
      var oldDataIndexMap = {};
      var newDataIndexMap = {};
      var oldDataKeyArr = [];
      var newDataKeyArr = [];

      this._initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter');

      this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter');

      for (var i = 0; i < oldDataKeyArr.length; i++) {
        var oldKey = oldDataKeyArr[i];
        var oldIdxMapVal = oldDataIndexMap[oldKey];
        var newIdxMapVal = newDataIndexMap[oldKey];
        var oldIdxMapValLen = dataIndexMapValueLength(oldIdxMapVal);
        var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal);

        if (oldIdxMapValLen > 1 && newIdxMapValLen === 1) {
          this._updateManyToOne && this._updateManyToOne(newIdxMapVal, oldIdxMapVal);
          newDataIndexMap[oldKey] = null;
        } else if (oldIdxMapValLen === 1 && newIdxMapValLen > 1) {
          this._updateOneToMany && this._updateOneToMany(newIdxMapVal, oldIdxMapVal);
          newDataIndexMap[oldKey] = null;
        } else if (oldIdxMapValLen === 1 && newIdxMapValLen === 1) {
          this._update && this._update(newIdxMapVal, oldIdxMapVal);
          newDataIndexMap[oldKey] = null;
        } else if (oldIdxMapValLen > 1) {
          for (var i_1 = 0; i_1 < oldIdxMapValLen; i_1++) {
            this._remove && this._remove(oldIdxMapVal[i_1]);
          }
        } else {
          this._remove && this._remove(oldIdxMapVal);
        }
      }

      this._performRestAdd(newDataKeyArr, newDataIndexMap);
    };

    DataDiffer.prototype._performRestAdd = function (newDataKeyArr, newDataIndexMap) {
      for (var i = 0; i < newDataKeyArr.length; i++) {
        var newKey = newDataKeyArr[i];
        var newIdxMapVal = newDataIndexMap[newKey];
        var idxMapValLen = dataIndexMapValueLength(newIdxMapVal);

        if (idxMapValLen > 1) {
          for (var j = 0; j < idxMapValLen; j++) {
            this._add && this._add(newIdxMapVal[j]);
          }
        } else if (idxMapValLen === 1) {
          this._add && this._add(newIdxMapVal);
        }

        newDataIndexMap[newKey] = null;
      }
    };

    DataDiffer.prototype._initIndexMap = function (arr, map, keyArr, keyGetterName) {
      var cbModeMultiple = this._diffModeMultiple;

      for (var i = 0; i < arr.length; i++) {
        var key = '_ec_' + this[keyGetterName](arr[i], i);

        if (!cbModeMultiple) {
          keyArr[i] = key;
        }

        if (!map) {
          continue;
        }

        var idxMapVal = map[key];
        var idxMapValLen = dataIndexMapValueLength(idxMapVal);

        if (idxMapValLen === 0) {
          map[key] = i;

          if (cbModeMultiple) {
            keyArr.push(key);
          }
        } else if (idxMapValLen === 1) {
          map[key] = [idxMapVal, i];
        } else {
          idxMapVal.push(i);
        }
      }
    };

    return DataDiffer;
  }();

  function summarizeDimensions(data) {
    var summary = {};
    var encode = summary.encode = {};
    var notExtraCoordDimMap = createHashMap();
    var defaultedLabel = [];
    var defaultedTooltip = [];
    var userOutput = summary.userOutput = {
      dimensionNames: data.dimensions.slice(),
      encode: {}
    };
    each(data.dimensions, function (dimName) {
      var dimItem = data.getDimensionInfo(dimName);
      var coordDim = dimItem.coordDim;

      if (coordDim) {
        if (true) {
          assert(VISUAL_DIMENSIONS.get(coordDim) == null);
        }

        var coordDimIndex = dimItem.coordDimIndex;
        getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName;

        if (!dimItem.isExtraCoord) {
          notExtraCoordDimMap.set(coordDim, 1);

          if (mayLabelDimType(dimItem.type)) {
            defaultedLabel[0] = dimName;
          }

          getOrCreateEncodeArr(userOutput.encode, coordDim)[coordDimIndex] = dimItem.index;
        }

        if (dimItem.defaultTooltip) {
          defaultedTooltip.push(dimName);
        }
      }

      VISUAL_DIMENSIONS.each(function (v, otherDim) {
        var encodeArr = getOrCreateEncodeArr(encode, otherDim);
        var dimIndex = dimItem.otherDims[otherDim];

        if (dimIndex != null && dimIndex !== false) {
          encodeArr[dimIndex] = dimItem.name;
        }
      });
    });
    var dataDimsOnCoord = [];
    var encodeFirstDimNotExtra = {};
    notExtraCoordDimMap.each(function (v, coordDim) {
      var dimArr = encode[coordDim];
      encodeFirstDimNotExtra[coordDim] = dimArr[0];
      dataDimsOnCoord = dataDimsOnCoord.concat(dimArr);
    });
    summary.dataDimsOnCoord = dataDimsOnCoord;
    summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra;
    var encodeLabel = encode.label;

    if (encodeLabel && encodeLabel.length) {
      defaultedLabel = encodeLabel.slice();
    }

    var encodeTooltip = encode.tooltip;

    if (encodeTooltip && encodeTooltip.length) {
      defaultedTooltip = encodeTooltip.slice();
    } else if (!defaultedTooltip.length) {
      defaultedTooltip = defaultedLabel.slice();
    }

    encode.defaultedLabel = defaultedLabel;
    encode.defaultedTooltip = defaultedTooltip;
    return summary;
  }

  function getOrCreateEncodeArr(encode, dim) {
    if (!encode.hasOwnProperty(dim)) {
      encode[dim] = [];
    }

    return encode[dim];
  }

  function getDimensionTypeByAxis(axisType) {
    return axisType === 'category' ? 'ordinal' : axisType === 'time' ? 'time' : 'float';
  }

  function mayLabelDimType(dimType) {
    return !(dimType === 'ordinal' || dimType === 'time');
  }

  var DataDimensionInfo = function () {
    function DataDimensionInfo(opt) {
      this.otherDims = {};

      if (opt != null) {
        extend(this, opt);
      }
    }

    return DataDimensionInfo;
  }();

  var mathFloor = Math.floor;
  var isObject$3 = isObject;
  var map$1 = map;
  var UNDEFINED = 'undefined';
  var INDEX_NOT_FOUND = -1;
  var ID_PREFIX = 'e\0\0';
  var dataCtors = {
    'float': typeof Float64Array === UNDEFINED ? Array : Float64Array,
    'int': typeof Int32Array === UNDEFINED ? Array : Int32Array,
    'ordinal': Array,
    'number': Array,
    'time': Array
  };
  var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
  var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array;
  var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;
  var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_rawData', '_dimValueGetter', '_count', '_rawCount', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount'];
  var CLONE_PROPERTIES = ['_extent', '_approximateExtent', '_rawExtent'];
  var defaultDimValueGetters;
  var prepareInvertedIndex;
  var getIndicesCtor;
  var prepareStorage;
  var getRawIndexWithoutIndices;
  var getRawIndexWithIndices;
  var getId;
  var getIdNameFromStore;
  var makeIdFromName;
  var normalizeDimensions;
  var validateDimensions;
  var cloneListForMapAndSample;
  var getInitialExtent;
  var setItemDataAndSeriesIndex;
  var transferProperties;

  var List = function () {
    function List(dimensions, hostModel) {
      this.type = 'list';
      this._count = 0;
      this._rawCount = 0;
      this._storage = {};
      this._storageArr = [];
      this._nameList = [];
      this._idList = [];
      this._visual = {};
      this._layout = {};
      this._itemVisuals = [];
      this._itemLayouts = [];
      this._graphicEls = [];
      this._rawExtent = {};
      this._extent = {};
      this._approximateExtent = {};
      this._calculationInfo = {};
      this.hasItemOption = true;
      this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map'];
      this.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
      this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample'];
      this.getRawIndex = getRawIndexWithoutIndices;
      dimensions = dimensions || ['x', 'y'];
      var dimensionInfos = {};
      var dimensionNames = [];
      var invertedIndicesMap = {};

      for (var i = 0; i < dimensions.length; i++) {
        var dimInfoInput = dimensions[i];
        var dimensionInfo = isString(dimInfoInput) ? new DataDimensionInfo({
          name: dimInfoInput
        }) : !(dimInfoInput instanceof DataDimensionInfo) ? new DataDimensionInfo(dimInfoInput) : dimInfoInput;
        var dimensionName = dimensionInfo.name;
        dimensionInfo.type = dimensionInfo.type || 'float';

        if (!dimensionInfo.coordDim) {
          dimensionInfo.coordDim = dimensionName;
          dimensionInfo.coordDimIndex = 0;
        }

        var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {};
        dimensionNames.push(dimensionName);
        dimensionInfos[dimensionName] = dimensionInfo;
        dimensionInfo.index = i;

        if (dimensionInfo.createInvertedIndices) {
          invertedIndicesMap[dimensionName] = [];
        }

        if (otherDims.itemName === 0) {
          this._nameDimIdx = i;
          this._nameOrdinalMeta = dimensionInfo.ordinalMeta;
        }

        if (otherDims.itemId === 0) {
          this._idDimIdx = i;
          this._idOrdinalMeta = dimensionInfo.ordinalMeta;
        }
      }

      this.dimensions = dimensionNames;
      this._dimensionInfos = dimensionInfos;
      this.hostModel = hostModel;
      this._dimensionsSummary = summarizeDimensions(this);
      this._invertedIndicesMap = invertedIndicesMap;
      this.userOutput = this._dimensionsSummary.userOutput;
    }

    List.prototype.getDimension = function (dim) {
      if (typeof dim === 'number' || !isNaN(dim) && !this._dimensionInfos.hasOwnProperty(dim)) {
        dim = this.dimensions[dim];
      }

      return dim;
    };

    List.prototype.getDimensionInfo = function (dim) {
      return this._dimensionInfos[this.getDimension(dim)];
    };

    List.prototype.getDimensionsOnCoord = function () {
      return this._dimensionsSummary.dataDimsOnCoord.slice();
    };

    List.prototype.mapDimension = function (coordDim, idx) {
      var dimensionsSummary = this._dimensionsSummary;

      if (idx == null) {
        return dimensionsSummary.encodeFirstDimNotExtra[coordDim];
      }

      var dims = dimensionsSummary.encode[coordDim];
      return dims ? dims[idx] : null;
    };

    List.prototype.mapDimensionsAll = function (coordDim) {
      var dimensionsSummary = this._dimensionsSummary;
      var dims = dimensionsSummary.encode[coordDim];
      return (dims || []).slice();
    };

    List.prototype.initData = function (data, nameList, dimValueGetter) {
      var notProvider = isSourceInstance(data) || isArrayLike(data);
      var provider = notProvider ? new DefaultDataProvider(data, this.dimensions.length) : data;

      if (true) {
        assert(notProvider || isFunction(provider.getItem) && isFunction(provider.count), 'Inavlid data provider.');
      }

      this._rawData = provider;
      var sourceFormat = provider.getSource().sourceFormat;
      this._storage = {};
      this._indices = null;
      this._dontMakeIdFromName = this._idDimIdx != null || sourceFormat === SOURCE_FORMAT_TYPED_ARRAY || !!provider.fillStorage;
      this._nameList = (nameList || []).slice();
      this._idList = [];
      this._nameRepeatCount = {};

      if (!dimValueGetter) {
        this.hasItemOption = false;
      }

      this.defaultDimValueGetter = defaultDimValueGetters[sourceFormat];
      this._dimValueGetter = dimValueGetter = dimValueGetter || this.defaultDimValueGetter;
      this._dimValueGetterArrayRows = defaultDimValueGetters.arrayRows;
      this._rawExtent = {};

      this._initDataFromProvider(0, provider.count());

      if (provider.pure) {
        this.hasItemOption = false;
      }
    };

    List.prototype.getProvider = function () {
      return this._rawData;
    };

    List.prototype.appendData = function (data) {
      if (true) {
        assert(!this._indices, 'appendData can only be called on raw data.');
      }

      var rawData = this._rawData;
      var start = this.count();
      rawData.appendData(data);
      var end = rawData.count();

      if (!rawData.persistent) {
        end += start;
      }

      this._initDataFromProvider(start, end, true);
    };

    List.prototype.appendValues = function (values, names) {
      var storage = this._storage;
      var dimensions = this.dimensions;
      var dimLen = dimensions.length;
      var rawExtent = this._rawExtent;
      var start = this.count();
      var end = start + Math.max(values.length, names ? names.length : 0);

      for (var i = 0; i < dimLen; i++) {
        var dim = dimensions[i];

        if (!rawExtent[dim]) {
          rawExtent[dim] = getInitialExtent();
        }

        prepareStorage(storage, this._dimensionInfos[dim], end, true);
      }

      var rawExtentArr = map$1(dimensions, function (dim) {
        return rawExtent[dim];
      });
      var storageArr = this._storageArr = map$1(dimensions, function (dim) {
        return storage[dim];
      });
      var emptyDataItem = [];

      for (var idx = start; idx < end; idx++) {
        var sourceIdx = idx - start;

        for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
          var dim = dimensions[dimIdx];

          var val = this._dimValueGetterArrayRows(values[sourceIdx] || emptyDataItem, dim, sourceIdx, dimIdx);

          storageArr[dimIdx][idx] = val;
          var dimRawExtent = rawExtentArr[dimIdx];
          val < dimRawExtent[0] && (dimRawExtent[0] = val);
          val > dimRawExtent[1] && (dimRawExtent[1] = val);
        }

        if (names) {
          this._nameList[idx] = names[sourceIdx];

          if (!this._dontMakeIdFromName) {
            makeIdFromName(this, idx);
          }
        }
      }

      this._rawCount = this._count = end;
      this._extent = {};
      prepareInvertedIndex(this);
    };

    List.prototype._initDataFromProvider = function (start, end, append) {
      if (start >= end) {
        return;
      }

      var rawData = this._rawData;
      var storage = this._storage;
      var dimensions = this.dimensions;
      var dimLen = dimensions.length;
      var dimensionInfoMap = this._dimensionInfos;
      var nameList = this._nameList;
      var idList = this._idList;
      var rawExtent = this._rawExtent;
      var sourceFormat = rawData.getSource().sourceFormat;
      var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL;

      for (var i = 0; i < dimLen; i++) {
        var dim = dimensions[i];

        if (!rawExtent[dim]) {
          rawExtent[dim] = getInitialExtent();
        }

        prepareStorage(storage, dimensionInfoMap[dim], end, append);
      }

      var storageArr = this._storageArr = map$1(dimensions, function (dim) {
        return storage[dim];
      });
      var rawExtentArr = map$1(dimensions, function (dim) {
        return rawExtent[dim];
      });

      if (rawData.fillStorage) {
        rawData.fillStorage(start, end, storageArr, rawExtentArr);
      } else {
        var dataItem = [];

        for (var idx = start; idx < end; idx++) {
          dataItem = rawData.getItem(idx, dataItem);

          for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
            var dim = dimensions[dimIdx];
            var dimStorage = storageArr[dimIdx];

            var val = this._dimValueGetter(dataItem, dim, idx, dimIdx);

            dimStorage[idx] = val;
            var dimRawExtent = rawExtentArr[dimIdx];
            val < dimRawExtent[0] && (dimRawExtent[0] = val);
            val > dimRawExtent[1] && (dimRawExtent[1] = val);
          }

          if (isFormatOriginal && !rawData.pure && dataItem) {
            var itemName = dataItem.name;

            if (nameList[idx] == null && itemName != null) {
              nameList[idx] = convertOptionIdName(itemName, null);
            }

            var itemId = dataItem.id;

            if (idList[idx] == null && itemId != null) {
              idList[idx] = convertOptionIdName(itemId, null);
            }
          }

          if (!this._dontMakeIdFromName) {
            makeIdFromName(this, idx);
          }
        }
      }

      if (!rawData.persistent && rawData.clean) {
        rawData.clean();
      }

      this._rawCount = this._count = end;
      this._extent = {};
      prepareInvertedIndex(this);
    };

    List.prototype.count = function () {
      return this._count;
    };

    List.prototype.getIndices = function () {
      var newIndices;
      var indices = this._indices;

      if (indices) {
        var Ctor = indices.constructor;
        var thisCount = this._count;

        if (Ctor === Array) {
          newIndices = new Ctor(thisCount);

          for (var i = 0; i < thisCount; i++) {
            newIndices[i] = indices[i];
          }
        } else {
          newIndices = new Ctor(indices.buffer, 0, thisCount);
        }
      } else {
        var Ctor = getIndicesCtor(this);
        newIndices = new Ctor(this.count());

        for (var i = 0; i < newIndices.length; i++) {
          newIndices[i] = i;
        }
      }

      return newIndices;
    };

    List.prototype.getByDimIdx = function (dimIdx, idx) {
      if (!(idx >= 0 && idx < this._count)) {
        return NaN;
      }

      var dimStore = this._storageArr[dimIdx];
      return dimStore ? dimStore[this.getRawIndex(idx)] : NaN;
    };

    List.prototype.get = function (dim, idx) {
      if (!(idx >= 0 && idx < this._count)) {
        return NaN;
      }

      var dimStore = this._storage[dim];
      return dimStore ? dimStore[this.getRawIndex(idx)] : NaN;
    };

    List.prototype.getByRawIndex = function (dim, rawIdx) {
      if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
        return NaN;
      }

      var dimStore = this._storage[dim];
      return dimStore ? dimStore[rawIdx] : NaN;
    };

    List.prototype.getValues = function (dimensions, idx) {
      var values = [];

      if (!isArray(dimensions)) {
        idx = dimensions;
        dimensions = this.dimensions;
      }

      for (var i = 0, len = dimensions.length; i < len; i++) {
        values.push(this.get(dimensions[i], idx));
      }

      return values;
    };

    List.prototype.hasValue = function (idx) {
      var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord;

      for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) {
        if (isNaN(this.get(dataDimsOnCoord[i], idx))) {
          return false;
        }
      }

      return true;
    };

    List.prototype.getDataExtent = function (dim) {
      dim = this.getDimension(dim);
      var dimData = this._storage[dim];
      var initialExtent = getInitialExtent();

      if (!dimData) {
        return initialExtent;
      }

      var currEnd = this.count();
      var useRaw = !this._indices;
      var dimExtent;

      if (useRaw) {
        return this._rawExtent[dim].slice();
      }

      dimExtent = this._extent[dim];

      if (dimExtent) {
        return dimExtent.slice();
      }

      dimExtent = initialExtent;
      var min = dimExtent[0];
      var max = dimExtent[1];

      for (var i = 0; i < currEnd; i++) {
        var rawIdx = this.getRawIndex(i);
        var value = dimData[rawIdx];
        value < min && (min = value);
        value > max && (max = value);
      }

      dimExtent = [min, max];
      this._extent[dim] = dimExtent;
      return dimExtent;
    };

    List.prototype.getApproximateExtent = function (dim) {
      dim = this.getDimension(dim);
      return this._approximateExtent[dim] || this.getDataExtent(dim);
    };

    List.prototype.setApproximateExtent = function (extent, dim) {
      dim = this.getDimension(dim);
      this._approximateExtent[dim] = extent.slice();
    };

    List.prototype.getCalculationInfo = function (key) {
      return this._calculationInfo[key];
    };

    List.prototype.setCalculationInfo = function (key, value) {
      isObject$3(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
    };

    List.prototype.getSum = function (dim) {
      var dimData = this._storage[dim];
      var sum = 0;

      if (dimData) {
        for (var i = 0, len = this.count(); i < len; i++) {
          var value = this.get(dim, i);

          if (!isNaN(value)) {
            sum += value;
          }
        }
      }

      return sum;
    };

    List.prototype.getMedian = function (dim) {
      var dimDataArray = [];
      this.each(dim, function (val) {
        if (!isNaN(val)) {
          dimDataArray.push(val);
        }
      });
      var sortedDimDataArray = dimDataArray.sort(function (a, b) {
        return a - b;
      });
      var len = this.count();
      return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
    };

    List.prototype.rawIndexOf = function (dim, value) {
      var invertedIndices = dim && this._invertedIndicesMap[dim];

      if (true) {
        if (!invertedIndices) {
          throw new Error('Do not supported yet');
        }
      }

      var rawIndex = invertedIndices[value];

      if (rawIndex == null || isNaN(rawIndex)) {
        return INDEX_NOT_FOUND;
      }

      return rawIndex;
    };

    List.prototype.indexOfName = function (name) {
      for (var i = 0, len = this.count(); i < len; i++) {
        if (this.getName(i) === name) {
          return i;
        }
      }

      return -1;
    };

    List.prototype.indexOfRawIndex = function (rawIndex) {
      if (rawIndex >= this._rawCount || rawIndex < 0) {
        return -1;
      }

      if (!this._indices) {
        return rawIndex;
      }

      var indices = this._indices;
      var rawDataIndex = indices[rawIndex];

      if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
        return rawIndex;
      }

      var left = 0;
      var right = this._count - 1;

      while (left <= right) {
        var mid = (left + right) / 2 | 0;

        if (indices[mid] < rawIndex) {
          left = mid + 1;
        } else if (indices[mid] > rawIndex) {
          right = mid - 1;
        } else {
          return mid;
        }
      }

      return -1;
    };

    List.prototype.indicesOfNearest = function (dim, value, maxDistance) {
      var storage = this._storage;
      var dimData = storage[dim];
      var nearestIndices = [];

      if (!dimData) {
        return nearestIndices;
      }

      if (maxDistance == null) {
        maxDistance = Infinity;
      }

      var minDist = Infinity;
      var minDiff = -1;
      var nearestIndicesLen = 0;

      for (var i = 0, len = this.count(); i < len; i++) {
        var dataIndex = this.getRawIndex(i);
        var diff = value - dimData[dataIndex];
        var dist = Math.abs(diff);

        if (dist <= maxDistance) {
          if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) {
            minDist = dist;
            minDiff = diff;
            nearestIndicesLen = 0;
          }

          if (diff === minDiff) {
            nearestIndices[nearestIndicesLen++] = i;
          }
        }
      }

      nearestIndices.length = nearestIndicesLen;
      return nearestIndices;
    };

    List.prototype.getRawDataItem = function (idx) {
      if (!this._rawData.persistent) {
        var val = [];

        for (var i = 0; i < this.dimensions.length; i++) {
          var dim = this.dimensions[i];
          val.push(this.get(dim, idx));
        }

        return val;
      } else {
        return this._rawData.getItem(this.getRawIndex(idx));
      }
    };

    List.prototype.getName = function (idx) {
      var rawIndex = this.getRawIndex(idx);
      var name = this._nameList[rawIndex];

      if (name == null && this._nameDimIdx != null) {
        name = getIdNameFromStore(this, this._nameDimIdx, this._nameOrdinalMeta, rawIndex);
      }

      if (name == null) {
        name = '';
      }

      return name;
    };

    List.prototype.getId = function (idx) {
      return getId(this, this.getRawIndex(idx));
    };

    List.prototype.each = function (dims, cb, ctx, ctxCompat) {
      var _this = this;

      if (!this._count) {
        return;
      }

      if (typeof dims === 'function') {
        ctxCompat = ctx;
        ctx = cb;
        cb = dims;
        dims = [];
      }

      var fCtx = ctx || ctxCompat || this;
      var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this);

      if (true) {
        validateDimensions(this, dimNames);
      }

      var dimSize = dimNames.length;
      var dimIndices = map$1(dimNames, function (dimName) {
        return _this._dimensionInfos[dimName].index;
      });
      var storageArr = this._storageArr;

      for (var i = 0, len = this.count(); i < len; i++) {
        var rawIdx = this.getRawIndex(i);

        switch (dimSize) {
          case 0:
            cb.call(fCtx, i);
            break;

          case 1:
            cb.call(fCtx, storageArr[dimIndices[0]][rawIdx], i);
            break;

          case 2:
            cb.call(fCtx, storageArr[dimIndices[0]][rawIdx], storageArr[dimIndices[1]][rawIdx], i);
            break;

          default:
            var k = 0;
            var value = [];

            for (; k < dimSize; k++) {
              value[k] = storageArr[dimIndices[k]][rawIdx];
            }

            value[k] = i;
            cb.apply(fCtx, value);
        }
      }
    };

    List.prototype.filterSelf = function (dims, cb, ctx, ctxCompat) {
      var _this = this;

      if (!this._count) {
        return;
      }

      if (typeof dims === 'function') {
        ctxCompat = ctx;
        ctx = cb;
        cb = dims;
        dims = [];
      }

      var fCtx = ctx || ctxCompat || this;
      var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this);

      if (true) {
        validateDimensions(this, dimNames);
      }

      var count = this.count();
      var Ctor = getIndicesCtor(this);
      var newIndices = new Ctor(count);
      var value = [];
      var dimSize = dimNames.length;
      var offset = 0;
      var dimIndices = map$1(dimNames, function (dimName) {
        return _this._dimensionInfos[dimName].index;
      });
      var dim0 = dimIndices[0];
      var storageArr = this._storageArr;

      for (var i = 0; i < count; i++) {
        var keep = void 0;
        var rawIdx = this.getRawIndex(i);

        if (dimSize === 0) {
          keep = cb.call(fCtx, i);
        } else if (dimSize === 1) {
          var val = storageArr[dim0][rawIdx];
          keep = cb.call(fCtx, val, i);
        } else {
          var k = 0;

          for (; k < dimSize; k++) {
            value[k] = storageArr[dimIndices[k]][rawIdx];
          }

          value[k] = i;
          keep = cb.apply(fCtx, value);
        }

        if (keep) {
          newIndices[offset++] = rawIdx;
        }
      }

      if (offset < count) {
        this._indices = newIndices;
      }

      this._count = offset;
      this._extent = {};
      this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
      return this;
    };

    List.prototype.selectRange = function (range) {
      var _this = this;

      var len = this._count;

      if (!len) {
        return;
      }

      var dimensions = [];

      for (var dim in range) {
        if (range.hasOwnProperty(dim)) {
          dimensions.push(dim);
        }
      }

      if (true) {
        validateDimensions(this, dimensions);
      }

      var dimSize = dimensions.length;

      if (!dimSize) {
        return;
      }

      var originalCount = this.count();
      var Ctor = getIndicesCtor(this);
      var newIndices = new Ctor(originalCount);
      var offset = 0;
      var dim0 = dimensions[0];
      var dimIndices = map$1(dimensions, function (dimName) {
        return _this._dimensionInfos[dimName].index;
      });
      var min = range[dim0][0];
      var max = range[dim0][1];
      var storageArr = this._storageArr;
      var quickFinished = false;

      if (!this._indices) {
        var idx = 0;

        if (dimSize === 1) {
          var dimStorage = storageArr[dimIndices[0]];

          for (var i = 0; i < len; i++) {
            var val = dimStorage[i];

            if (val >= min && val <= max || isNaN(val)) {
              newIndices[offset++] = idx;
            }

            idx++;
          }

          quickFinished = true;
        } else if (dimSize === 2) {
          var dimStorage = storageArr[dimIndices[0]];
          var dimStorage2 = storageArr[dimIndices[1]];
          var min2 = range[dimensions[1]][0];
          var max2 = range[dimensions[1]][1];

          for (var i = 0; i < len; i++) {
            var val = dimStorage[i];
            var val2 = dimStorage2[i];

            if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) {
              newIndices[offset++] = idx;
            }

            idx++;
          }

          quickFinished = true;
        }
      }

      if (!quickFinished) {
        if (dimSize === 1) {
          for (var i = 0; i < originalCount; i++) {
            var rawIndex = this.getRawIndex(i);
            var val = storageArr[dimIndices[0]][rawIndex];

            if (val >= min && val <= max || isNaN(val)) {
              newIndices[offset++] = rawIndex;
            }
          }
        } else {
          for (var i = 0; i < originalCount; i++) {
            var keep = true;
            var rawIndex = this.getRawIndex(i);

            for (var k = 0; k < dimSize; k++) {
              var dimk = dimensions[k];
              var val = storageArr[dimIndices[k]][rawIndex];

              if (val < range[dimk][0] || val > range[dimk][1]) {
                keep = false;
              }
            }

            if (keep) {
              newIndices[offset++] = this.getRawIndex(i);
            }
          }
        }
      }

      if (offset < originalCount) {
        this._indices = newIndices;
      }

      this._count = offset;
      this._extent = {};
      this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
      return this;
    };

    List.prototype.mapArray = function (dims, cb, ctx, ctxCompat) {
      if (typeof dims === 'function') {
        ctxCompat = ctx;
        ctx = cb;
        cb = dims;
        dims = [];
      }

      ctx = ctx || ctxCompat || this;
      var result = [];
      this.each(dims, function () {
        result.push(cb && cb.apply(this, arguments));
      }, ctx);
      return result;
    };

    List.prototype.map = function (dims, cb, ctx, ctxCompat) {
      var fCtx = ctx || ctxCompat || this;
      var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this);

      if (true) {
        validateDimensions(this, dimNames);
      }

      var list = cloneListForMapAndSample(this, dimNames);
      var storage = list._storage;
      list._indices = this._indices;
      list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
      var tmpRetValue = [];
      var dimSize = dimNames.length;
      var dataCount = this.count();
      var values = [];
      var rawExtent = list._rawExtent;

      for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) {
        for (var dimIndex = 0; dimIndex < dimSize; dimIndex++) {
          values[dimIndex] = this.get(dimNames[dimIndex], dataIndex);
        }

        values[dimSize] = dataIndex;
        var retValue = cb && cb.apply(fCtx, values);

        if (retValue != null) {
          if (typeof retValue !== 'object') {
            tmpRetValue[0] = retValue;
            retValue = tmpRetValue;
          }

          var rawIndex = this.getRawIndex(dataIndex);

          for (var i = 0; i < retValue.length; i++) {
            var dim = dimNames[i];
            var val = retValue[i];
            var rawExtentOnDim = rawExtent[dim];
            var dimStore = storage[dim];

            if (dimStore) {
              dimStore[rawIndex] = val;
            }

            if (val < rawExtentOnDim[0]) {
              rawExtentOnDim[0] = val;
            }

            if (val > rawExtentOnDim[1]) {
              rawExtentOnDim[1] = val;
            }
          }
        }
      }

      return list;
    };

    List.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) {
      var list = cloneListForMapAndSample(this, [dimension]);
      var targetStorage = list._storage;
      var frameValues = [];
      var frameSize = mathFloor(1 / rate);
      var dimStore = targetStorage[dimension];
      var len = this.count();
      var rawExtentOnDim = list._rawExtent[dimension];
      var newIndices = new (getIndicesCtor(this))(len);
      var offset = 0;

      for (var i = 0; i < len; i += frameSize) {
        if (frameSize > len - i) {
          frameSize = len - i;
          frameValues.length = frameSize;
        }

        for (var k = 0; k < frameSize; k++) {
          var dataIdx = this.getRawIndex(i + k);
          frameValues[k] = dimStore[dataIdx];
        }

        var value = sampleValue(frameValues);
        var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1));
        dimStore[sampleFrameIdx] = value;

        if (value < rawExtentOnDim[0]) {
          rawExtentOnDim[0] = value;
        }

        if (value > rawExtentOnDim[1]) {
          rawExtentOnDim[1] = value;
        }

        newIndices[offset++] = sampleFrameIdx;
      }

      list._count = offset;
      list._indices = newIndices;
      list.getRawIndex = getRawIndexWithIndices;
      return list;
    };

    List.prototype.lttbDownSample = function (valueDimension, rate) {
      var list = cloneListForMapAndSample(this, []);
      var targetStorage = list._storage;
      var dimStore = targetStorage[valueDimension];
      var len = this.count();
      var newIndices = new (getIndicesCtor(this))(len);
      var sampledIndex = 0;
      var frameSize = mathFloor(1 / rate);
      var currentRawIndex = this.getRawIndex(0);
      var maxArea;
      var area;
      var nextRawIndex;
      newIndices[sampledIndex++] = currentRawIndex;

      for (var i = 1; i < len - 1; i += frameSize) {
        var nextFrameStart = Math.min(i + frameSize, len - 1);
        var nextFrameEnd = Math.min(i + frameSize * 2, len);
        var avgX = (nextFrameEnd + nextFrameStart) / 2;
        var avgY = 0;

        for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) {
          var rawIndex = this.getRawIndex(idx);
          var y = dimStore[rawIndex];

          if (isNaN(y)) {
            continue;
          }

          avgY += y;
        }

        avgY /= nextFrameEnd - nextFrameStart;
        var frameStart = i;
        var frameEnd = Math.min(i + frameSize, len);
        var pointAX = i - 1;
        var pointAY = dimStore[currentRawIndex];
        maxArea = -1;
        nextRawIndex = frameStart;

        for (var idx = frameStart; idx < frameEnd; idx++) {
          var rawIndex = this.getRawIndex(idx);
          var y = dimStore[rawIndex];

          if (isNaN(y)) {
            continue;
          }

          area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY));

          if (area > maxArea) {
            maxArea = area;
            nextRawIndex = rawIndex;
          }
        }

        newIndices[sampledIndex++] = nextRawIndex;
        currentRawIndex = nextRawIndex;
      }

      newIndices[sampledIndex++] = this.getRawIndex(len - 1);
      list._count = sampledIndex;
      list._indices = newIndices;
      list.getRawIndex = getRawIndexWithIndices;
      return list;
    };

    List.prototype.getItemModel = function (idx) {
      var hostModel = this.hostModel;
      var dataItem = this.getRawDataItem(idx);
      return new Model(dataItem, hostModel, hostModel && hostModel.ecModel);
    };

    List.prototype.diff = function (otherList) {
      var thisList = this;
      return new DataDiffer(otherList ? otherList.getIndices() : [], this.getIndices(), function (idx) {
        return getId(otherList, idx);
      }, function (idx) {
        return getId(thisList, idx);
      });
    };

    List.prototype.getVisual = function (key) {
      var visual = this._visual;
      return visual && visual[key];
    };

    List.prototype.setVisual = function (kvObj, val) {
      this._visual = this._visual || {};

      if (isObject$3(kvObj)) {
        extend(this._visual, kvObj);
      } else {
        this._visual[kvObj] = val;
      }
    };

    List.prototype.getItemVisual = function (idx, key) {
      var itemVisual = this._itemVisuals[idx];
      var val = itemVisual && itemVisual[key];

      if (val == null) {
        return this.getVisual(key);
      }

      return val;
    };

    List.prototype.hasItemVisual = function () {
      return this._itemVisuals.length > 0;
    };

    List.prototype.ensureUniqueItemVisual = function (idx, key) {
      var itemVisuals = this._itemVisuals;
      var itemVisual = itemVisuals[idx];

      if (!itemVisual) {
        itemVisual = itemVisuals[idx] = {};
      }

      var val = itemVisual[key];

      if (val == null) {
        val = this.getVisual(key);

        if (isArray(val)) {
          val = val.slice();
        } else if (isObject$3(val)) {
          val = extend({}, val);
        }

        itemVisual[key] = val;
      }

      return val;
    };

    List.prototype.setItemVisual = function (idx, key, value) {
      var itemVisual = this._itemVisuals[idx] || {};
      this._itemVisuals[idx] = itemVisual;

      if (isObject$3(key)) {
        extend(itemVisual, key);
      } else {
        itemVisual[key] = value;
      }
    };

    List.prototype.clearAllVisual = function () {
      this._visual = {};
      this._itemVisuals = [];
    };

    List.prototype.setLayout = function (key, val) {
      if (isObject$3(key)) {
        for (var name_1 in key) {
          if (key.hasOwnProperty(name_1)) {
            this.setLayout(name_1, key[name_1]);
          }
        }

        return;
      }

      this._layout[key] = val;
    };

    List.prototype.getLayout = function (key) {
      return this._layout[key];
    };

    List.prototype.getItemLayout = function (idx) {
      return this._itemLayouts[idx];
    };

    List.prototype.setItemLayout = function (idx, layout, merge) {
      this._itemLayouts[idx] = merge ? extend(this._itemLayouts[idx] || {}, layout) : layout;
    };

    List.prototype.clearItemLayouts = function () {
      this._itemLayouts.length = 0;
    };

    List.prototype.setItemGraphicEl = function (idx, el) {
      var hostModel = this.hostModel;

      if (el) {
        var ecData = getECData(el);
        ecData.dataIndex = idx;
        ecData.dataType = this.dataType;
        ecData.seriesIndex = hostModel && hostModel.seriesIndex;

        if (el.type === 'group') {
          el.traverse(setItemDataAndSeriesIndex, el);
        }
      }

      this._graphicEls[idx] = el;
    };

    List.prototype.getItemGraphicEl = function (idx) {
      return this._graphicEls[idx];
    };

    List.prototype.eachItemGraphicEl = function (cb, context) {
      each(this._graphicEls, function (el, idx) {
        if (el) {
          cb && cb.call(context, el, idx);
        }
      });
    };

    List.prototype.cloneShallow = function (list) {
      if (!list) {
        var dimensionInfoList = map$1(this.dimensions, this.getDimensionInfo, this);
        list = new List(dimensionInfoList, this.hostModel);
      }

      list._storage = this._storage;
      list._storageArr = this._storageArr;
      transferProperties(list, this);

      if (this._indices) {
        var Ctor = this._indices.constructor;

        if (Ctor === Array) {
          var thisCount = this._indices.length;
          list._indices = new Ctor(thisCount);

          for (var i = 0; i < thisCount; i++) {
            list._indices[i] = this._indices[i];
          }
        } else {
          list._indices = new Ctor(this._indices);
        }
      } else {
        list._indices = null;
      }

      list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
      return list;
    };

    List.prototype.wrapMethod = function (methodName, injectFunction) {
      var originalMethod = this[methodName];

      if (typeof originalMethod !== 'function') {
        return;
      }

      this.__wrappedMethods = this.__wrappedMethods || [];

      this.__wrappedMethods.push(methodName);

      this[methodName] = function () {
        var res = originalMethod.apply(this, arguments);
        return injectFunction.apply(this, [res].concat(slice(arguments)));
      };
    };

    List.internalField = function () {
      defaultDimValueGetters = {
        arrayRows: getDimValueSimply,
        objectRows: function (dataItem, dimName, dataIndex, dimIndex) {
          return parseDataValue(dataItem[dimName], this._dimensionInfos[dimName]);
        },
        keyedColumns: getDimValueSimply,
        original: function (dataItem, dimName, dataIndex, dimIndex) {
          var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value);

          if (!this._rawData.pure && isDataItemOption(dataItem)) {
            this.hasItemOption = true;
          }

          return parseDataValue(value instanceof Array ? value[dimIndex] : value, this._dimensionInfos[dimName]);
        },
        typedArray: function (dataItem, dimName, dataIndex, dimIndex) {
          return dataItem[dimIndex];
        }
      };

      function getDimValueSimply(dataItem, dimName, dataIndex, dimIndex) {
        return parseDataValue(dataItem[dimIndex], this._dimensionInfos[dimName]);
      }

      prepareInvertedIndex = function (list) {
        var invertedIndicesMap = list._invertedIndicesMap;
        each(invertedIndicesMap, function (invertedIndices, dim) {
          var dimInfo = list._dimensionInfos[dim];
          var ordinalMeta = dimInfo.ordinalMeta;

          if (ordinalMeta) {
            invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length);

            for (var i = 0; i < invertedIndices.length; i++) {
              invertedIndices[i] = INDEX_NOT_FOUND;
            }

            for (var i = 0; i < list._count; i++) {
              invertedIndices[list.get(dim, i)] = i;
            }
          }
        });
      };

      getIdNameFromStore = function (list, dimIdx, ordinalMeta, rawIndex) {
        var val;
        var chunk = list._storageArr[dimIdx];

        if (chunk) {
          val = chunk[rawIndex];

          if (ordinalMeta && ordinalMeta.categories.length) {
            val = ordinalMeta.categories[val];
          }
        }

        return convertOptionIdName(val, null);
      };

      getIndicesCtor = function (list) {
        return list._rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
      };

      prepareStorage = function (storage, dimInfo, end, append) {
        var DataCtor = dataCtors[dimInfo.type];
        var dim = dimInfo.name;

        if (append) {
          var oldStore = storage[dim];
          var oldLen = oldStore && oldStore.length;

          if (!(oldLen === end)) {
            var newStore = new DataCtor(end);

            for (var j = 0; j < oldLen; j++) {
              newStore[j] = oldStore[j];
            }

            storage[dim] = newStore;
          }
        } else {
          storage[dim] = new DataCtor(end);
        }
      };

      getRawIndexWithoutIndices = function (idx) {
        return idx;
      };

      getRawIndexWithIndices = function (idx) {
        if (idx < this._count && idx >= 0) {
          return this._indices[idx];
        }

        return -1;
      };

      getId = function (list, rawIndex) {
        var id = list._idList[rawIndex];

        if (id == null && list._idDimIdx != null) {
          id = getIdNameFromStore(list, list._idDimIdx, list._idOrdinalMeta, rawIndex);
        }

        if (id == null) {
          id = ID_PREFIX + rawIndex;
        }

        return id;
      };

      normalizeDimensions = function (dimensions) {
        if (!isArray(dimensions)) {
          dimensions = dimensions != null ? [dimensions] : [];
        }

        return dimensions;
      };

      validateDimensions = function (list, dims) {
        for (var i = 0; i < dims.length; i++) {
          if (!list._dimensionInfos[dims[i]]) {
            console.error('Unkown dimension ' + dims[i]);
          }
        }
      };

      cloneListForMapAndSample = function (original, excludeDimensions) {
        var allDimensions = original.dimensions;
        var list = new List(map$1(allDimensions, original.getDimensionInfo, original), original.hostModel);
        transferProperties(list, original);
        var storage = list._storage = {};
        var originalStorage = original._storage;
        var storageArr = list._storageArr = [];

        for (var i = 0; i < allDimensions.length; i++) {
          var dim = allDimensions[i];

          if (originalStorage[dim]) {
            if (indexOf(excludeDimensions, dim) >= 0) {
              storage[dim] = cloneChunk(originalStorage[dim]);
              list._rawExtent[dim] = getInitialExtent();
              list._extent[dim] = null;
            } else {
              storage[dim] = originalStorage[dim];
            }

            storageArr.push(storage[dim]);
          }
        }

        return list;
      };

      function cloneChunk(originalChunk) {
        var Ctor = originalChunk.constructor;
        return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk);
      }

      getInitialExtent = function () {
        return [Infinity, -Infinity];
      };

      setItemDataAndSeriesIndex = function (child) {
        var childECData = getECData(child);
        var thisECData = getECData(this);
        childECData.seriesIndex = thisECData.seriesIndex;
        childECData.dataIndex = thisECData.dataIndex;
        childECData.dataType = thisECData.dataType;
      };

      transferProperties = function (target, source) {
        each(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) {
          if (source.hasOwnProperty(propName)) {
            target[propName] = source[propName];
          }
        });
        target.__wrappedMethods = source.__wrappedMethods;
        each(CLONE_PROPERTIES, function (propName) {
          target[propName] = clone(source[propName]);
        });
        target._calculationInfo = extend({}, source._calculationInfo);
      };

      makeIdFromName = function (list, idx) {
        var nameList = list._nameList;
        var idList = list._idList;
        var nameDimIdx = list._nameDimIdx;
        var idDimIdx = list._idDimIdx;
        var name = nameList[idx];
        var id = idList[idx];

        if (name == null && nameDimIdx != null) {
          nameList[idx] = name = getIdNameFromStore(list, nameDimIdx, list._nameOrdinalMeta, idx);
        }

        if (id == null && idDimIdx != null) {
          idList[idx] = id = getIdNameFromStore(list, idDimIdx, list._idOrdinalMeta, idx);
        }

        if (id == null && name != null) {
          var nameRepeatCount = list._nameRepeatCount;
          var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1;
          id = name;

          if (nmCnt > 1) {
            id += '__ec__' + nmCnt;
          }

          idList[idx] = id;
        }
      };
    }();

    return List;
  }();

  function completeDimensions(sysDims, source, opt) {
    if (!isSourceInstance(source)) {
      source = createSourceFromSeriesDataOption(source);
    }

    opt = opt || {};
    sysDims = (sysDims || []).slice();
    var dimsDef = (opt.dimsDef || []).slice();
    var dataDimNameMap = createHashMap();
    var coordDimNameMap = createHashMap();
    var result = [];
    var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimCount);

    for (var i = 0; i < dimCount; i++) {
      var dimDefItemRaw = dimsDef[i];
      var dimDefItem = dimsDef[i] = extend({}, isObject(dimDefItemRaw) ? dimDefItemRaw : {
        name: dimDefItemRaw
      });
      var userDimName = dimDefItem.name;
      var resultItem = result[i] = new DataDimensionInfo();

      if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
        resultItem.name = resultItem.displayName = userDimName;
        dataDimNameMap.set(userDimName, i);
      }

      dimDefItem.type != null && (resultItem.type = dimDefItem.type);
      dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName);
    }

    var encodeDef = opt.encodeDef;

    if (!encodeDef && opt.encodeDefaulter) {
      encodeDef = opt.encodeDefaulter(source, dimCount);
    }

    var encodeDefMap = createHashMap(encodeDef);
    encodeDefMap.each(function (dataDimsRaw, coordDim) {
      var dataDims = normalizeToArray(dataDimsRaw).slice();

      if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) {
        encodeDefMap.set(coordDim, false);
        return;
      }

      var validDataDims = encodeDefMap.set(coordDim, []);
      each(dataDims, function (resultDimIdxOrName, idx) {
        var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName;

        if (resultDimIdx != null && resultDimIdx < dimCount) {
          validDataDims[idx] = resultDimIdx;
          applyDim(result[resultDimIdx], coordDim, idx);
        }
      });
    });
    var availDimIdx = 0;
    each(sysDims, function (sysDimItemRaw) {
      var coordDim;
      var sysDimItemDimsDef;
      var sysDimItemOtherDims;
      var sysDimItem;

      if (isString(sysDimItemRaw)) {
        coordDim = sysDimItemRaw;
        sysDimItem = {};
      } else {
        sysDimItem = sysDimItemRaw;
        coordDim = sysDimItem.name;
        var ordinalMeta = sysDimItem.ordinalMeta;
        sysDimItem.ordinalMeta = null;
        sysDimItem = clone(sysDimItem);
        sysDimItem.ordinalMeta = ordinalMeta;
        sysDimItemDimsDef = sysDimItem.dimsDef;
        sysDimItemOtherDims = sysDimItem.otherDims;
        sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null;
      }

      var dataDims = encodeDefMap.get(coordDim);

      if (dataDims === false) {
        return;
      }

      dataDims = normalizeToArray(dataDims);

      if (!dataDims.length) {
        for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) {
          while (availDimIdx < result.length && result[availDimIdx].coordDim != null) {
            availDimIdx++;
          }

          availDimIdx < result.length && dataDims.push(availDimIdx++);
        }
      }

      each(dataDims, function (resultDimIdx, coordDimIndex) {
        var resultItem = result[resultDimIdx];
        applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex);

        if (resultItem.name == null && sysDimItemDimsDef) {
          var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex];
          !isObject(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = {
            name: sysDimItemDimsDefItem
          });
          resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name;
          resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip;
        }

        sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims);
      });
    });

    function applyDim(resultItem, coordDim, coordDimIndex) {
      if (VISUAL_DIMENSIONS.get(coordDim) != null) {
        resultItem.otherDims[coordDim] = coordDimIndex;
      } else {
        resultItem.coordDim = coordDim;
        resultItem.coordDimIndex = coordDimIndex;
        coordDimNameMap.set(coordDim, true);
      }
    }

    var generateCoord = opt.generateCoord;
    var generateCoordCount = opt.generateCoordCount;
    var fromZero = generateCoordCount != null;
    generateCoordCount = generateCoord ? generateCoordCount || 1 : 0;
    var extra = generateCoord || 'value';

    for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
      var resultItem = result[resultDimIdx] = result[resultDimIdx] || new DataDimensionInfo();
      var coordDim = resultItem.coordDim;

      if (coordDim == null) {
        resultItem.coordDim = genName(extra, coordDimNameMap, fromZero);
        resultItem.coordDimIndex = 0;

        if (!generateCoord || generateCoordCount <= 0) {
          resultItem.isExtraCoord = true;
        }

        generateCoordCount--;
      }

      resultItem.name == null && (resultItem.name = genName(resultItem.coordDim, dataDimNameMap, false));

      if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) {
        resultItem.type = 'ordinal';
      }
    }

    return result;
  }

  function getDimCount(source, sysDims, dimsDef, optDimCount) {
    var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0);
    each(sysDims, function (sysDimItem) {
      var sysDimItemDimsDef;

      if (isObject(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) {
        dimCount = Math.max(dimCount, sysDimItemDimsDef.length);
      }
    });
    return dimCount;
  }

  function genName(name, map, fromZero) {
    if (fromZero || map.get(name) != null) {
      var i = 0;

      while (map.get(name + i) != null) {
        i++;
      }

      name += i;
    }

    map.set(name, true);
    return name;
  }

  function createDimensions(source, opt) {
    opt = opt || {};
    return completeDimensions(opt.coordDimensions || [], source, {
      dimsDef: opt.dimensionsDefine || source.dimensionsDefine,
      encodeDef: opt.encodeDefine || source.encodeDefine,
      dimCount: opt.dimensionsCount,
      encodeDefaulter: opt.encodeDefaulter,
      generateCoord: opt.generateCoord,
      generateCoordCount: opt.generateCoordCount
    });
  }

  var CoordSysInfo = function () {
    function CoordSysInfo(coordSysName) {
      this.coordSysDims = [];
      this.axisMap = createHashMap();
      this.categoryAxisMap = createHashMap();
      this.coordSysName = coordSysName;
    }

    return CoordSysInfo;
  }();

  function getCoordSysInfoBySeries(seriesModel) {
    var coordSysName = seriesModel.get('coordinateSystem');
    var result = new CoordSysInfo(coordSysName);
    var fetch = fetchers[coordSysName];

    if (fetch) {
      fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
      return result;
    }
  }

  var fetchers = {
    cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
      var xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0];
      var yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0];

      if (true) {
        if (!xAxisModel) {
          throw new Error('xAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('xAxisId'), 0) + '" not found');
        }

        if (!yAxisModel) {
          throw new Error('yAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('yAxisId'), 0) + '" not found');
        }
      }

      result.coordSysDims = ['x', 'y'];
      axisMap.set('x', xAxisModel);
      axisMap.set('y', yAxisModel);

      if (isCategory(xAxisModel)) {
        categoryAxisMap.set('x', xAxisModel);
        result.firstCategoryDimIndex = 0;
      }

      if (isCategory(yAxisModel)) {
        categoryAxisMap.set('y', yAxisModel);
        result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
      }
    },
    singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
      var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0];

      if (true) {
        if (!singleAxisModel) {
          throw new Error('singleAxis should be specified.');
        }
      }

      result.coordSysDims = ['single'];
      axisMap.set('single', singleAxisModel);

      if (isCategory(singleAxisModel)) {
        categoryAxisMap.set('single', singleAxisModel);
        result.firstCategoryDimIndex = 0;
      }
    },
    polar: function (seriesModel, result, axisMap, categoryAxisMap) {
      var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0];
      var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
      var angleAxisModel = polarModel.findAxisModel('angleAxis');

      if (true) {
        if (!angleAxisModel) {
          throw new Error('angleAxis option not found');
        }

        if (!radiusAxisModel) {
          throw new Error('radiusAxis option not found');
        }
      }

      result.coordSysDims = ['radius', 'angle'];
      axisMap.set('radius', radiusAxisModel);
      axisMap.set('angle', angleAxisModel);

      if (isCategory(radiusAxisModel)) {
        categoryAxisMap.set('radius', radiusAxisModel);
        result.firstCategoryDimIndex = 0;
      }

      if (isCategory(angleAxisModel)) {
        categoryAxisMap.set('angle', angleAxisModel);
        result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
      }
    },
    geo: function (seriesModel, result, axisMap, categoryAxisMap) {
      result.coordSysDims = ['lng', 'lat'];
    },
    parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
      var ecModel = seriesModel.ecModel;
      var parallelModel = ecModel.getComponent('parallel', seriesModel.get('parallelIndex'));
      var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();
      each(parallelModel.parallelAxisIndex, function (axisIndex, index) {
        var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
        var axisDim = coordSysDims[index];
        axisMap.set(axisDim, axisModel);

        if (isCategory(axisModel)) {
          categoryAxisMap.set(axisDim, axisModel);

          if (result.firstCategoryDimIndex == null) {
            result.firstCategoryDimIndex = index;
          }
        }
      });
    }
  };

  function isCategory(axisModel) {
    return axisModel.get('type') === 'category';
  }

  function enableDataStack(seriesModel, dimensionInfoList, opt) {
    opt = opt || {};
    var byIndex = opt.byIndex;
    var stackedCoordDimension = opt.stackedCoordDimension;
    var mayStack = !!(seriesModel && seriesModel.get('stack'));
    var stackedByDimInfo;
    var stackedDimInfo;
    var stackResultDimension;
    var stackedOverDimension;
    each(dimensionInfoList, function (dimensionInfo, index) {
      if (isString(dimensionInfo)) {
        dimensionInfoList[index] = dimensionInfo = {
          name: dimensionInfo
        };
      }

      if (mayStack && !dimensionInfo.isExtraCoord) {
        if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) {
          stackedByDimInfo = dimensionInfo;
        }

        if (!stackedDimInfo && dimensionInfo.type !== 'ordinal' && dimensionInfo.type !== 'time' && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)) {
          stackedDimInfo = dimensionInfo;
        }
      }
    });

    if (stackedDimInfo && !byIndex && !stackedByDimInfo) {
      byIndex = true;
    }

    if (stackedDimInfo) {
      stackResultDimension = '__\0ecstackresult';
      stackedOverDimension = '__\0ecstackedover';

      if (stackedByDimInfo) {
        stackedByDimInfo.createInvertedIndices = true;
      }

      var stackedDimCoordDim_1 = stackedDimInfo.coordDim;
      var stackedDimType = stackedDimInfo.type;
      var stackedDimCoordIndex_1 = 0;
      each(dimensionInfoList, function (dimensionInfo) {
        if (dimensionInfo.coordDim === stackedDimCoordDim_1) {
          stackedDimCoordIndex_1++;
        }
      });
      dimensionInfoList.push({
        name: stackResultDimension,
        coordDim: stackedDimCoordDim_1,
        coordDimIndex: stackedDimCoordIndex_1,
        type: stackedDimType,
        isExtraCoord: true,
        isCalculationCoord: true
      });
      stackedDimCoordIndex_1++;
      dimensionInfoList.push({
        name: stackedOverDimension,
        coordDim: stackedOverDimension,
        coordDimIndex: stackedDimCoordIndex_1,
        type: stackedDimType,
        isExtraCoord: true,
        isCalculationCoord: true
      });
    }

    return {
      stackedDimension: stackedDimInfo && stackedDimInfo.name,
      stackedByDimension: stackedByDimInfo && stackedByDimInfo.name,
      isStackedByIndex: byIndex,
      stackedOverDimension: stackedOverDimension,
      stackResultDimension: stackResultDimension
    };
  }

  function isDimensionStacked(data, stackedDim) {
    return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension');
  }

  function getStackedDimension(data, targetDim) {
    return isDimensionStacked(data, targetDim) ? data.getCalculationInfo('stackResultDimension') : targetDim;
  }

  function createListFromArray(source, seriesModel, opt) {
    opt = opt || {};

    if (!isSourceInstance(source)) {
      source = createSourceFromSeriesDataOption(source);
    }

    var coordSysName = seriesModel.get('coordinateSystem');
    var registeredCoordSys = CoordinateSystemManager.get(coordSysName);
    var coordSysInfo = getCoordSysInfoBySeries(seriesModel);
    var coordSysDimDefs;

    if (coordSysInfo && coordSysInfo.coordSysDims) {
      coordSysDimDefs = map(coordSysInfo.coordSysDims, function (dim) {
        var dimInfo = {
          name: dim
        };
        var axisModel = coordSysInfo.axisMap.get(dim);

        if (axisModel) {
          var axisType = axisModel.get('type');
          dimInfo.type = getDimensionTypeByAxis(axisType);
        }

        return dimInfo;
      });
    }

    if (!coordSysDimDefs) {
      coordSysDimDefs = registeredCoordSys && (registeredCoordSys.getDimensionsInfo ? registeredCoordSys.getDimensionsInfo() : registeredCoordSys.dimensions.slice()) || ['x', 'y'];
    }

    var useEncodeDefaulter = opt.useEncodeDefaulter;
    var dimInfoList = createDimensions(source, {
      coordDimensions: coordSysDimDefs,
      generateCoord: opt.generateCoord,
      encodeDefaulter: isFunction(useEncodeDefaulter) ? useEncodeDefaulter : useEncodeDefaulter ? curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null
    });
    var firstCategoryDimIndex;
    var hasNameEncode;
    coordSysInfo && each(dimInfoList, function (dimInfo, dimIndex) {
      var coordDim = dimInfo.coordDim;
      var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim);

      if (categoryAxisModel) {
        if (firstCategoryDimIndex == null) {
          firstCategoryDimIndex = dimIndex;
        }

        dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta();
      }

      if (dimInfo.otherDims.itemName != null) {
        hasNameEncode = true;
      }
    });

    if (!hasNameEncode && firstCategoryDimIndex != null) {
      dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0;
    }

    var stackCalculationInfo = enableDataStack(seriesModel, dimInfoList);
    var list = new List(dimInfoList, seriesModel);
    list.setCalculationInfo(stackCalculationInfo);
    var dimValueGetter = firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source) ? function (itemOpt, dimName, dataIndex, dimIndex) {
      return dimIndex === firstCategoryDimIndex ? dataIndex : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex);
    } : null;
    list.hasItemOption = false;
    list.initData(source, null, dimValueGetter);
    return list;
  }

  function isNeedCompleteOrdinalData(source) {
    if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) {
      var sampleItem = firstDataNotNull(source.data || []);
      return sampleItem != null && !isArray(getDataItemValue(sampleItem));
    }
  }

  function firstDataNotNull(data) {
    var i = 0;

    while (i < data.length && data[i] == null) {
      i++;
    }

    return data[i];
  }

  var Scale = function () {
    function Scale(setting) {
      this._setting = setting || {};
      this._extent = [Infinity, -Infinity];
    }

    Scale.prototype.getSetting = function (name) {
      return this._setting[name];
    };

    Scale.prototype.unionExtent = function (other) {
      var extent = this._extent;
      other[0] < extent[0] && (extent[0] = other[0]);
      other[1] > extent[1] && (extent[1] = other[1]);
    };

    Scale.prototype.unionExtentFromData = function (data, dim) {
      this.unionExtent(data.getApproximateExtent(dim));
    };

    Scale.prototype.getExtent = function () {
      return this._extent.slice();
    };

    Scale.prototype.setExtent = function (start, end) {
      var thisExtent = this._extent;

      if (!isNaN(start)) {
        thisExtent[0] = start;
      }

      if (!isNaN(end)) {
        thisExtent[1] = end;
      }
    };

    Scale.prototype.isInExtentRange = function (value) {
      return this._extent[0] <= value && this._extent[1] >= value;
    };

    Scale.prototype.isBlank = function () {
      return this._isBlank;
    };

    Scale.prototype.setBlank = function (isBlank) {
      this._isBlank = isBlank;
    };

    return Scale;
  }();

  enableClassManagement(Scale, {
    registerWhenExtend: true
  });

  var OrdinalMeta = function () {
    function OrdinalMeta(opt) {
      this.categories = opt.categories || [];
      this._needCollect = opt.needCollect;
      this._deduplication = opt.deduplication;
    }

    OrdinalMeta.createByAxisModel = function (axisModel) {
      var option = axisModel.option;
      var data = option.data;
      var categories = data && map(data, getName);
      return new OrdinalMeta({
        categories: categories,
        needCollect: !categories,
        deduplication: option.dedplication !== false
      });
    };

    OrdinalMeta.prototype.getOrdinal = function (category) {
      return this._getOrCreateMap().get(category);
    };

    OrdinalMeta.prototype.parseAndCollect = function (category) {
      var index;
      var needCollect = this._needCollect;

      if (typeof category !== 'string' && !needCollect) {
        return category;
      }

      if (needCollect && !this._deduplication) {
        index = this.categories.length;
        this.categories[index] = category;
        return index;
      }

      var map = this._getOrCreateMap();

      index = map.get(category);

      if (index == null) {
        if (needCollect) {
          index = this.categories.length;
          this.categories[index] = category;
          map.set(category, index);
        } else {
          index = NaN;
        }
      }

      return index;
    };

    OrdinalMeta.prototype._getOrCreateMap = function () {
      return this._map || (this._map = createHashMap(this.categories));
    };

    return OrdinalMeta;
  }();

  function getName(obj) {
    if (isObject(obj) && obj.value != null) {
      return obj.value;
    } else {
      return obj + '';
    }
  }

  var roundNumber = round$1;

  function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) {
    var result = {};
    var span = extent[1] - extent[0];
    var interval = result.interval = nice(span / splitNumber, true);

    if (minInterval != null && interval < minInterval) {
      interval = result.interval = minInterval;
    }

    if (maxInterval != null && interval > maxInterval) {
      interval = result.interval = maxInterval;
    }

    var precision = result.intervalPrecision = getIntervalPrecision(interval);
    var niceTickExtent = result.niceTickExtent = [roundNumber(Math.ceil(extent[0] / interval) * interval, precision), roundNumber(Math.floor(extent[1] / interval) * interval, precision)];
    fixExtent(niceTickExtent, extent);
    return result;
  }

  function getIntervalPrecision(interval) {
    return getPrecisionSafe(interval) + 2;
  }

  function clamp(niceTickExtent, idx, extent) {
    niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]);
  }

  function fixExtent(niceTickExtent, extent) {
    !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]);
    !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]);
    clamp(niceTickExtent, 0, extent);
    clamp(niceTickExtent, 1, extent);

    if (niceTickExtent[0] > niceTickExtent[1]) {
      niceTickExtent[0] = niceTickExtent[1];
    }
  }

  function contain$1(val, extent) {
    return val >= extent[0] && val <= extent[1];
  }

  function normalize$1(val, extent) {
    if (extent[1] === extent[0]) {
      return 0.5;
    }

    return (val - extent[0]) / (extent[1] - extent[0]);
  }

  function scale$2(val, extent) {
    return val * (extent[1] - extent[0]) + extent[0];
  }

  var OrdinalScale = function (_super) {
    __extends(OrdinalScale, _super);

    function OrdinalScale(setting) {
      var _this = _super.call(this, setting) || this;

      _this.type = 'ordinal';

      var ordinalMeta = _this.getSetting('ordinalMeta');

      if (!ordinalMeta) {
        ordinalMeta = new OrdinalMeta({});
      }

      if (isArray(ordinalMeta)) {
        ordinalMeta = new OrdinalMeta({
          categories: map(ordinalMeta, function (item) {
            return isObject(item) ? item.value : item;
          })
        });
      }

      _this._ordinalMeta = ordinalMeta;
      _this._categorySortInfo = [];
      _this._extent = _this.getSetting('extent') || [0, ordinalMeta.categories.length - 1];
      return _this;
    }

    OrdinalScale.prototype.parse = function (val) {
      return typeof val === 'string' ? this._ordinalMeta.getOrdinal(val) : Math.round(val);
    };

    OrdinalScale.prototype.contain = function (rank) {
      rank = this.parse(rank);
      return contain$1(rank, this._extent) && this._ordinalMeta.categories[rank] != null;
    };

    OrdinalScale.prototype.normalize = function (val) {
      val = this.getCategoryIndex(this.parse(val));
      return normalize$1(val, this._extent);
    };

    OrdinalScale.prototype.scale = function (val) {
      val = this.getCategoryIndex(val);
      return Math.round(scale$2(val, this._extent));
    };

    OrdinalScale.prototype.getTicks = function () {
      var ticks = [];
      var extent = this._extent;
      var rank = extent[0];

      while (rank <= extent[1]) {
        ticks.push({
          value: this.getCategoryIndex(rank)
        });
        rank++;
      }

      return ticks;
    };

    OrdinalScale.prototype.getMinorTicks = function (splitNumber) {
      return;
    };

    OrdinalScale.prototype.setCategorySortInfo = function (info) {
      this._categorySortInfo = info;
    };

    OrdinalScale.prototype.getCategorySortInfo = function () {
      return this._categorySortInfo;
    };

    OrdinalScale.prototype.getCategoryIndex = function (n) {
      if (this._categorySortInfo.length) {
        return this._categorySortInfo[n].beforeSortIndex;
      } else {
        return n;
      }
    };

    OrdinalScale.prototype.getRawIndex = function (displayIndex) {
      if (this._categorySortInfo.length) {
        return this._categorySortInfo[displayIndex].ordinalNumber;
      } else {
        return displayIndex;
      }
    };

    OrdinalScale.prototype.getLabel = function (tick) {
      if (!this.isBlank()) {
        var rawIndex = this.getRawIndex(tick.value);
        var cateogry = this._ordinalMeta.categories[rawIndex];
        return cateogry == null ? '' : cateogry + '';
      }
    };

    OrdinalScale.prototype.count = function () {
      return this._extent[1] - this._extent[0] + 1;
    };

    OrdinalScale.prototype.unionExtentFromData = function (data, dim) {
      this.unionExtent(data.getApproximateExtent(dim));
    };

    OrdinalScale.prototype.isInExtentRange = function (value) {
      value = this.getCategoryIndex(value);
      return this._extent[0] <= value && this._extent[1] >= value;
    };

    OrdinalScale.prototype.getOrdinalMeta = function () {
      return this._ordinalMeta;
    };

    OrdinalScale.prototype.niceTicks = function () {};

    OrdinalScale.prototype.niceExtent = function () {};

    OrdinalScale.type = 'ordinal';
    return OrdinalScale;
  }(Scale);

  Scale.registerClass(OrdinalScale);
  var roundNumber$1 = round$1;

  var IntervalScale = function (_super) {
    __extends(IntervalScale, _super);

    function IntervalScale() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'interval';
      _this._interval = 0;
      _this._intervalPrecision = 2;
      return _this;
    }

    IntervalScale.prototype.parse = function (val) {
      return val;
    };

    IntervalScale.prototype.contain = function (val) {
      return contain$1(val, this._extent);
    };

    IntervalScale.prototype.normalize = function (val) {
      return normalize$1(val, this._extent);
    };

    IntervalScale.prototype.scale = function (val) {
      return scale$2(val, this._extent);
    };

    IntervalScale.prototype.setExtent = function (start, end) {
      var thisExtent = this._extent;

      if (!isNaN(start)) {
        thisExtent[0] = parseFloat(start);
      }

      if (!isNaN(end)) {
        thisExtent[1] = parseFloat(end);
      }
    };

    IntervalScale.prototype.unionExtent = function (other) {
      var extent = this._extent;
      other[0] < extent[0] && (extent[0] = other[0]);
      other[1] > extent[1] && (extent[1] = other[1]);
      this.setExtent(extent[0], extent[1]);
    };

    IntervalScale.prototype.getInterval = function () {
      return this._interval;
    };

    IntervalScale.prototype.setInterval = function (interval) {
      this._interval = interval;
      this._niceExtent = this._extent.slice();
      this._intervalPrecision = getIntervalPrecision(interval);
    };

    IntervalScale.prototype.getTicks = function (expandToNicedExtent) {
      var interval = this._interval;
      var extent = this._extent;
      var niceTickExtent = this._niceExtent;
      var intervalPrecision = this._intervalPrecision;
      var ticks = [];

      if (!interval) {
        return ticks;
      }

      var safeLimit = 10000;

      if (extent[0] < niceTickExtent[0]) {
        if (expandToNicedExtent) {
          ticks.push({
            value: roundNumber$1(niceTickExtent[0] - interval, intervalPrecision)
          });
        } else {
          ticks.push({
            value: extent[0]
          });
        }
      }

      var tick = niceTickExtent[0];

      while (tick <= niceTickExtent[1]) {
        ticks.push({
          value: tick
        });
        tick = roundNumber$1(tick + interval, intervalPrecision);

        if (tick === ticks[ticks.length - 1].value) {
          break;
        }

        if (ticks.length > safeLimit) {
          return [];
        }
      }

      var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceTickExtent[1];

      if (extent[1] > lastNiceTick) {
        if (expandToNicedExtent) {
          ticks.push({
            value: roundNumber$1(lastNiceTick + interval, intervalPrecision)
          });
        } else {
          ticks.push({
            value: extent[1]
          });
        }
      }

      return ticks;
    };

    IntervalScale.prototype.getMinorTicks = function (splitNumber) {
      var ticks = this.getTicks(true);
      var minorTicks = [];
      var extent = this.getExtent();

      for (var i = 1; i < ticks.length; i++) {
        var nextTick = ticks[i];
        var prevTick = ticks[i - 1];
        var count = 0;
        var minorTicksGroup = [];
        var interval = nextTick.value - prevTick.value;
        var minorInterval = interval / splitNumber;

        while (count < splitNumber - 1) {
          var minorTick = roundNumber$1(prevTick.value + (count + 1) * minorInterval);

          if (minorTick > extent[0] && minorTick < extent[1]) {
            minorTicksGroup.push(minorTick);
          }

          count++;
        }

        minorTicks.push(minorTicksGroup);
      }

      return minorTicks;
    };

    IntervalScale.prototype.getLabel = function (data, opt) {
      if (data == null) {
        return '';
      }

      var precision = opt && opt.precision;

      if (precision == null) {
        precision = getPrecisionSafe(data.value) || 0;
      } else if (precision === 'auto') {
        precision = this._intervalPrecision;
      }

      var dataNum = roundNumber$1(data.value, precision, true);
      return addCommas(dataNum);
    };

    IntervalScale.prototype.niceTicks = function (splitNumber, minInterval, maxInterval) {
      splitNumber = splitNumber || 5;
      var extent = this._extent;
      var span = extent[1] - extent[0];

      if (!isFinite(span)) {
        return;
      }

      if (span < 0) {
        span = -span;
        extent.reverse();
      }

      var result = intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval);
      this._intervalPrecision = result.intervalPrecision;
      this._interval = result.interval;
      this._niceExtent = result.niceTickExtent;
    };

    IntervalScale.prototype.niceExtent = function (opt) {
      var extent = this._extent;

      if (extent[0] === extent[1]) {
        if (extent[0] !== 0) {
          var expandSize = extent[0];

          if (!opt.fixMax) {
            extent[1] += expandSize / 2;
            extent[0] -= expandSize / 2;
          } else {
            extent[0] -= expandSize / 2;
          }
        } else {
          extent[1] = 1;
        }
      }

      var span = extent[1] - extent[0];

      if (!isFinite(span)) {
        extent[0] = 0;
        extent[1] = 1;
      }

      this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);
      var interval = this._interval;

      if (!opt.fixMin) {
        extent[0] = roundNumber$1(Math.floor(extent[0] / interval) * interval);
      }

      if (!opt.fixMax) {
        extent[1] = roundNumber$1(Math.ceil(extent[1] / interval) * interval);
      }
    };

    IntervalScale.type = 'interval';
    return IntervalScale;
  }(Scale);

  Scale.registerClass(IntervalScale);
  var STACK_PREFIX = '__ec_stack_';
  var LARGE_BAR_MIN_WIDTH = 0.5;
  var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array;

  function getSeriesStackId(seriesModel) {
    return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
  }

  function getAxisKey(axis) {
    return axis.dim + axis.index;
  }

  function getLayoutOnAxis(opt) {
    var params = [];
    var baseAxis = opt.axis;
    var axisKey = 'axis0';

    if (baseAxis.type !== 'category') {
      return;
    }

    var bandWidth = baseAxis.getBandWidth();

    for (var i = 0; i < opt.count || 0; i++) {
      params.push(defaults({
        bandWidth: bandWidth,
        axisKey: axisKey,
        stackId: STACK_PREFIX + i
      }, opt));
    }

    var widthAndOffsets = doCalBarWidthAndOffset(params);
    var result = [];

    for (var i = 0; i < opt.count; i++) {
      var item = widthAndOffsets[axisKey][STACK_PREFIX + i];
      item.offsetCenter = item.offset + item.width / 2;
      result.push(item);
    }

    return result;
  }

  function prepareLayoutBarSeries(seriesType, ecModel) {
    var seriesModels = [];
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
      if (isOnCartesian(seriesModel) && !isInLargeMode(seriesModel)) {
        seriesModels.push(seriesModel);
      }
    });
    return seriesModels;
  }

  function getValueAxesMinGaps(barSeries) {
    var axisValues = {};
    each(barSeries, function (seriesModel) {
      var cartesian = seriesModel.coordinateSystem;
      var baseAxis = cartesian.getBaseAxis();

      if (baseAxis.type !== 'time' && baseAxis.type !== 'value') {
        return;
      }

      var data = seriesModel.getData();
      var key = baseAxis.dim + '_' + baseAxis.index;
      var dim = data.mapDimension(baseAxis.dim);

      for (var i = 0, cnt = data.count(); i < cnt; ++i) {
        var value = data.get(dim, i);

        if (!axisValues[key]) {
          axisValues[key] = [value];
        } else {
          axisValues[key].push(value);
        }
      }
    });
    var axisMinGaps = {};

    for (var key in axisValues) {
      if (axisValues.hasOwnProperty(key)) {
        var valuesInAxis = axisValues[key];

        if (valuesInAxis) {
          valuesInAxis.sort(function (a, b) {
            return a - b;
          });
          var min = null;

          for (var j = 1; j < valuesInAxis.length; ++j) {
            var delta = valuesInAxis[j] - valuesInAxis[j - 1];

            if (delta > 0) {
              min = min === null ? delta : Math.min(min, delta);
            }
          }

          axisMinGaps[key] = min;
        }
      }
    }

    return axisMinGaps;
  }

  function makeColumnLayout(barSeries) {
    var axisMinGaps = getValueAxesMinGaps(barSeries);
    var seriesInfoList = [];
    each(barSeries, function (seriesModel) {
      var cartesian = seriesModel.coordinateSystem;
      var baseAxis = cartesian.getBaseAxis();
      var axisExtent = baseAxis.getExtent();
      var bandWidth;

      if (baseAxis.type === 'category') {
        bandWidth = baseAxis.getBandWidth();
      } else if (baseAxis.type === 'value' || baseAxis.type === 'time') {
        var key = baseAxis.dim + '_' + baseAxis.index;
        var minGap = axisMinGaps[key];
        var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]);
        var scale = baseAxis.scale.getExtent();
        var scaleSpan = Math.abs(scale[1] - scale[0]);
        bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan;
      } else {
        var data = seriesModel.getData();
        bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count();
      }

      var barWidth = parsePercent$2(seriesModel.get('barWidth'), bandWidth);
      var barMaxWidth = parsePercent$2(seriesModel.get('barMaxWidth'), bandWidth);
      var barMinWidth = parsePercent$2(seriesModel.get('barMinWidth') || 1, bandWidth);
      var barGap = seriesModel.get('barGap');
      var barCategoryGap = seriesModel.get('barCategoryGap');
      seriesInfoList.push({
        bandWidth: bandWidth,
        barWidth: barWidth,
        barMaxWidth: barMaxWidth,
        barMinWidth: barMinWidth,
        barGap: barGap,
        barCategoryGap: barCategoryGap,
        axisKey: getAxisKey(baseAxis),
        stackId: getSeriesStackId(seriesModel)
      });
    });
    return doCalBarWidthAndOffset(seriesInfoList);
  }

  function doCalBarWidthAndOffset(seriesInfoList) {
    var columnsMap = {};
    each(seriesInfoList, function (seriesInfo, idx) {
      var axisKey = seriesInfo.axisKey;
      var bandWidth = seriesInfo.bandWidth;
      var columnsOnAxis = columnsMap[axisKey] || {
        bandWidth: bandWidth,
        remainedWidth: bandWidth,
        autoWidthCount: 0,
        categoryGap: null,
        gap: '20%',
        stacks: {}
      };
      var stacks = columnsOnAxis.stacks;
      columnsMap[axisKey] = columnsOnAxis;
      var stackId = seriesInfo.stackId;

      if (!stacks[stackId]) {
        columnsOnAxis.autoWidthCount++;
      }

      stacks[stackId] = stacks[stackId] || {
        width: 0,
        maxWidth: 0
      };
      var barWidth = seriesInfo.barWidth;

      if (barWidth && !stacks[stackId].width) {
        stacks[stackId].width = barWidth;
        barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
        columnsOnAxis.remainedWidth -= barWidth;
      }

      var barMaxWidth = seriesInfo.barMaxWidth;
      barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
      var barMinWidth = seriesInfo.barMinWidth;
      barMinWidth && (stacks[stackId].minWidth = barMinWidth);
      var barGap = seriesInfo.barGap;
      barGap != null && (columnsOnAxis.gap = barGap);
      var barCategoryGap = seriesInfo.barCategoryGap;
      barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap);
    });
    var result = {};
    each(columnsMap, function (columnsOnAxis, coordSysName) {
      result[coordSysName] = {};
      var stacks = columnsOnAxis.stacks;
      var bandWidth = columnsOnAxis.bandWidth;
      var categoryGapPercent = columnsOnAxis.categoryGap;

      if (categoryGapPercent == null) {
        var columnCount = keys(stacks).length;
        categoryGapPercent = Math.max(35 - columnCount * 4, 15) + '%';
      }

      var categoryGap = parsePercent$2(categoryGapPercent, bandWidth);
      var barGapPercent = parsePercent$2(columnsOnAxis.gap, 1);
      var remainedWidth = columnsOnAxis.remainedWidth;
      var autoWidthCount = columnsOnAxis.autoWidthCount;
      var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
      autoWidth = Math.max(autoWidth, 0);
      each(stacks, function (column) {
        var maxWidth = column.maxWidth;
        var minWidth = column.minWidth;

        if (!column.width) {
          var finalWidth = autoWidth;

          if (maxWidth && maxWidth < finalWidth) {
            finalWidth = Math.min(maxWidth, remainedWidth);
          }

          if (minWidth && minWidth > finalWidth) {
            finalWidth = minWidth;
          }

          if (finalWidth !== autoWidth) {
            column.width = finalWidth;
            remainedWidth -= finalWidth + barGapPercent * finalWidth;
            autoWidthCount--;
          }
        } else {
          var finalWidth = column.width;

          if (maxWidth) {
            finalWidth = Math.min(finalWidth, maxWidth);
          }

          if (minWidth) {
            finalWidth = Math.max(finalWidth, minWidth);
          }

          column.width = finalWidth;
          remainedWidth -= finalWidth + barGapPercent * finalWidth;
          autoWidthCount--;
        }
      });
      autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
      autoWidth = Math.max(autoWidth, 0);
      var widthSum = 0;
      var lastColumn;
      each(stacks, function (column, idx) {
        if (!column.width) {
          column.width = autoWidth;
        }

        lastColumn = column;
        widthSum += column.width * (1 + barGapPercent);
      });

      if (lastColumn) {
        widthSum -= lastColumn.width * barGapPercent;
      }

      var offset = -widthSum / 2;
      each(stacks, function (column, stackId) {
        result[coordSysName][stackId] = result[coordSysName][stackId] || {
          bandWidth: bandWidth,
          offset: offset,
          width: column.width
        };
        offset += column.width * (1 + barGapPercent);
      });
    });
    return result;
  }

  function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) {
    if (barWidthAndOffset && axis) {
      var result = barWidthAndOffset[getAxisKey(axis)];

      if (result != null && seriesModel != null) {
        return result[getSeriesStackId(seriesModel)];
      }

      return result;
    }
  }

  function layout(seriesType, ecModel) {
    var seriesModels = prepareLayoutBarSeries(seriesType, ecModel);
    var barWidthAndOffset = makeColumnLayout(seriesModels);
    var lastStackCoords = {};
    each(seriesModels, function (seriesModel) {
      var data = seriesModel.getData();
      var cartesian = seriesModel.coordinateSystem;
      var baseAxis = cartesian.getBaseAxis();
      var stackId = getSeriesStackId(seriesModel);
      var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
      var columnOffset = columnLayoutInfo.offset;
      var columnWidth = columnLayoutInfo.width;
      var valueAxis = cartesian.getOtherAxis(baseAxis);
      var barMinHeight = seriesModel.get('barMinHeight') || 0;
      lastStackCoords[stackId] = lastStackCoords[stackId] || [];
      data.setLayout({
        bandWidth: columnLayoutInfo.bandWidth,
        offset: columnOffset,
        size: columnWidth
      });
      var valueDim = data.mapDimension(valueAxis.dim);
      var baseDim = data.mapDimension(baseAxis.dim);
      var stacked = isDimensionStacked(data, valueDim);
      var isValueAxisH = valueAxis.isHorizontal();
      var valueAxisStart = getValueAxisStart(baseAxis, valueAxis);

      for (var idx = 0, len = data.count(); idx < len; idx++) {
        var value = data.get(valueDim, idx);
        var baseValue = data.get(baseDim, idx);
        var sign = value >= 0 ? 'p' : 'n';
        var baseCoord = valueAxisStart;

        if (stacked) {
          if (!lastStackCoords[stackId][baseValue]) {
            lastStackCoords[stackId][baseValue] = {
              p: valueAxisStart,
              n: valueAxisStart
            };
          }

          baseCoord = lastStackCoords[stackId][baseValue][sign];
        }

        var x = void 0;
        var y = void 0;
        var width = void 0;
        var height = void 0;

        if (isValueAxisH) {
          var coord = cartesian.dataToPoint([value, baseValue]);
          x = baseCoord;
          y = coord[1] + columnOffset;
          width = coord[0] - valueAxisStart;
          height = columnWidth;

          if (Math.abs(width) < barMinHeight) {
            width = (width < 0 ? -1 : 1) * barMinHeight;
          }

          if (!isNaN(width)) {
            stacked && (lastStackCoords[stackId][baseValue][sign] += width);
          }
        } else {
          var coord = cartesian.dataToPoint([baseValue, value]);
          x = coord[0] + columnOffset;
          y = baseCoord;
          width = columnWidth;
          height = coord[1] - valueAxisStart;

          if (Math.abs(height) < barMinHeight) {
            height = (height <= 0 ? -1 : 1) * barMinHeight;
          }

          if (!isNaN(height)) {
            stacked && (lastStackCoords[stackId][baseValue][sign] += height);
          }
        }

        data.setItemLayout(idx, {
          x: x,
          y: y,
          width: width,
          height: height
        });
      }
    });
  }

  var largeLayout = {
    seriesType: 'bar',
    plan: createRenderPlanner(),
    reset: function (seriesModel) {
      if (!isOnCartesian(seriesModel) || !isInLargeMode(seriesModel)) {
        return;
      }

      var data = seriesModel.getData();
      var cartesian = seriesModel.coordinateSystem;
      var coordLayout = cartesian.master.getRect();
      var baseAxis = cartesian.getBaseAxis();
      var valueAxis = cartesian.getOtherAxis(baseAxis);
      var valueDim = data.mapDimension(valueAxis.dim);
      var baseDim = data.mapDimension(baseAxis.dim);
      var valueAxisHorizontal = valueAxis.isHorizontal();
      var valueDimIdx = valueAxisHorizontal ? 0 : 1;
      var barWidth = retrieveColumnLayout(makeColumnLayout([seriesModel]), baseAxis, seriesModel).width;

      if (!(barWidth > LARGE_BAR_MIN_WIDTH)) {
        barWidth = LARGE_BAR_MIN_WIDTH;
      }

      return {
        progress: function (params, data) {
          var count = params.count;
          var largePoints = new LargeArr(count * 2);
          var largeBackgroundPoints = new LargeArr(count * 2);
          var largeDataIndices = new LargeArr(count);
          var dataIndex;
          var coord = [];
          var valuePair = [];
          var pointsOffset = 0;
          var idxOffset = 0;

          while ((dataIndex = params.next()) != null) {
            valuePair[valueDimIdx] = data.get(valueDim, dataIndex);
            valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex);
            coord = cartesian.dataToPoint(valuePair, null, coord);
            largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0];
            largePoints[pointsOffset++] = coord[0];
            largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height;
            largePoints[pointsOffset++] = coord[1];
            largeDataIndices[idxOffset++] = dataIndex;
          }

          data.setLayout({
            largePoints: largePoints,
            largeDataIndices: largeDataIndices,
            largeBackgroundPoints: largeBackgroundPoints,
            barWidth: barWidth,
            valueAxisStart: getValueAxisStart(baseAxis, valueAxis),
            backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y,
            valueAxisHorizontal: valueAxisHorizontal
          });
        }
      };
    }
  };

  function isOnCartesian(seriesModel) {
    return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d';
  }

  function isInLargeMode(seriesModel) {
    return seriesModel.pipelineContext && seriesModel.pipelineContext.large;
  }

  function getValueAxisStart(baseAxis, valueAxis, stacked) {
    return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0));
  }

  var bisect = function (a, x, lo, hi) {
    while (lo < hi) {
      var mid = lo + hi >>> 1;

      if (a[mid][1] < x) {
        lo = mid + 1;
      } else {
        hi = mid;
      }
    }

    return lo;
  };

  var TimeScale = function (_super) {
    __extends(TimeScale, _super);

    function TimeScale(settings) {
      var _this = _super.call(this, settings) || this;

      _this.type = 'time';
      return _this;
    }

    TimeScale.prototype.getLabel = function (tick) {
      var useUTC = this.getSetting('useUTC');
      return format(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, useUTC, this.getSetting('locale'));
    };

    TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) {
      var isUTC = this.getSetting('useUTC');
      var lang = this.getSetting('locale');
      return leveledFormat(tick, idx, labelFormatter, lang, isUTC);
    };

    TimeScale.prototype.getTicks = function (expandToNicedExtent) {
      var interval = this._interval;
      var extent = this._extent;
      var ticks = [];

      if (!interval) {
        return ticks;
      }

      ticks.push({
        value: extent[0],
        level: 0
      });
      var useUTC = this.getSetting('useUTC');
      var innerTicks = getIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent);
      ticks = ticks.concat(innerTicks);
      ticks.push({
        value: extent[1],
        level: 0
      });
      return ticks;
    };

    TimeScale.prototype.niceExtent = function (opt) {
      var extent = this._extent;

      if (extent[0] === extent[1]) {
        extent[0] -= ONE_DAY;
        extent[1] += ONE_DAY;
      }

      if (extent[1] === -Infinity && extent[0] === Infinity) {
        var d = new Date();
        extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate());
        extent[0] = extent[1] - ONE_DAY;
      }

      this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);
    };

    TimeScale.prototype.niceTicks = function (approxTickNum, minInterval, maxInterval) {
      approxTickNum = approxTickNum || 10;
      var extent = this._extent;
      var span = extent[1] - extent[0];
      this._approxInterval = span / approxTickNum;

      if (minInterval != null && this._approxInterval < minInterval) {
        this._approxInterval = minInterval;
      }

      if (maxInterval != null && this._approxInterval > maxInterval) {
        this._approxInterval = maxInterval;
      }

      var scaleIntervalsLen = scaleIntervals.length;
      var idx = Math.min(bisect(scaleIntervals, this._approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1);
      this._interval = scaleIntervals[idx][1];
      this._minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0];
    };

    TimeScale.prototype.parse = function (val) {
      return typeof val === 'number' ? val : +parseDate(val);
    };

    TimeScale.prototype.contain = function (val) {
      return contain$1(this.parse(val), this._extent);
    };

    TimeScale.prototype.normalize = function (val) {
      return normalize$1(this.parse(val), this._extent);
    };

    TimeScale.prototype.scale = function (val) {
      return scale$2(val, this._extent);
    };

    TimeScale.type = 'time';
    return TimeScale;
  }(IntervalScale);

  var scaleIntervals = [['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR]];

  function isUnitValueSame(unit, valueA, valueB, isUTC) {
    var dateA = parseDate(valueA);
    var dateB = parseDate(valueB);

    var isSame = function (unit) {
      return getUnitValue(dateA, unit, isUTC) === getUnitValue(dateB, unit, isUTC);
    };

    var isSameYear = function () {
      return isSame('year');
    };

    var isSameMonth = function () {
      return isSameYear() && isSame('month');
    };

    var isSameDay = function () {
      return isSameMonth() && isSame('day');
    };

    var isSameHour = function () {
      return isSameDay() && isSame('hour');
    };

    var isSameMinute = function () {
      return isSameHour() && isSame('minute');
    };

    var isSameSecond = function () {
      return isSameMinute() && isSame('second');
    };

    var isSameMilliSecond = function () {
      return isSameSecond() && isSame('millisecond');
    };

    switch (unit) {
      case 'year':
        return isSameYear();

      case 'month':
        return isSameMonth();

      case 'day':
        return isSameDay();

      case 'hour':
        return isSameHour();

      case 'minute':
        return isSameMinute();

      case 'second':
        return isSameSecond();

      case 'millisecond':
        return isSameMilliSecond();
    }
  }

  function getDateInterval(approxInterval, daysInMonth) {
    approxInterval /= ONE_DAY;
    return approxInterval > 16 ? 16 : approxInterval > 7.5 ? 7 : approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1;
  }

  function getMonthInterval(approxInterval) {
    var APPROX_ONE_MONTH = 30 * ONE_DAY;
    approxInterval /= APPROX_ONE_MONTH;
    return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1;
  }

  function getHourInterval(approxInterval) {
    approxInterval /= ONE_HOUR;
    return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1;
  }

  function getMinutesAndSecondsInterval(approxInterval, isMinutes) {
    approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND;
    return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1;
  }

  function getMillisecondsInterval(approxInterval) {
    return nice(approxInterval, true);
  }

  function getFirstTimestampOfUnit(date, unitName, isUTC) {
    var outDate = new Date(date);

    switch (getPrimaryTimeUnit(unitName)) {
      case 'year':
      case 'month':
        outDate[monthSetterName(isUTC)](0);

      case 'day':
        outDate[dateSetterName(isUTC)](1);

      case 'hour':
        outDate[hoursSetterName(isUTC)](0);

      case 'minute':
        outDate[minutesSetterName(isUTC)](0);

      case 'second':
        outDate[secondsSetterName(isUTC)](0);
        outDate[millisecondsSetterName(isUTC)](0);
    }

    return outDate.getTime();
  }

  function getIntervalTicks(bottomUnitName, approxInterval, isUTC, extent) {
    var safeLimit = 10000;
    var unitNames = timeUnits;
    var iter = 0;

    function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) {
      var date = new Date(minTimestamp);
      var dateTime = minTimestamp;
      var d = date[getMethodName]();

      while (dateTime < maxTimestamp && dateTime <= extent[1]) {
        out.push({
          value: dateTime
        });
        d += interval;
        date[setMethodName](d);
        dateTime = date.getTime();
      }

      out.push({
        value: dateTime,
        notAdd: true
      });
    }

    function addLevelTicks(unitName, lastLevelTicks, levelTicks) {
      var newAddedTicks = [];
      var isFirstLevel = !lastLevelTicks.length;

      if (isUnitValueSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) {
        return;
      }

      if (isFirstLevel) {
        lastLevelTicks = [{
          value: getFirstTimestampOfUnit(new Date(extent[0]), unitName, isUTC)
        }, {
          value: extent[1]
        }];
      }

      for (var i = 0; i < lastLevelTicks.length - 1; i++) {
        var startTick = lastLevelTicks[i].value;
        var endTick = lastLevelTicks[i + 1].value;

        if (startTick === endTick) {
          continue;
        }

        var interval = void 0;
        var getterName = void 0;
        var setterName = void 0;
        var isDate = false;

        switch (unitName) {
          case 'year':
            interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365));
            getterName = fullYearGetterName(isUTC);
            setterName = fullYearSetterName(isUTC);
            break;

          case 'half-year':
          case 'quarter':
          case 'month':
            interval = getMonthInterval(approxInterval);
            getterName = monthGetterName(isUTC);
            setterName = monthSetterName(isUTC);
            break;

          case 'week':
          case 'half-week':
          case 'day':
            interval = getDateInterval(approxInterval);
            getterName = dateGetterName(isUTC);
            setterName = dateSetterName(isUTC);
            isDate = true;
            break;

          case 'half-day':
          case 'quarter-day':
          case 'hour':
            interval = getHourInterval(approxInterval);
            getterName = hoursGetterName(isUTC);
            setterName = hoursSetterName(isUTC);
            break;

          case 'minute':
            interval = getMinutesAndSecondsInterval(approxInterval, true);
            getterName = minutesGetterName(isUTC);
            setterName = minutesSetterName(isUTC);
            break;

          case 'second':
            interval = getMinutesAndSecondsInterval(approxInterval, false);
            getterName = secondsGetterName(isUTC);
            setterName = secondsSetterName(isUTC);
            break;

          case 'millisecond':
            interval = getMillisecondsInterval(approxInterval);
            getterName = millisecondsGetterName(isUTC);
            setterName = millisecondsSetterName(isUTC);
            break;
        }

        addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks);

        if (unitName === 'year' && levelTicks.length > 1 && i === 0) {
          levelTicks.unshift({
            value: levelTicks[0].value - interval
          });
        }
      }

      for (var i = 0; i < newAddedTicks.length; i++) {
        levelTicks.push(newAddedTicks[i]);
      }

      return newAddedTicks;
    }

    var levelsTicks = [];
    var currentLevelTicks = [];
    var tickCount = 0;
    var lastLevelTickCount = 0;

    for (var i = 0; i < unitNames.length && iter++ < safeLimit; ++i) {
      var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]);

      if (!isPrimaryTimeUnit(unitNames[i])) {
        continue;
      }

      addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks);
      var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null;

      if (primaryTimeUnit !== nextPrimaryTimeUnit) {
        if (currentLevelTicks.length) {
          lastLevelTickCount = tickCount;
          currentLevelTicks.sort(function (a, b) {
            return a.value - b.value;
          });
          var levelTicksRemoveDuplicated = [];

          for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) {
            var tickValue = currentLevelTicks[i_1].value;

            if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) {
              levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]);

              if (tickValue >= extent[0] && tickValue <= extent[1]) {
                tickCount++;
              }
            }
          }

          var targetTickNum = (extent[1] - extent[0]) / approxInterval;

          if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) {
            break;
          }

          levelsTicks.push(levelTicksRemoveDuplicated);

          if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) {
            break;
          }
        }

        currentLevelTicks = [];
      }
    }

    if (true) {
      if (iter >= safeLimit) {
        warn('Exceed safe limit.');
      }
    }

    var levelsTicksInExtent = filter(map(levelsTicks, function (levelTicks) {
      return filter(levelTicks, function (tick) {
        return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd;
      });
    }), function (levelTicks) {
      return levelTicks.length > 0;
    });
    var ticks = [];
    var maxLevel = levelsTicksInExtent.length - 1;

    for (var i = 0; i < levelsTicksInExtent.length; ++i) {
      var levelTicks = levelsTicksInExtent[i];

      for (var k = 0; k < levelTicks.length; ++k) {
        ticks.push({
          value: levelTicks[k].value,
          level: maxLevel - i
        });
      }
    }

    ticks.sort(function (a, b) {
      return a.value - b.value;
    });
    var result = [];

    for (var i = 0; i < ticks.length; ++i) {
      if (i === 0 || ticks[i].value !== ticks[i - 1].value) {
        result.push(ticks[i]);
      }
    }

    return result;
  }

  Scale.registerClass(TimeScale);
  var scaleProto = Scale.prototype;
  var intervalScaleProto = IntervalScale.prototype;
  var getPrecisionSafe$1 = getPrecisionSafe;
  var roundingErrorFix = round$1;
  var mathFloor$1 = Math.floor;
  var mathCeil = Math.ceil;
  var mathPow$1 = Math.pow;
  var mathLog = Math.log;

  var LogScale = function (_super) {
    __extends(LogScale, _super);

    function LogScale() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'log';
      _this.base = 10;
      _this._originalScale = new IntervalScale();
      _this._interval = 0;
      return _this;
    }

    LogScale.prototype.getTicks = function (expandToNicedExtent) {
      var originalScale = this._originalScale;
      var extent = this._extent;
      var originalExtent = originalScale.getExtent();
      var ticks = intervalScaleProto.getTicks.call(this, expandToNicedExtent);
      return map(ticks, function (tick) {
        var val = tick.value;
        var powVal = round$1(mathPow$1(this.base, val));
        powVal = val === extent[0] && this._fixMin ? fixRoundingError(powVal, originalExtent[0]) : powVal;
        powVal = val === extent[1] && this._fixMax ? fixRoundingError(powVal, originalExtent[1]) : powVal;
        return {
          value: powVal
        };
      }, this);
    };

    LogScale.prototype.setExtent = function (start, end) {
      var base = this.base;
      start = mathLog(start) / mathLog(base);
      end = mathLog(end) / mathLog(base);
      intervalScaleProto.setExtent.call(this, start, end);
    };

    LogScale.prototype.getExtent = function () {
      var base = this.base;
      var extent = scaleProto.getExtent.call(this);
      extent[0] = mathPow$1(base, extent[0]);
      extent[1] = mathPow$1(base, extent[1]);
      var originalScale = this._originalScale;
      var originalExtent = originalScale.getExtent();
      this._fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0]));
      this._fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1]));
      return extent;
    };

    LogScale.prototype.unionExtent = function (extent) {
      this._originalScale.unionExtent(extent);

      var base = this.base;
      extent[0] = mathLog(extent[0]) / mathLog(base);
      extent[1] = mathLog(extent[1]) / mathLog(base);
      scaleProto.unionExtent.call(this, extent);
    };

    LogScale.prototype.unionExtentFromData = function (data, dim) {
      this.unionExtent(data.getApproximateExtent(dim));
    };

    LogScale.prototype.niceTicks = function (approxTickNum) {
      approxTickNum = approxTickNum || 10;
      var extent = this._extent;
      var span = extent[1] - extent[0];

      if (span === Infinity || span <= 0) {
        return;
      }

      var interval = quantity(span);
      var err = approxTickNum / span * interval;

      if (err <= 0.5) {
        interval *= 10;
      }

      while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) {
        interval *= 10;
      }

      var niceExtent = [round$1(mathCeil(extent[0] / interval) * interval), round$1(mathFloor$1(extent[1] / interval) * interval)];
      this._interval = interval;
      this._niceExtent = niceExtent;
    };

    LogScale.prototype.niceExtent = function (opt) {
      intervalScaleProto.niceExtent.call(this, opt);
      this._fixMin = opt.fixMin;
      this._fixMax = opt.fixMax;
    };

    LogScale.prototype.parse = function (val) {
      return val;
    };

    LogScale.prototype.contain = function (val) {
      val = mathLog(val) / mathLog(this.base);
      return contain$1(val, this._extent);
    };

    LogScale.prototype.normalize = function (val) {
      val = mathLog(val) / mathLog(this.base);
      return normalize$1(val, this._extent);
    };

    LogScale.prototype.scale = function (val) {
      val = scale$2(val, this._extent);
      return mathPow$1(this.base, val);
    };

    LogScale.type = 'log';
    return LogScale;
  }(Scale);

  var proto = LogScale.prototype;
  proto.getMinorTicks = intervalScaleProto.getMinorTicks;
  proto.getLabel = intervalScaleProto.getLabel;

  function fixRoundingError(val, originalVal) {
    return roundingErrorFix(val, getPrecisionSafe$1(originalVal));
  }

  Scale.registerClass(LogScale);

  var ScaleRawExtentInfo = function () {
    function ScaleRawExtentInfo(scale, model, originalExtent) {
      this._prepareParams(scale, model, originalExtent);
    }

    ScaleRawExtentInfo.prototype._prepareParams = function (scale, model, dataExtent) {
      if (dataExtent[1] < dataExtent[0]) {
        dataExtent = [NaN, NaN];
      }

      this._dataMin = dataExtent[0];
      this._dataMax = dataExtent[1];
      var isOrdinal = this._isOrdinal = scale.type === 'ordinal';
      this._needCrossZero = model.getNeedCrossZero && model.getNeedCrossZero();
      var modelMinRaw = this._modelMinRaw = model.get('min', true);

      if (isFunction(modelMinRaw)) {
        this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({
          min: dataExtent[0],
          max: dataExtent[1]
        }));
      } else if (modelMinRaw !== 'dataMin') {
        this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw);
      }

      var modelMaxRaw = this._modelMaxRaw = model.get('max', true);

      if (isFunction(modelMaxRaw)) {
        this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({
          min: dataExtent[0],
          max: dataExtent[1]
        }));
      } else if (modelMaxRaw !== 'dataMax') {
        this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw);
      }

      if (isOrdinal) {
        this._axisDataLen = model.getCategories().length;
      } else {
        var boundaryGap = model.get('boundaryGap');
        var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0];

        if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') {
          if (true) {
            console.warn('Boolean type for boundaryGap is only ' + 'allowed for ordinal axis. Please use string in ' + 'percentage instead, e.g., "20%". Currently, ' + 'boundaryGap is set to be 0.');
          }

          this._boundaryGapInner = [0, 0];
        } else {
          this._boundaryGapInner = [parsePercent(boundaryGapArr[0], 1), parsePercent(boundaryGapArr[1], 1)];
        }
      }
    };

    ScaleRawExtentInfo.prototype.calculate = function () {
      var isOrdinal = this._isOrdinal;
      var dataMin = this._dataMin;
      var dataMax = this._dataMax;
      var axisDataLen = this._axisDataLen;
      var boundaryGapInner = this._boundaryGapInner;
      var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null;
      var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum;
      var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum;
      var minFixed = min != null;
      var maxFixed = max != null;

      if (min == null) {
        min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span;
      }

      if (max == null) {
        max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span;
      }

      (min == null || !isFinite(min)) && (min = NaN);
      (max == null || !isFinite(max)) && (max = NaN);

      if (min > max) {
        min = NaN;
        max = NaN;
      }

      var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen;

      if (this._needCrossZero) {
        if (min > 0 && max > 0 && !minFixed) {
          min = 0;
        }

        if (min < 0 && max < 0 && !maxFixed) {
          max = 0;
        }
      }

      var determinedMin = this._determinedMin;
      var determinedMax = this._determinedMax;

      if (determinedMin != null) {
        min = determinedMin;
        minFixed = true;
      }

      if (determinedMax != null) {
        max = determinedMax;
        maxFixed = true;
      }

      return {
        min: min,
        max: max,
        minFixed: minFixed,
        maxFixed: maxFixed,
        isBlank: isBlank
      };
    };

    ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) {
      if (true) {
        assert(!this.frozen);
      }

      this[DATA_MIN_MAX_ATTR[minMaxName]] = val;
    };

    ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) {
      var attr = DETERMINED_MIN_MAX_ATTR[minMaxName];

      if (true) {
        assert(!this.frozen && this[attr] == null);
      }

      this[attr] = val;
    };

    ScaleRawExtentInfo.prototype.freeze = function () {
      this.frozen = true;
    };

    return ScaleRawExtentInfo;
  }();

  var DETERMINED_MIN_MAX_ATTR = {
    min: '_determinedMin',
    max: '_determinedMax'
  };
  var DATA_MIN_MAX_ATTR = {
    min: '_dataMin',
    max: '_dataMax'
  };

  function ensureScaleRawExtentInfo(scale, model, originalExtent) {
    var rawExtentInfo = scale.rawExtentInfo;

    if (rawExtentInfo) {
      return rawExtentInfo;
    }

    rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent);
    scale.rawExtentInfo = rawExtentInfo;
    return rawExtentInfo;
  }

  function parseAxisModelMinMax(scale, minMax) {
    return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax);
  }

  function getScaleExtent(scale, model) {
    var scaleType = scale.type;
    var rawExtentResult = ensureScaleRawExtentInfo(scale, model, scale.getExtent()).calculate();
    scale.setBlank(rawExtentResult.isBlank);
    var min = rawExtentResult.min;
    var max = rawExtentResult.max;
    var ecModel = model.ecModel;

    if (ecModel && scaleType === 'time') {
      var barSeriesModels = prepareLayoutBarSeries('bar', ecModel);
      var isBaseAxisAndHasBarSeries_1 = false;
      each(barSeriesModels, function (seriesModel) {
        isBaseAxisAndHasBarSeries_1 = isBaseAxisAndHasBarSeries_1 || seriesModel.getBaseAxis() === model.axis;
      });

      if (isBaseAxisAndHasBarSeries_1) {
        var barWidthAndOffset = makeColumnLayout(barSeriesModels);
        var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset);
        min = adjustedScale.min;
        max = adjustedScale.max;
      }
    }

    return {
      extent: [min, max],
      fixMin: rawExtentResult.minFixed,
      fixMax: rawExtentResult.maxFixed
    };
  }

  function adjustScaleForOverflow(min, max, model, barWidthAndOffset) {
    var axisExtent = model.axis.getExtent();
    var axisLength = axisExtent[1] - axisExtent[0];
    var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis);

    if (barsOnCurrentAxis === undefined) {
      return {
        min: min,
        max: max
      };
    }

    var minOverflow = Infinity;
    each(barsOnCurrentAxis, function (item) {
      minOverflow = Math.min(item.offset, minOverflow);
    });
    var maxOverflow = -Infinity;
    each(barsOnCurrentAxis, function (item) {
      maxOverflow = Math.max(item.offset + item.width, maxOverflow);
    });
    minOverflow = Math.abs(minOverflow);
    maxOverflow = Math.abs(maxOverflow);
    var totalOverFlow = minOverflow + maxOverflow;
    var oldRange = max - min;
    var oldRangePercentOfNew = 1 - (minOverflow + maxOverflow) / axisLength;
    var overflowBuffer = oldRange / oldRangePercentOfNew - oldRange;
    max += overflowBuffer * (maxOverflow / totalOverFlow);
    min -= overflowBuffer * (minOverflow / totalOverFlow);
    return {
      min: min,
      max: max
    };
  }

  function niceScaleExtent(scale, model) {
    var extentInfo = getScaleExtent(scale, model);
    var extent = extentInfo.extent;
    var splitNumber = model.get('splitNumber');

    if (scale instanceof LogScale) {
      scale.base = model.get('logBase');
    }

    var scaleType = scale.type;
    scale.setExtent(extent[0], extent[1]);
    scale.niceExtent({
      splitNumber: splitNumber,
      fixMin: extentInfo.fixMin,
      fixMax: extentInfo.fixMax,
      minInterval: scaleType === 'interval' || scaleType === 'time' ? model.get('minInterval') : null,
      maxInterval: scaleType === 'interval' || scaleType === 'time' ? model.get('maxInterval') : null
    });
    var interval = model.get('interval');

    if (interval != null) {
      scale.setInterval && scale.setInterval(interval);
    }
  }

  function createScaleByModel(model, axisType) {
    axisType = axisType || model.get('type');

    if (axisType) {
      switch (axisType) {
        case 'category':
          return new OrdinalScale({
            ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(),
            extent: [Infinity, -Infinity]
          });

        case 'time':
          return new TimeScale({
            locale: model.ecModel.getLocaleModel(),
            useUTC: model.ecModel.get('useUTC')
          });

        default:
          return new (Scale.getClass(axisType) || IntervalScale)();
      }
    }
  }

  function ifAxisCrossZero(axis) {
    var dataExtent = axis.scale.getExtent();
    var min = dataExtent[0];
    var max = dataExtent[1];
    return !(min > 0 && max > 0 || min < 0 && max < 0);
  }

  function makeLabelFormatter(axis) {
    var labelFormatter = axis.getLabelModel().get('formatter');
    var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null;

    if (axis.scale.type === 'time') {
      return function (tpl) {
        return function (tick, idx) {
          return axis.scale.getFormattedLabel(tick, idx, tpl);
        };
      }(labelFormatter);
    } else if (typeof labelFormatter === 'string') {
      return function (tpl) {
        return function (tick) {
          var label = axis.scale.getLabel(tick);
          var text = tpl.replace('{value}', label != null ? label : '');
          return text;
        };
      }(labelFormatter);
    } else if (typeof labelFormatter === 'function') {
      return function (cb) {
        return function (tick, idx) {
          if (categoryTickStart != null) {
            idx = tick.value - categoryTickStart;
          }

          return cb(getAxisRawValue(axis, tick), idx, tick.level != null ? {
            level: tick.level
          } : null);
        };
      }(labelFormatter);
    } else {
      return function (tick) {
        return axis.scale.getLabel(tick);
      };
    }
  }

  function getAxisRawValue(axis, tick) {
    return axis.type === 'category' ? axis.scale.getLabel(tick) : tick.value;
  }

  function estimateLabelUnionRect(axis) {
    var axisModel = axis.model;
    var scale = axis.scale;

    if (!axisModel.get(['axisLabel', 'show']) || scale.isBlank()) {
      return;
    }

    var realNumberScaleTicks;
    var tickCount;
    var categoryScaleExtent = scale.getExtent();

    if (scale instanceof OrdinalScale) {
      tickCount = scale.count();
    } else {
      realNumberScaleTicks = scale.getTicks();
      tickCount = realNumberScaleTicks.length;
    }

    var axisLabelModel = axis.getLabelModel();
    var labelFormatter = makeLabelFormatter(axis);
    var rect;
    var step = 1;

    if (tickCount > 40) {
      step = Math.ceil(tickCount / 40);
    }

    for (var i = 0; i < tickCount; i += step) {
      var tick = realNumberScaleTicks ? realNumberScaleTicks[i] : {
        value: categoryScaleExtent[0] + i
      };
      var label = labelFormatter(tick, i);
      var unrotatedSingleRect = axisLabelModel.getTextRect(label);
      var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0);
      rect ? rect.union(singleRect) : rect = singleRect;
    }

    return rect;
  }

  function rotateTextRect(textRect, rotate) {
    var rotateRadians = rotate * Math.PI / 180;
    var beforeWidth = textRect.width;
    var beforeHeight = textRect.height;
    var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
    var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
    var rotatedRect = new BoundingRect(textRect.x, textRect.y, afterWidth, afterHeight);
    return rotatedRect;
  }

  function getOptionCategoryInterval(model) {
    var interval = model.get('interval');
    return interval == null ? 'auto' : interval;
  }

  function shouldShowAllLabels(axis) {
    return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0;
  }

  function getDataDimensionsOnAxis(data, axisDim) {
    var dataDimMap = {};
    each(data.mapDimensionsAll(axisDim), function (dataDim) {
      dataDimMap[getStackedDimension(data, dataDim)] = true;
    });
    return keys(dataDimMap);
  }

  function unionAxisExtentFromData(dataExtent, data, axisDim) {
    if (data) {
      each(getDataDimensionsOnAxis(data, axisDim), function (dim) {
        var seriesExtent = data.getApproximateExtent(dim);
        seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]);
        seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]);
      });
    }
  }

  var AxisModelCommonMixin = function () {
    function AxisModelCommonMixin() {}

    AxisModelCommonMixin.prototype.getNeedCrossZero = function () {
      var option = this.option;
      return !option.scale;
    };

    AxisModelCommonMixin.prototype.getCoordSysModel = function () {
      return;
    };

    return AxisModelCommonMixin;
  }();

  function createList(seriesModel) {
    return createListFromArray(seriesModel.getSource(), seriesModel);
  }

  var dataStack$1 = {
    isDimensionStacked: isDimensionStacked,
    enableDataStack: enableDataStack,
    getStackedDimension: getStackedDimension
  };

  function createScale(dataExtent, option) {
    var axisModel = option;

    if (!(option instanceof Model)) {
      axisModel = new Model(option);
    }

    var scale = createScaleByModel(axisModel);
    scale.setExtent(dataExtent[0], dataExtent[1]);
    niceScaleExtent(scale, axisModel);
    return scale;
  }

  function mixinAxisModelCommonMethods(Model) {
    mixin(Model, AxisModelCommonMixin);
  }

  var helper = /*#__PURE__*/Object.freeze({
    __proto__: null,
    createList: createList,
    getLayoutRect: getLayoutRect,
    dataStack: dataStack$1,
    createScale: createScale,
    mixinAxisModelCommonMethods: mixinAxisModelCommonMethods,
    getECData: getECData,
    createDimensions: createDimensions,
    createSymbol: createSymbol
  });
  var EPSILON$3 = 1e-8;

  function isAroundEqual$1(a, b) {
    return Math.abs(a - b) < EPSILON$3;
  }

  function contain$2(points, x, y) {
    var w = 0;
    var p = points[0];

    if (!p) {
      return false;
    }

    for (var i = 1; i < points.length; i++) {
      var p2 = points[i];
      w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
      p = p2;
    }

    var p0 = points[0];

    if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
      w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
    }

    return w !== 0;
  }

  var Region = function () {
    function Region(name, geometries, cp) {
      this.name = name;
      this.geometries = geometries;

      if (!cp) {
        var rect = this.getBoundingRect();
        cp = [rect.x + rect.width / 2, rect.y + rect.height / 2];
      } else {
        cp = [cp[0], cp[1]];
      }

      this.center = cp;
    }

    Region.prototype.getBoundingRect = function () {
      var rect = this._rect;

      if (rect) {
        return rect;
      }

      var MAX_NUMBER = Number.MAX_VALUE;
      var min$1 = [MAX_NUMBER, MAX_NUMBER];
      var max$1 = [-MAX_NUMBER, -MAX_NUMBER];
      var min2 = [];
      var max2 = [];
      var geometries = this.geometries;
      var i = 0;

      for (; i < geometries.length; i++) {
        if (geometries[i].type !== 'polygon') {
          continue;
        }

        var exterior = geometries[i].exterior;
        fromPoints(exterior, min2, max2);
        min(min$1, min$1, min2);
        max(max$1, max$1, max2);
      }

      if (i === 0) {
        min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
      }

      return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
    };

    Region.prototype.contain = function (coord) {
      var rect = this.getBoundingRect();
      var geometries = this.geometries;

      if (!rect.contain(coord[0], coord[1])) {
        return false;
      }

      loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
        if (geometries[i].type !== 'polygon') {
          continue;
        }

        var exterior = geometries[i].exterior;
        var interiors = geometries[i].interiors;

        if (contain$2(exterior, coord[0], coord[1])) {
          for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
            if (contain$2(interiors[k], coord[0], coord[1])) {
              continue loopGeo;
            }
          }

          return true;
        }
      }

      return false;
    };

    Region.prototype.transformTo = function (x, y, width, height) {
      var rect = this.getBoundingRect();
      var aspect = rect.width / rect.height;

      if (!width) {
        width = aspect * height;
      } else if (!height) {
        height = width / aspect;
      }

      var target = new BoundingRect(x, y, width, height);
      var transform = rect.calculateTransform(target);
      var geometries = this.geometries;

      for (var i = 0; i < geometries.length; i++) {
        if (geometries[i].type !== 'polygon') {
          continue;
        }

        var exterior = geometries[i].exterior;
        var interiors = geometries[i].interiors;

        for (var p = 0; p < exterior.length; p++) {
          applyTransform(exterior[p], exterior[p], transform);
        }

        for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
          for (var p = 0; p < interiors[h].length; p++) {
            applyTransform(interiors[h][p], interiors[h][p], transform);
          }
        }
      }

      rect = this._rect;
      rect.copy(target);
      this.center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
    };

    Region.prototype.cloneShallow = function (name) {
      name == null && (name = this.name);
      var newRegion = new Region(name, this.geometries, this.center);
      newRegion._rect = this._rect;
      newRegion.transformTo = null;
      return newRegion;
    };

    return Region;
  }();

  function decode(json) {
    if (!json.UTF8Encoding) {
      return json;
    }

    var jsonCompressed = json;
    var encodeScale = jsonCompressed.UTF8Scale;

    if (encodeScale == null) {
      encodeScale = 1024;
    }

    var features = jsonCompressed.features;

    for (var f = 0; f < features.length; f++) {
      var feature = features[f];
      var geometry = feature.geometry;

      if (geometry.type === 'Polygon') {
        var coordinates = geometry.coordinates;

        for (var c = 0; c < coordinates.length; c++) {
          coordinates[c] = decodePolygon(coordinates[c], geometry.encodeOffsets[c], encodeScale);
        }
      } else if (geometry.type === 'MultiPolygon') {
        var coordinates = geometry.coordinates;

        for (var c = 0; c < coordinates.length; c++) {
          var coordinate = coordinates[c];

          for (var c2 = 0; c2 < coordinate.length; c2++) {
            coordinate[c2] = decodePolygon(coordinate[c2], geometry.encodeOffsets[c][c2], encodeScale);
          }
        }
      }
    }

    jsonCompressed.UTF8Encoding = false;
    return jsonCompressed;
  }

  function decodePolygon(coordinate, encodeOffsets, encodeScale) {
    var result = [];
    var prevX = encodeOffsets[0];
    var prevY = encodeOffsets[1];

    for (var i = 0; i < coordinate.length; i += 2) {
      var x = coordinate.charCodeAt(i) - 64;
      var y = coordinate.charCodeAt(i + 1) - 64;
      x = x >> 1 ^ -(x & 1);
      y = y >> 1 ^ -(y & 1);
      x += prevX;
      y += prevY;
      prevX = x;
      prevY = y;
      result.push([x / encodeScale, y / encodeScale]);
    }

    return result;
  }

  function parseGeoJSON(geoJson, nameProperty) {
    geoJson = decode(geoJson);
    return map(filter(geoJson.features, function (featureObj) {
      return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0;
    }), function (featureObj) {
      var properties = featureObj.properties;
      var geo = featureObj.geometry;
      var geometries = [];

      if (geo.type === 'Polygon') {
        var coordinates = geo.coordinates;
        geometries.push({
          type: 'polygon',
          exterior: coordinates[0],
          interiors: coordinates.slice(1)
        });
      }

      if (geo.type === 'MultiPolygon') {
        var coordinates = geo.coordinates;
        each(coordinates, function (item) {
          if (item[0]) {
            geometries.push({
              type: 'polygon',
              exterior: item[0],
              interiors: item.slice(1)
            });
          }
        });
      }

      var region = new Region(properties[nameProperty || 'name'], geometries, properties.cp);
      region.properties = properties;
      return region;
    });
  }

  var inner$4 = makeInner();

  function createAxisLabels(axis) {
    return axis.type === 'category' ? makeCategoryLabels(axis) : makeRealNumberLabels(axis);
  }

  function createAxisTicks(axis, tickModel) {
    return axis.type === 'category' ? makeCategoryTicks(axis, tickModel) : {
      ticks: map(axis.scale.getTicks(), function (tick) {
        return tick.value;
      })
    };
  }

  function makeCategoryLabels(axis) {
    var labelModel = axis.getLabelModel();
    var result = makeCategoryLabelsActually(axis, labelModel);
    return !labelModel.get('show') || axis.scale.isBlank() ? {
      labels: [],
      labelCategoryInterval: result.labelCategoryInterval
    } : result;
  }

  function makeCategoryLabelsActually(axis, labelModel) {
    var labelsCache = getListCache(axis, 'labels');
    var optionLabelInterval = getOptionCategoryInterval(labelModel);
    var result = listCacheGet(labelsCache, optionLabelInterval);

    if (result) {
      return result;
    }

    var labels;
    var numericLabelInterval;

    if (isFunction(optionLabelInterval)) {
      labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval);
    } else {
      numericLabelInterval = optionLabelInterval === 'auto' ? makeAutoCategoryInterval(axis) : optionLabelInterval;
      labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval);
    }

    return listCacheSet(labelsCache, optionLabelInterval, {
      labels: labels,
      labelCategoryInterval: numericLabelInterval
    });
  }

  function makeCategoryTicks(axis, tickModel) {
    var ticksCache = getListCache(axis, 'ticks');
    var optionTickInterval = getOptionCategoryInterval(tickModel);
    var result = listCacheGet(ticksCache, optionTickInterval);

    if (result) {
      return result;
    }

    var ticks;
    var tickCategoryInterval;

    if (!tickModel.get('show') || axis.scale.isBlank()) {
      ticks = [];
    }

    if (isFunction(optionTickInterval)) {
      ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true);
    } else if (optionTickInterval === 'auto') {
      var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel());
      tickCategoryInterval = labelsResult.labelCategoryInterval;
      ticks = map(labelsResult.labels, function (labelItem) {
        return labelItem.tickValue;
      });
    } else {
      tickCategoryInterval = optionTickInterval;
      ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true);
    }

    return listCacheSet(ticksCache, optionTickInterval, {
      ticks: ticks,
      tickCategoryInterval: tickCategoryInterval
    });
  }

  function makeRealNumberLabels(axis) {
    var ticks = axis.scale.getTicks();
    var labelFormatter = makeLabelFormatter(axis);
    return {
      labels: map(ticks, function (tick, idx) {
        return {
          formattedLabel: labelFormatter(tick, idx),
          rawLabel: axis.scale.getLabel(tick),
          tickValue: tick.value
        };
      })
    };
  }

  function getListCache(axis, prop) {
    return inner$4(axis)[prop] || (inner$4(axis)[prop] = []);
  }

  function listCacheGet(cache, key) {
    for (var i = 0; i < cache.length; i++) {
      if (cache[i].key === key) {
        return cache[i].value;
      }
    }
  }

  function listCacheSet(cache, key, value) {
    cache.push({
      key: key,
      value: value
    });
    return value;
  }

  function makeAutoCategoryInterval(axis) {
    var result = inner$4(axis).autoInterval;
    return result != null ? result : inner$4(axis).autoInterval = axis.calculateCategoryInterval();
  }

  function calculateCategoryInterval(axis) {
    var params = fetchAutoCategoryIntervalCalculationParams(axis);
    var labelFormatter = makeLabelFormatter(axis);
    var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI;
    var ordinalScale = axis.scale;
    var ordinalExtent = ordinalScale.getExtent();
    var tickCount = ordinalScale.count();

    if (ordinalExtent[1] - ordinalExtent[0] < 1) {
      return 0;
    }

    var step = 1;

    if (tickCount > 40) {
      step = Math.max(1, Math.floor(tickCount / 40));
    }

    var tickValue = ordinalExtent[0];
    var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
    var unitW = Math.abs(unitSpan * Math.cos(rotation));
    var unitH = Math.abs(unitSpan * Math.sin(rotation));
    var maxW = 0;
    var maxH = 0;

    for (; tickValue <= ordinalExtent[1]; tickValue += step) {
      var width = 0;
      var height = 0;
      var rect = getBoundingRect(labelFormatter({
        value: tickValue
      }), params.font, 'center', 'top');
      width = rect.width * 1.3;
      height = rect.height * 1.3;
      maxW = Math.max(maxW, width, 7);
      maxH = Math.max(maxH, height, 7);
    }

    var dw = maxW / unitW;
    var dh = maxH / unitH;
    isNaN(dw) && (dw = Infinity);
    isNaN(dh) && (dh = Infinity);
    var interval = Math.max(0, Math.floor(Math.min(dw, dh)));
    var cache = inner$4(axis.model);
    var axisExtent = axis.getExtent();
    var lastAutoInterval = cache.lastAutoInterval;
    var lastTickCount = cache.lastTickCount;

    if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 && lastAutoInterval > interval && cache.axisExtent0 === axisExtent[0] && cache.axisExtent1 === axisExtent[1]) {
      interval = lastAutoInterval;
    } else {
      cache.lastTickCount = tickCount;
      cache.lastAutoInterval = interval;
      cache.axisExtent0 = axisExtent[0];
      cache.axisExtent1 = axisExtent[1];
    }

    return interval;
  }

  function fetchAutoCategoryIntervalCalculationParams(axis) {
    var labelModel = axis.getLabelModel();
    return {
      axisRotate: axis.getRotate ? axis.getRotate() : axis.isHorizontal && !axis.isHorizontal() ? 90 : 0,
      labelRotate: labelModel.get('rotate') || 0,
      font: labelModel.getFont()
    };
  }

  function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) {
    var labelFormatter = makeLabelFormatter(axis);
    var ordinalScale = axis.scale;
    var ordinalExtent = ordinalScale.getExtent();
    var labelModel = axis.getLabelModel();
    var result = [];
    var step = Math.max((categoryInterval || 0) + 1, 1);
    var startTick = ordinalExtent[0];
    var tickCount = ordinalScale.count();

    if (startTick !== 0 && step > 1 && tickCount / step > 2) {
      startTick = Math.round(Math.ceil(startTick / step) * step);
    }

    var showAllLabel = shouldShowAllLabels(axis);
    var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel;
    var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel;

    if (includeMinLabel && startTick !== ordinalExtent[0]) {
      addItem(ordinalExtent[0]);
    }

    var tickValue = startTick;

    for (; tickValue <= ordinalExtent[1]; tickValue += step) {
      addItem(tickValue);
    }

    if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) {
      addItem(ordinalExtent[1]);
    }

    function addItem(tickValue) {
      var tickObj = {
        value: tickValue
      };
      result.push(onlyTick ? tickValue : {
        formattedLabel: labelFormatter(tickObj),
        rawLabel: ordinalScale.getLabel(tickObj),
        tickValue: tickValue
      });
    }

    return result;
  }

  function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) {
    var ordinalScale = axis.scale;
    var labelFormatter = makeLabelFormatter(axis);
    var result = [];
    each(ordinalScale.getTicks(), function (tick) {
      var rawLabel = ordinalScale.getLabel(tick);
      var tickValue = tick.value;

      if (categoryInterval(tick.value, rawLabel)) {
        result.push(onlyTick ? tickValue : {
          formattedLabel: labelFormatter(tick),
          rawLabel: rawLabel,
          tickValue: tickValue
        });
      }
    });
    return result;
  }

  var NORMALIZED_EXTENT = [0, 1];

  var Axis = function () {
    function Axis(dim, scale, extent) {
      this.onBand = false;
      this.inverse = false;
      this.dim = dim;
      this.scale = scale;
      this._extent = extent || [0, 0];
    }

    Axis.prototype.contain = function (coord) {
      var extent = this._extent;
      var min = Math.min(extent[0], extent[1]);
      var max = Math.max(extent[0], extent[1]);
      return coord >= min && coord <= max;
    };

    Axis.prototype.containData = function (data) {
      return this.scale.contain(data);
    };

    Axis.prototype.getExtent = function () {
      return this._extent.slice();
    };

    Axis.prototype.getPixelPrecision = function (dataExtent) {
      return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent);
    };

    Axis.prototype.setExtent = function (start, end) {
      var extent = this._extent;
      extent[0] = start;
      extent[1] = end;
    };

    Axis.prototype.dataToCoord = function (data, clamp) {
      var extent = this._extent;
      var scale = this.scale;
      data = scale.normalize(data);

      if (this.onBand && scale.type === 'ordinal') {
        extent = extent.slice();
        fixExtentWithBands(extent, scale.count());
      }

      return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
    };

    Axis.prototype.coordToData = function (coord, clamp) {
      var extent = this._extent;
      var scale = this.scale;

      if (this.onBand && scale.type === 'ordinal') {
        extent = extent.slice();
        fixExtentWithBands(extent, scale.count());
      }

      var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);
      return this.scale.scale(t);
    };

    Axis.prototype.pointToData = function (point, clamp) {
      return;
    };

    Axis.prototype.getTicksCoords = function (opt) {
      opt = opt || {};
      var tickModel = opt.tickModel || this.getTickModel();
      var result = createAxisTicks(this, tickModel);
      var ticks = result.ticks;
      var ticksCoords = map(ticks, function (tickVal) {
        return {
          coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawIndex(tickVal) : tickVal),
          tickValue: tickVal
        };
      }, this);
      var alignWithLabel = tickModel.get('alignWithLabel');
      fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp);
      return ticksCoords;
    };

    Axis.prototype.getMinorTicksCoords = function () {
      if (this.scale.type === 'ordinal') {
        return [];
      }

      var minorTickModel = this.model.getModel('minorTick');
      var splitNumber = minorTickModel.get('splitNumber');

      if (!(splitNumber > 0 && splitNumber < 100)) {
        splitNumber = 5;
      }

      var minorTicks = this.scale.getMinorTicks(splitNumber);
      var minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
        return map(minorTicksGroup, function (minorTick) {
          return {
            coord: this.dataToCoord(minorTick),
            tickValue: minorTick
          };
        }, this);
      }, this);
      return minorTicksCoords;
    };

    Axis.prototype.getViewLabels = function () {
      return createAxisLabels(this).labels;
    };

    Axis.prototype.getLabelModel = function () {
      return this.model.getModel('axisLabel');
    };

    Axis.prototype.getTickModel = function () {
      return this.model.getModel('axisTick');
    };

    Axis.prototype.getBandWidth = function () {
      var axisExtent = this._extent;
      var dataExtent = this.scale.getExtent();
      var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0);
      len === 0 && (len = 1);
      var size = Math.abs(axisExtent[1] - axisExtent[0]);
      return Math.abs(size) / len;
    };

    Axis.prototype.calculateCategoryInterval = function () {
      return calculateCategoryInterval(this);
    };

    return Axis;
  }();

  function fixExtentWithBands(extent, nTick) {
    var size = extent[1] - extent[0];
    var len = nTick;
    var margin = size / len / 2;
    extent[0] += margin;
    extent[1] -= margin;
  }

  function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) {
    var ticksLen = ticksCoords.length;

    if (!axis.onBand || alignWithLabel || !ticksLen) {
      return;
    }

    var axisExtent = axis.getExtent();
    var last;
    var diffSize;

    if (ticksLen === 1) {
      ticksCoords[0].coord = axisExtent[0];
      last = ticksCoords[1] = {
        coord: axisExtent[0]
      };
    } else {
      var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
      var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;
      each(ticksCoords, function (ticksItem) {
        ticksItem.coord -= shift_1 / 2;
      });
      var dataExtent = axis.scale.getExtent();
      diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;
      last = {
        coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize
      };
      ticksCoords.push(last);
    }

    var inverse = axisExtent[0] > axisExtent[1];

    if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
      clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift();
    }

    if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) {
      ticksCoords.unshift({
        coord: axisExtent[0]
      });
    }

    if (littleThan(axisExtent[1], last.coord)) {
      clamp ? last.coord = axisExtent[1] : ticksCoords.pop();
    }

    if (clamp && littleThan(last.coord, axisExtent[1])) {
      ticksCoords.push({
        coord: axisExtent[1]
      });
    }

    function littleThan(a, b) {
      a = round$1(a);
      b = round$1(b);
      return inverse ? a > b : a < b;
    }
  }

  var parseGeoJson = parseGeoJSON;
  var number = {};
  each(['linearMap', 'round', 'asc', 'getPrecision', 'getPrecisionSafe', 'getPixelPrecision', 'getPercentWithPrecision', 'MAX_SAFE_INTEGER', 'remRadian', 'isRadianAroundZero', 'parseDate', 'quantity', 'quantityExponent', 'nice', 'quantile', 'reformIntervals', 'isNumeric', 'numericToNumber'], function (name) {
    number[name] = numberUtil[name];
  });
  var format$1 = {};
  each(['addCommas', 'toCamelCase', 'normalizeCssArray', 'encodeHTML', 'formatTpl', 'getTooltipMarker', 'formatTime', 'capitalFirst', 'truncateText', 'getTextRect'], function (name) {
    format$1[name] = formatUtil[name];
  });
  var time = {
    parse: parseDate,
    format: format
  };
  var ecUtil = {};
  each(['map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter', 'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction', 'extend', 'defaults', 'clone', 'merge'], function (name) {
    ecUtil[name] = zrUtil[name];
  });
  var GRAPHIC_KEYS = ['extendShape', 'extendPath', 'makePath', 'makeImage', 'mergePath', 'resizePath', 'createIcon', 'updateProps', 'initProps', 'getTransform', 'clipPointsByRect', 'clipRectByRect', 'registerShape', 'getShapeClass', 'Group', 'Image', 'Text', 'Circle', 'Ellipse', 'Sector', 'Ring', 'Polygon', 'Polyline', 'Rect', 'Line', 'BezierCurve', 'Arc', 'IncrementalDisplayable', 'CompoundPath', 'LinearGradient', 'RadialGradient', 'BoundingRect'];
  var graphic$1 = {};
  each(GRAPHIC_KEYS, function (name) {
    graphic$1[name] = graphic[name];
  });
  var RELATIONAL_EXPRESSION_OP_ALIAS_MAP = {
    value: 'eq',
    '<': 'lt',
    '<=': 'lte',
    '>': 'gt',
    '>=': 'gte',
    '=': 'eq',
    '!=': 'ne',
    '<>': 'ne'
  };

  var RegExpEvaluator = function () {
    function RegExpEvaluator(rVal) {
      var condValue = this._condVal = isString(rVal) ? new RegExp(rVal) : isRegExp(rVal) ? rVal : null;

      if (condValue == null) {
        var errMsg = '';

        if (true) {
          errMsg = makePrintable('Illegal regexp', rVal, 'in');
        }

        throwError(errMsg);
      }
    }

    RegExpEvaluator.prototype.evaluate = function (lVal) {
      var type = typeof lVal;
      return type === 'string' ? this._condVal.test(lVal) : type === 'number' ? this._condVal.test(lVal + '') : false;
    };

    return RegExpEvaluator;
  }();

  var ConstConditionInternal = function () {
    function ConstConditionInternal() {}

    ConstConditionInternal.prototype.evaluate = function () {
      return this.value;
    };

    return ConstConditionInternal;
  }();

  var AndConditionInternal = function () {
    function AndConditionInternal() {}

    AndConditionInternal.prototype.evaluate = function () {
      var children = this.children;

      for (var i = 0; i < children.length; i++) {
        if (!children[i].evaluate()) {
          return false;
        }
      }

      return true;
    };

    return AndConditionInternal;
  }();

  var OrConditionInternal = function () {
    function OrConditionInternal() {}

    OrConditionInternal.prototype.evaluate = function () {
      var children = this.children;

      for (var i = 0; i < children.length; i++) {
        if (children[i].evaluate()) {
          return true;
        }
      }

      return false;
    };

    return OrConditionInternal;
  }();

  var NotConditionInternal = function () {
    function NotConditionInternal() {}

    NotConditionInternal.prototype.evaluate = function () {
      return !this.child.evaluate();
    };

    return NotConditionInternal;
  }();

  var RelationalConditionInternal = function () {
    function RelationalConditionInternal() {}

    RelationalConditionInternal.prototype.evaluate = function () {
      var needParse = !!this.valueParser;
      var getValue = this.getValue;
      var tarValRaw = getValue(this.valueGetterParam);
      var tarValParsed = needParse ? this.valueParser(tarValRaw) : null;

      for (var i = 0; i < this.subCondList.length; i++) {
        if (!this.subCondList[i].evaluate(needParse ? tarValParsed : tarValRaw)) {
          return false;
        }
      }

      return true;
    };

    return RelationalConditionInternal;
  }();

  function parseOption(exprOption, getters) {
    if (exprOption === true || exprOption === false) {
      var cond = new ConstConditionInternal();
      cond.value = exprOption;
      return cond;
    }

    var errMsg = '';

    if (!isObjectNotArray(exprOption)) {
      if (true) {
        errMsg = makePrintable('Illegal config. Expect a plain object but actually', exprOption);
      }

      throwError(errMsg);
    }

    if (exprOption.and) {
      return parseAndOrOption('and', exprOption, getters);
    } else if (exprOption.or) {
      return parseAndOrOption('or', exprOption, getters);
    } else if (exprOption.not) {
      return parseNotOption(exprOption, getters);
    }

    return parseRelationalOption(exprOption, getters);
  }

  function parseAndOrOption(op, exprOption, getters) {
    var subOptionArr = exprOption[op];
    var errMsg = '';

    if (true) {
      errMsg = makePrintable('"and"/"or" condition should only be `' + op + ': [...]` and must not be empty array.', 'Illegal condition:', exprOption);
    }

    if (!isArray(subOptionArr)) {
      throwError(errMsg);
    }

    if (!subOptionArr.length) {
      throwError(errMsg);
    }

    var cond = op === 'and' ? new AndConditionInternal() : new OrConditionInternal();
    cond.children = map(subOptionArr, function (subOption) {
      return parseOption(subOption, getters);
    });

    if (!cond.children.length) {
      throwError(errMsg);
    }

    return cond;
  }

  function parseNotOption(exprOption, getters) {
    var subOption = exprOption.not;
    var errMsg = '';

    if (true) {
      errMsg = makePrintable('"not" condition should only be `not: {}`.', 'Illegal condition:', exprOption);
    }

    if (!isObjectNotArray(subOption)) {
      throwError(errMsg);
    }

    var cond = new NotConditionInternal();
    cond.child = parseOption(subOption, getters);

    if (!cond.child) {
      throwError(errMsg);
    }

    return cond;
  }

  function parseRelationalOption(exprOption, getters) {
    var errMsg = '';
    var valueGetterParam = getters.prepareGetValue(exprOption);
    var subCondList = [];
    var exprKeys = keys(exprOption);
    var parserName = exprOption.parser;
    var valueParser = parserName ? getRawValueParser(parserName) : null;

    for (var i = 0; i < exprKeys.length; i++) {
      var keyRaw = exprKeys[i];

      if (keyRaw === 'parser' || getters.valueGetterAttrMap.get(keyRaw)) {
        continue;
      }

      var op = hasOwn(RELATIONAL_EXPRESSION_OP_ALIAS_MAP, keyRaw) ? RELATIONAL_EXPRESSION_OP_ALIAS_MAP[keyRaw] : keyRaw;
      var condValueRaw = exprOption[keyRaw];
      var condValueParsed = valueParser ? valueParser(condValueRaw) : condValueRaw;
      var evaluator = createFilterComparator(op, condValueParsed) || op === 'reg' && new RegExpEvaluator(condValueParsed);

      if (!evaluator) {
        if (true) {
          errMsg = makePrintable('Illegal relational operation: "' + keyRaw + '" in condition:', exprOption);
        }

        throwError(errMsg);
      }

      subCondList.push(evaluator);
    }

    if (!subCondList.length) {
      if (true) {
        errMsg = makePrintable('Relational condition must have at least one operator.', 'Illegal condition:', exprOption);
      }

      throwError(errMsg);
    }

    var cond = new RelationalConditionInternal();
    cond.valueGetterParam = valueGetterParam;
    cond.valueParser = valueParser;
    cond.getValue = getters.getValue;
    cond.subCondList = subCondList;
    return cond;
  }

  function isObjectNotArray(val) {
    return isObject(val) && !isArrayLike(val);
  }

  var ConditionalExpressionParsed = function () {
    function ConditionalExpressionParsed(exprOption, getters) {
      this._cond = parseOption(exprOption, getters);
    }

    ConditionalExpressionParsed.prototype.evaluate = function () {
      return this._cond.evaluate();
    };

    return ConditionalExpressionParsed;
  }();

  function parseConditionalExpression(exprOption, getters) {
    return new ConditionalExpressionParsed(exprOption, getters);
  }

  var filterTransform = {
    type: 'echarts:filter',
    transform: function (params) {
      var upstream = params.upstream;
      var rawItem;
      var condition = parseConditionalExpression(params.config, {
        valueGetterAttrMap: createHashMap({
          dimension: true
        }),
        prepareGetValue: function (exprOption) {
          var errMsg = '';
          var dimLoose = exprOption.dimension;

          if (!hasOwn(exprOption, 'dimension')) {
            if (true) {
              errMsg = makePrintable('Relation condition must has prop "dimension" specified.', 'Illegal condition:', exprOption);
            }

            throwError(errMsg);
          }

          var dimInfo = upstream.getDimensionInfo(dimLoose);

          if (!dimInfo) {
            if (true) {
              errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal condition:', exprOption, '.\n');
            }

            throwError(errMsg);
          }

          return {
            dimIdx: dimInfo.index
          };
        },
        getValue: function (param) {
          return upstream.retrieveValueFromItem(rawItem, param.dimIdx);
        }
      });
      var resultData = [];

      for (var i = 0, len = upstream.count(); i < len; i++) {
        rawItem = upstream.getRawDataItem(i);

        if (condition.evaluate()) {
          resultData.push(rawItem);
        }
      }

      return {
        data: resultData
      };
    }
  };
  var sampleLog = '';

  if (true) {
    sampleLog = ['Valid config is like:', '{ dimension: "age", order: "asc" }', 'or [{ dimension: "age", order: "asc"], { dimension: "date", order: "desc" }]'].join(' ');
  }

  var sortTransform = {
    type: 'echarts:sort',
    transform: function (params) {
      var upstream = params.upstream;
      var config = params.config;
      var errMsg = '';
      var orderExprList = normalizeToArray(config);

      if (!orderExprList.length) {
        if (true) {
          errMsg = 'Empty `config` in sort transform.';
        }

        throwError(errMsg);
      }

      var orderDefList = [];
      each(orderExprList, function (orderExpr) {
        var dimLoose = orderExpr.dimension;
        var order = orderExpr.order;
        var parserName = orderExpr.parser;
        var incomparable = orderExpr.incomparable;

        if (dimLoose == null) {
          if (true) {
            errMsg = 'Sort transform config must has "dimension" specified.' + sampleLog;
          }

          throwError(errMsg);
        }

        if (order !== 'asc' && order !== 'desc') {
          if (true) {
            errMsg = 'Sort transform config must has "order" specified.' + sampleLog;
          }

          throwError(errMsg);
        }

        if (incomparable && incomparable !== 'min' && incomparable !== 'max') {
          var errMsg_1 = '';

          if (true) {
            errMsg_1 = 'incomparable must be "min" or "max" rather than "' + incomparable + '".';
          }

          throwError(errMsg_1);
        }

        if (order !== 'asc' && order !== 'desc') {
          var errMsg_2 = '';

          if (true) {
            errMsg_2 = 'order must be "asc" or "desc" rather than "' + order + '".';
          }

          throwError(errMsg_2);
        }

        var dimInfo = upstream.getDimensionInfo(dimLoose);

        if (!dimInfo) {
          if (true) {
            errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal config:', orderExpr, '.\n');
          }

          throwError(errMsg);
        }

        var parser = parserName ? getRawValueParser(parserName) : null;

        if (parserName && !parser) {
          if (true) {
            errMsg = makePrintable('Invalid parser name ' + parserName + '.\n', 'Illegal config:', orderExpr, '.\n');
          }

          throwError(errMsg);
        }

        orderDefList.push({
          dimIdx: dimInfo.index,
          parser: parser,
          comparator: new SortOrderComparator(order, incomparable)
        });
      });
      var sourceFormat = upstream.sourceFormat;

      if (sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS) {
        if (true) {
          errMsg = 'sourceFormat "' + sourceFormat + '" is not supported yet';
        }

        throwError(errMsg);
      }

      var resultData = [];

      for (var i = 0, len = upstream.count(); i < len; i++) {
        resultData.push(upstream.getRawDataItem(i));
      }

      resultData.sort(function (item0, item1) {
        for (var i = 0; i < orderDefList.length; i++) {
          var orderDef = orderDefList[i];
          var val0 = upstream.retrieveValueFromItem(item0, orderDef.dimIdx);
          var val1 = upstream.retrieveValueFromItem(item1, orderDef.dimIdx);

          if (orderDef.parser) {
            val0 = orderDef.parser(val0);
            val1 = orderDef.parser(val1);
          }

          var result = orderDef.comparator.evaluate(val0, val1);

          if (result !== 0) {
            return result;
          }
        }

        return 0;
      });
      return {
        data: resultData
      };
    }
  };
  registerTransform(filterTransform);
  registerTransform(sortTransform);

  var LineSeriesModel = function (_super) {
    __extends(LineSeriesModel, _super);

    function LineSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = LineSeriesModel.type;
      _this.hasSymbolVisual = true;
      _this.legendSymbol = 'line';
      return _this;
    }

    LineSeriesModel.prototype.getInitialData = function (option) {
      if (true) {
        var coordSys = option.coordinateSystem;

        if (coordSys !== 'polar' && coordSys !== 'cartesian2d') {
          throw new Error('Line not support coordinateSystem besides cartesian and polar');
        }
      }

      return createListFromArray(this.getSource(), this, {
        useEncodeDefaulter: true
      });
    };

    LineSeriesModel.type = 'series.line';
    LineSeriesModel.dependencies = ['grid', 'polar'];
    LineSeriesModel.defaultOption = {
      zlevel: 0,
      z: 3,
      coordinateSystem: 'cartesian2d',
      legendHoverLink: true,
      clip: true,
      label: {
        position: 'top'
      },
      endLabel: {
        show: false,
        valueAnimation: true,
        distance: 8
      },
      lineStyle: {
        width: 2,
        type: 'solid'
      },
      emphasis: {
        scale: true,
        lineStyle: {
          width: 'bolder'
        }
      },
      step: false,
      smooth: false,
      smoothMonotone: null,
      symbol: 'emptyCircle',
      symbolSize: 4,
      symbolRotate: null,
      showSymbol: true,
      showAllSymbol: 'auto',
      connectNulls: false,
      sampling: 'none',
      animationEasing: 'linear',
      progressive: 0,
      hoverLayerThreshold: Infinity
    };
    return LineSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(LineSeriesModel);

  function getDefaultLabel(data, dataIndex) {
    var labelDims = data.mapDimensionsAll('defaultedLabel');
    var len = labelDims.length;

    if (len === 1) {
      return retrieveRawValue(data, dataIndex, labelDims[0]);
    } else if (len) {
      var vals = [];

      for (var i = 0; i < labelDims.length; i++) {
        vals.push(retrieveRawValue(data, dataIndex, labelDims[i]));
      }

      return vals.join(' ');
    }
  }

  function getDefaultInterpolatedLabel(data, interpolatedValue) {
    var labelDims = data.mapDimensionsAll('defaultedLabel');

    if (!isArray(interpolatedValue)) {
      return interpolatedValue + '';
    }

    var vals = [];

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

      if (dimInfo) {
        vals.push(interpolatedValue[dimInfo.index]);
      }
    }

    return vals.join(' ');
  }

  var Symbol = function (_super) {
    __extends(Symbol, _super);

    function Symbol(data, idx, seriesScope, opts) {
      var _this = _super.call(this) || this;

      _this.updateData(data, idx, seriesScope, opts);

      return _this;
    }

    Symbol.prototype._createSymbol = function (symbolType, data, idx, symbolSize, keepAspect) {
      this.removeAll();
      var symbolPath = createSymbol(symbolType, -1, -1, 2, 2, null, keepAspect);
      symbolPath.attr({
        z2: 100,
        culling: true,
        scaleX: symbolSize[0] / 2,
        scaleY: symbolSize[1] / 2
      });
      symbolPath.drift = driftSymbol;
      this._symbolType = symbolType;
      this.add(symbolPath);
    };

    Symbol.prototype.stopSymbolAnimation = function (toLastFrame) {
      this.childAt(0).stopAnimation(null, toLastFrame);
    };

    Symbol.prototype.getSymbolPath = function () {
      return this.childAt(0);
    };

    Symbol.prototype.highlight = function () {
      enterEmphasis(this.childAt(0));
    };

    Symbol.prototype.downplay = function () {
      leaveEmphasis(this.childAt(0));
    };

    Symbol.prototype.setZ = function (zlevel, z) {
      var symbolPath = this.childAt(0);
      symbolPath.zlevel = zlevel;
      symbolPath.z = z;
    };

    Symbol.prototype.setDraggable = function (draggable) {
      var symbolPath = this.childAt(0);
      symbolPath.draggable = draggable;
      symbolPath.cursor = draggable ? 'move' : symbolPath.cursor;
    };

    Symbol.prototype.updateData = function (data, idx, seriesScope, opts) {
      this.silent = false;
      var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
      var seriesModel = data.hostModel;
      var symbolSize = Symbol.getSymbolSize(data, idx);
      var isInit = symbolType !== this._symbolType;
      var disableAnimation = opts && opts.disableAnimation;

      if (isInit) {
        var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect');

        this._createSymbol(symbolType, data, idx, symbolSize, keepAspect);
      } else {
        var symbolPath = this.childAt(0);
        symbolPath.silent = false;
        var target = {
          scaleX: symbolSize[0] / 2,
          scaleY: symbolSize[1] / 2
        };
        disableAnimation ? symbolPath.attr(target) : updateProps(symbolPath, target, seriesModel, idx);
      }

      this._updateCommon(data, idx, symbolSize, seriesScope, opts);

      if (isInit) {
        var symbolPath = this.childAt(0);

        if (!disableAnimation) {
          var target = {
            scaleX: this._sizeX,
            scaleY: this._sizeY,
            style: {
              opacity: symbolPath.style.opacity
            }
          };
          symbolPath.scaleX = symbolPath.scaleY = 0;
          symbolPath.style.opacity = 0;
          initProps(symbolPath, target, seriesModel, idx);
        }
      }

      if (disableAnimation) {
        this.childAt(0).stopAnimation('remove');
      }

      this._seriesModel = seriesModel;
    };

    Symbol.prototype._updateCommon = function (data, idx, symbolSize, seriesScope, opts) {
      var symbolPath = this.childAt(0);
      var seriesModel = data.hostModel;
      var emphasisItemStyle;
      var blurItemStyle;
      var selectItemStyle;
      var focus;
      var blurScope;
      var symbolOffset;
      var labelStatesModels;
      var hoverScale;
      var cursorStyle;

      if (seriesScope) {
        emphasisItemStyle = seriesScope.emphasisItemStyle;
        blurItemStyle = seriesScope.blurItemStyle;
        selectItemStyle = seriesScope.selectItemStyle;
        focus = seriesScope.focus;
        blurScope = seriesScope.blurScope;
        symbolOffset = seriesScope.symbolOffset;
        labelStatesModels = seriesScope.labelStatesModels;
        hoverScale = seriesScope.hoverScale;
        cursorStyle = seriesScope.cursorStyle;
      }

      if (!seriesScope || data.hasItemOption) {
        var itemModel = seriesScope && seriesScope.itemModel ? seriesScope.itemModel : data.getItemModel(idx);
        var emphasisModel = itemModel.getModel('emphasis');
        emphasisItemStyle = emphasisModel.getModel('itemStyle').getItemStyle();
        selectItemStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle();
        blurItemStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
        focus = emphasisModel.get('focus');
        blurScope = emphasisModel.get('blurScope');
        symbolOffset = itemModel.getShallow('symbolOffset');
        labelStatesModels = getLabelStatesModels(itemModel);
        hoverScale = emphasisModel.getShallow('scale');
        cursorStyle = itemModel.getShallow('cursor');
      }

      var symbolRotate = data.getItemVisual(idx, 'symbolRotate');
      symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);

      if (symbolOffset) {
        symbolPath.x = parsePercent$2(symbolOffset[0], symbolSize[0]);
        symbolPath.y = parsePercent$2(symbolOffset[1], symbolSize[1]);
      }

      cursorStyle && symbolPath.attr('cursor', cursorStyle);
      var symbolStyle = data.getItemVisual(idx, 'style');
      var visualColor = symbolStyle.fill;

      if (symbolPath instanceof ZRImage) {
        var pathStyle = symbolPath.style;
        symbolPath.useStyle(extend({
          image: pathStyle.image,
          x: pathStyle.x,
          y: pathStyle.y,
          width: pathStyle.width,
          height: pathStyle.height
        }, symbolStyle));
      } else {
        if (symbolPath.__isEmptyBrush) {
          symbolPath.useStyle(extend({}, symbolStyle));
        } else {
          symbolPath.useStyle(symbolStyle);
        }

        symbolPath.style.decal = null;
        symbolPath.setColor(visualColor, opts && opts.symbolInnerColor);
        symbolPath.style.strokeNoScale = true;
      }

      var liftZ = data.getItemVisual(idx, 'liftZ');
      var z2Origin = this._z2;

      if (liftZ != null) {
        if (z2Origin == null) {
          this._z2 = symbolPath.z2;
          symbolPath.z2 += liftZ;
        }
      } else if (z2Origin != null) {
        symbolPath.z2 = z2Origin;
        this._z2 = null;
      }

      var useNameLabel = opts && opts.useNameLabel;
      setLabelStyle(symbolPath, labelStatesModels, {
        labelFetcher: seriesModel,
        labelDataIndex: idx,
        defaultText: getLabelDefaultText,
        inheritColor: visualColor,
        defaultOpacity: symbolStyle.opacity
      });

      function getLabelDefaultText(idx) {
        return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx);
      }

      this._sizeX = symbolSize[0] / 2;
      this._sizeY = symbolSize[1] / 2;
      var emphasisState = symbolPath.ensureState('emphasis');
      emphasisState.style = emphasisItemStyle;
      symbolPath.ensureState('select').style = selectItemStyle;
      symbolPath.ensureState('blur').style = blurItemStyle;

      if (hoverScale) {
        var scaleRatio = Math.max(1.1, 3 / this._sizeY);
        emphasisState.scaleX = this._sizeX * scaleRatio;
        emphasisState.scaleY = this._sizeY * scaleRatio;
      }

      this.setSymbolScale(1);
      enableHoverEmphasis(this, focus, blurScope);
    };

    Symbol.prototype.setSymbolScale = function (scale) {
      this.scaleX = this.scaleY = scale;
    };

    Symbol.prototype.fadeOut = function (cb, opt) {
      var symbolPath = this.childAt(0);
      var seriesModel = this._seriesModel;
      var dataIndex = getECData(this).dataIndex;
      var animationOpt = opt && opt.animation;
      this.silent = symbolPath.silent = true;

      if (opt && opt.fadeLabel) {
        var textContent = symbolPath.getTextContent();

        if (textContent) {
          removeElement(textContent, {
            style: {
              opacity: 0
            }
          }, seriesModel, {
            dataIndex: dataIndex,
            removeOpt: animationOpt,
            cb: function () {
              symbolPath.removeTextContent();
            }
          });
        }
      } else {
        symbolPath.removeTextContent();
      }

      removeElement(symbolPath, {
        style: {
          opacity: 0
        },
        scaleX: 0,
        scaleY: 0
      }, seriesModel, {
        dataIndex: dataIndex,
        cb: cb,
        removeOpt: animationOpt
      });
    };

    Symbol.getSymbolSize = function (data, idx) {
      var symbolSize = data.getItemVisual(idx, 'symbolSize');
      return symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize];
    };

    return Symbol;
  }(Group);

  function driftSymbol(dx, dy) {
    this.parent.drift(dx, dy);
  }

  function symbolNeedsDraw(data, point, idx, opt) {
    return point && !isNaN(point[0]) && !isNaN(point[1]) && !(opt.isIgnore && opt.isIgnore(idx)) && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1])) && data.getItemVisual(idx, 'symbol') !== 'none';
  }

  function normalizeUpdateOpt(opt) {
    if (opt != null && !isObject(opt)) {
      opt = {
        isIgnore: opt
      };
    }

    return opt || {};
  }

  function makeSeriesScope(data) {
    var seriesModel = data.hostModel;
    var emphasisModel = seriesModel.getModel('emphasis');
    return {
      emphasisItemStyle: emphasisModel.getModel('itemStyle').getItemStyle(),
      blurItemStyle: seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(),
      selectItemStyle: seriesModel.getModel(['select', 'itemStyle']).getItemStyle(),
      focus: emphasisModel.get('focus'),
      blurScope: emphasisModel.get('blurScope'),
      symbolRotate: seriesModel.get('symbolRotate'),
      symbolOffset: seriesModel.get('symbolOffset'),
      hoverScale: emphasisModel.get('scale'),
      labelStatesModels: getLabelStatesModels(seriesModel),
      cursorStyle: seriesModel.get('cursor')
    };
  }

  var SymbolDraw = function () {
    function SymbolDraw(SymbolCtor) {
      this.group = new Group();
      this._SymbolCtor = SymbolCtor || Symbol;
    }

    SymbolDraw.prototype.updateData = function (data, opt) {
      opt = normalizeUpdateOpt(opt);
      var group = this.group;
      var seriesModel = data.hostModel;
      var oldData = this._data;
      var SymbolCtor = this._SymbolCtor;
      var disableAnimation = opt.disableAnimation;
      var seriesScope = makeSeriesScope(data);
      var symbolUpdateOpt = {
        disableAnimation: disableAnimation
      };

      var getSymbolPoint = opt.getSymbolPoint || function (idx) {
        return data.getItemLayout(idx);
      };

      if (!oldData) {
        group.removeAll();
      }

      data.diff(oldData).add(function (newIdx) {
        var point = getSymbolPoint(newIdx);

        if (symbolNeedsDraw(data, point, newIdx, opt)) {
          var symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt);
          symbolEl.setPosition(point);
          data.setItemGraphicEl(newIdx, symbolEl);
          group.add(symbolEl);
        }
      }).update(function (newIdx, oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);
        var point = getSymbolPoint(newIdx);

        if (!symbolNeedsDraw(data, point, newIdx, opt)) {
          group.remove(symbolEl);
          return;
        }

        if (!symbolEl) {
          symbolEl = new SymbolCtor(data, newIdx);
          symbolEl.setPosition(point);
        } else {
          symbolEl.updateData(data, newIdx, seriesScope, symbolUpdateOpt);
          var target = {
            x: point[0],
            y: point[1]
          };
          disableAnimation ? symbolEl.attr(target) : updateProps(symbolEl, target, seriesModel);
        }

        group.add(symbolEl);
        data.setItemGraphicEl(newIdx, symbolEl);
      }).remove(function (oldIdx) {
        var el = oldData.getItemGraphicEl(oldIdx);
        el && el.fadeOut(function () {
          group.remove(el);
        });
      }).execute();
      this._getSymbolPoint = getSymbolPoint;
      this._data = data;
    };

    SymbolDraw.prototype.isPersistent = function () {
      return true;
    };

    SymbolDraw.prototype.updateLayout = function () {
      var _this = this;

      var data = this._data;

      if (data) {
        data.eachItemGraphicEl(function (el, idx) {
          var point = _this._getSymbolPoint(idx);

          el.setPosition(point);
          el.markRedraw();
        });
      }
    };

    SymbolDraw.prototype.incrementalPrepareUpdate = function (data) {
      this._seriesScope = makeSeriesScope(data);
      this._data = null;
      this.group.removeAll();
    };

    SymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) {
      opt = normalizeUpdateOpt(opt);

      function updateIncrementalAndHover(el) {
        if (!el.isGroup) {
          el.incremental = true;
          el.ensureState('emphasis').hoverLayer = true;
        }
      }

      for (var idx = taskParams.start; idx < taskParams.end; idx++) {
        var point = data.getItemLayout(idx);

        if (symbolNeedsDraw(data, point, idx, opt)) {
          var el = new this._SymbolCtor(data, idx, this._seriesScope);
          el.traverse(updateIncrementalAndHover);
          el.setPosition(point);
          this.group.add(el);
          data.setItemGraphicEl(idx, el);
        }
      }
    };

    SymbolDraw.prototype.remove = function (enableAnimation) {
      var group = this.group;
      var data = this._data;

      if (data && enableAnimation) {
        data.eachItemGraphicEl(function (el) {
          el.fadeOut(function () {
            group.remove(el);
          });
        });
      } else {
        group.removeAll();
      }
    };

    return SymbolDraw;
  }();

  function prepareDataCoordInfo(coordSys, data, valueOrigin) {
    var baseAxis = coordSys.getBaseAxis();
    var valueAxis = coordSys.getOtherAxis(baseAxis);
    var valueStart = getValueStart(valueAxis, valueOrigin);
    var baseAxisDim = baseAxis.dim;
    var valueAxisDim = valueAxis.dim;
    var valueDim = data.mapDimension(valueAxisDim);
    var baseDim = data.mapDimension(baseAxisDim);
    var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0;
    var dims = map(coordSys.dimensions, function (coordDim) {
      return data.mapDimension(coordDim);
    });
    var stacked = false;
    var stackResultDim = data.getCalculationInfo('stackResultDimension');

    if (isDimensionStacked(data, dims[0])) {
      stacked = true;
      dims[0] = stackResultDim;
    }

    if (isDimensionStacked(data, dims[1])) {
      stacked = true;
      dims[1] = stackResultDim;
    }

    return {
      dataDimsForPoint: dims,
      valueStart: valueStart,
      valueAxisDim: valueAxisDim,
      baseAxisDim: baseAxisDim,
      stacked: !!stacked,
      valueDim: valueDim,
      baseDim: baseDim,
      baseDataOffset: baseDataOffset,
      stackedOverDimension: data.getCalculationInfo('stackedOverDimension')
    };
  }

  function getValueStart(valueAxis, valueOrigin) {
    var valueStart = 0;
    var extent = valueAxis.scale.getExtent();

    if (valueOrigin === 'start') {
      valueStart = extent[0];
    } else if (valueOrigin === 'end') {
      valueStart = extent[1];
    } else {
      if (extent[0] > 0) {
        valueStart = extent[0];
      } else if (extent[1] < 0) {
        valueStart = extent[1];
      }
    }

    return valueStart;
  }

  function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) {
    var value = NaN;

    if (dataCoordInfo.stacked) {
      value = data.get(data.getCalculationInfo('stackedOverDimension'), idx);
    }

    if (isNaN(value)) {
      value = dataCoordInfo.valueStart;
    }

    var baseDataOffset = dataCoordInfo.baseDataOffset;
    var stackedData = [];
    stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx);
    stackedData[1 - baseDataOffset] = value;
    return coordSys.dataToPoint(stackedData);
  }

  var supportFloat32Array = typeof Float32Array !== 'undefined';
  var Float32ArrayCtor = !supportFloat32Array ? Array : Float32Array;

  function createFloat32Array(arg) {
    if (isArray(arg)) {
      return supportFloat32Array ? new Float32Array(arg) : arg;
    }

    return new Float32ArrayCtor(arg);
  }

  function diffData(oldData, newData) {
    var diffResult = [];
    newData.diff(oldData).add(function (idx) {
      diffResult.push({
        cmd: '+',
        idx: idx
      });
    }).update(function (newIdx, oldIdx) {
      diffResult.push({
        cmd: '=',
        idx: oldIdx,
        idx1: newIdx
      });
    }).remove(function (idx) {
      diffResult.push({
        cmd: '-',
        idx: idx
      });
    }).execute();
    return diffResult;
  }

  function lineAnimationDiff(oldData, newData, oldStackedOnPoints, newStackedOnPoints, oldCoordSys, newCoordSys, oldValueOrigin, newValueOrigin) {
    var diff = diffData(oldData, newData);
    var currPoints = [];
    var nextPoints = [];
    var currStackedPoints = [];
    var nextStackedPoints = [];
    var status = [];
    var sortedIndices = [];
    var rawIndices = [];
    var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin);
    var oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin);
    var oldPoints = oldData.getLayout('points') || [];
    var newPoints = newData.getLayout('points') || [];

    for (var i = 0; i < diff.length; i++) {
      var diffItem = diff[i];
      var pointAdded = true;
      var oldIdx2 = void 0;
      var newIdx2 = void 0;

      switch (diffItem.cmd) {
        case '=':
          oldIdx2 = diffItem.idx * 2;
          newIdx2 = diffItem.idx1 * 2;
          var currentX = oldPoints[oldIdx2];
          var currentY = oldPoints[oldIdx2 + 1];
          var nextX = newPoints[newIdx2];
          var nextY = newPoints[newIdx2 + 1];

          if (isNaN(currentX) || isNaN(currentY)) {
            currentX = nextX;
            currentY = nextY;
          }

          currPoints.push(currentX, currentY);
          nextPoints.push(nextX, nextY);
          currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]);
          nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]);
          rawIndices.push(newData.getRawIndex(diffItem.idx1));
          break;

        case '+':
          var newIdx = diffItem.idx;
          var newDataDimsForPoint = newDataOldCoordInfo.dataDimsForPoint;
          var oldPt = oldCoordSys.dataToPoint([newData.get(newDataDimsForPoint[0], newIdx), newData.get(newDataDimsForPoint[1], newIdx)]);
          newIdx2 = newIdx * 2;
          currPoints.push(oldPt[0], oldPt[1]);
          nextPoints.push(newPoints[newIdx2], newPoints[newIdx2 + 1]);
          var stackedOnPoint = getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, newIdx);
          currStackedPoints.push(stackedOnPoint[0], stackedOnPoint[1]);
          nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]);
          rawIndices.push(newData.getRawIndex(newIdx));
          break;

        case '-':
          var oldIdx = diffItem.idx;
          var rawIndex = oldData.getRawIndex(oldIdx);
          var oldDataDimsForPoint = oldDataNewCoordInfo.dataDimsForPoint;
          oldIdx2 = oldIdx * 2;

          if (rawIndex !== oldIdx) {
            var newPt = newCoordSys.dataToPoint([oldData.get(oldDataDimsForPoint[0], oldIdx), oldData.get(oldDataDimsForPoint[1], oldIdx)]);
            var newStackedOnPt = getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, oldIdx);
            currPoints.push(oldPoints[oldIdx2], oldPoints[oldIdx2 + 1]);
            nextPoints.push(newPt[0], newPt[1]);
            currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]);
            nextStackedPoints.push(newStackedOnPt[0], newStackedOnPt[1]);
            rawIndices.push(rawIndex);
          } else {
            pointAdded = false;
          }

      }

      if (pointAdded) {
        status.push(diffItem);
        sortedIndices.push(sortedIndices.length);
      }
    }

    sortedIndices.sort(function (a, b) {
      return rawIndices[a] - rawIndices[b];
    });
    var len = currPoints.length;
    var sortedCurrPoints = createFloat32Array(len);
    var sortedNextPoints = createFloat32Array(len);
    var sortedCurrStackedPoints = createFloat32Array(len);
    var sortedNextStackedPoints = createFloat32Array(len);
    var sortedStatus = [];

    for (var i = 0; i < sortedIndices.length; i++) {
      var idx = sortedIndices[i];
      var i2 = i * 2;
      var idx2 = idx * 2;
      sortedCurrPoints[i2] = currPoints[idx2];
      sortedCurrPoints[i2 + 1] = currPoints[idx2 + 1];
      sortedNextPoints[i2] = nextPoints[idx2];
      sortedNextPoints[i2 + 1] = nextPoints[idx2 + 1];
      sortedCurrStackedPoints[i2] = currStackedPoints[idx2];
      sortedCurrStackedPoints[i2 + 1] = currStackedPoints[idx2 + 1];
      sortedNextStackedPoints[i2] = nextStackedPoints[idx2];
      sortedNextStackedPoints[i2 + 1] = nextStackedPoints[idx2 + 1];
      sortedStatus[i] = status[idx];
    }

    return {
      current: sortedCurrPoints,
      next: sortedNextPoints,
      stackedOnCurrent: sortedCurrStackedPoints,
      stackedOnNext: sortedNextStackedPoints,
      status: sortedStatus
    };
  }

  var mathMin$5 = Math.min;
  var mathMax$5 = Math.max;

  function isPointNull(x, y) {
    return isNaN(x) || isNaN(y);
  }

  function drawSegment(ctx, points, start, segLen, allLen, dir, smooth, smoothMonotone, connectNulls) {
    var prevX;
    var prevY;
    var cpx0;
    var cpy0;
    var cpx1;
    var cpy1;
    var idx = start;
    var k = 0;

    for (; k < segLen; k++) {
      var x = points[idx * 2];
      var y = points[idx * 2 + 1];

      if (idx >= allLen || idx < 0) {
        break;
      }

      if (isPointNull(x, y)) {
        if (connectNulls) {
          idx += dir;
          continue;
        }

        break;
      }

      if (idx === start) {
        ctx[dir > 0 ? 'moveTo' : 'lineTo'](x, y);
        cpx0 = x;
        cpy0 = y;
      } else {
        var dx = x - prevX;
        var dy = y - prevY;

        if (dx * dx + dy * dy < 0.5) {
          idx += dir;
          continue;
        }

        if (smooth > 0) {
          var nextIdx = idx + dir;
          var nextX = points[nextIdx * 2];
          var nextY = points[nextIdx * 2 + 1];
          var tmpK = k + 1;

          if (connectNulls) {
            while (isPointNull(nextX, nextY) && tmpK < segLen) {
              tmpK++;
              nextIdx += dir;
              nextX = points[nextIdx * 2];
              nextY = points[nextIdx * 2 + 1];
            }
          }

          var ratioNextSeg = 0.5;
          var vx = 0;
          var vy = 0;
          var nextCpx0 = void 0;
          var nextCpy0 = void 0;

          if (tmpK >= segLen || isPointNull(nextX, nextY)) {
            cpx1 = x;
            cpy1 = y;
          } else {
            vx = nextX - prevX;
            vy = nextY - prevY;
            var dx0 = x - prevX;
            var dx1 = nextX - x;
            var dy0 = y - prevY;
            var dy1 = nextY - y;
            var lenPrevSeg = void 0;
            var lenNextSeg = void 0;

            if (smoothMonotone === 'x') {
              lenPrevSeg = Math.abs(dx0);
              lenNextSeg = Math.abs(dx1);
              cpx1 = x - lenPrevSeg * smooth;
              cpy1 = y;
              nextCpx0 = x + lenPrevSeg * smooth;
              nextCpy0 = y;
            } else if (smoothMonotone === 'y') {
              lenPrevSeg = Math.abs(dy0);
              lenNextSeg = Math.abs(dy1);
              cpx1 = x;
              cpy1 = y - lenPrevSeg * smooth;
              nextCpx0 = x;
              nextCpy0 = y + lenPrevSeg * smooth;
            } else {
              lenPrevSeg = Math.sqrt(dx0 * dx0 + dy0 * dy0);
              lenNextSeg = Math.sqrt(dx1 * dx1 + dy1 * dy1);
              ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);
              cpx1 = x - vx * smooth * (1 - ratioNextSeg);
              cpy1 = y - vy * smooth * (1 - ratioNextSeg);
              nextCpx0 = x + vx * smooth * ratioNextSeg;
              nextCpy0 = y + vy * smooth * ratioNextSeg;
              nextCpx0 = mathMin$5(nextCpx0, mathMax$5(nextX, x));
              nextCpy0 = mathMin$5(nextCpy0, mathMax$5(nextY, y));
              nextCpx0 = mathMax$5(nextCpx0, mathMin$5(nextX, x));
              nextCpy0 = mathMax$5(nextCpy0, mathMin$5(nextY, y));
              vx = nextCpx0 - x;
              vy = nextCpy0 - y;
              cpx1 = x - vx * lenPrevSeg / lenNextSeg;
              cpy1 = y - vy * lenPrevSeg / lenNextSeg;
              cpx1 = mathMin$5(cpx1, mathMax$5(prevX, x));
              cpy1 = mathMin$5(cpy1, mathMax$5(prevY, y));
              cpx1 = mathMax$5(cpx1, mathMin$5(prevX, x));
              cpy1 = mathMax$5(cpy1, mathMin$5(prevY, y));
              vx = x - cpx1;
              vy = y - cpy1;
              nextCpx0 = x + vx * lenNextSeg / lenPrevSeg;
              nextCpy0 = y + vy * lenNextSeg / lenPrevSeg;
            }
          }

          ctx.bezierCurveTo(cpx0, cpy0, cpx1, cpy1, x, y);
          cpx0 = nextCpx0;
          cpy0 = nextCpy0;
        } else {
          ctx.lineTo(x, y);
        }
      }

      prevX = x;
      prevY = y;
      idx += dir;
    }

    return k;
  }

  var ECPolylineShape = function () {
    function ECPolylineShape() {
      this.smooth = 0;
      this.smoothConstraint = true;
    }

    return ECPolylineShape;
  }();

  var ECPolyline = function (_super) {
    __extends(ECPolyline, _super);

    function ECPolyline(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'ec-polyline';
      return _this;
    }

    ECPolyline.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    ECPolyline.prototype.getDefaultShape = function () {
      return new ECPolylineShape();
    };

    ECPolyline.prototype.buildPath = function (ctx, shape) {
      var points = shape.points;
      var i = 0;
      var len = points.length / 2;

      if (shape.connectNulls) {
        for (; len > 0; len--) {
          if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) {
            break;
          }
        }

        for (; i < len; i++) {
          if (!isPointNull(points[i * 2], points[i * 2 + 1])) {
            break;
          }
        }
      }

      while (i < len) {
        i += drawSegment(ctx, points, i, len, len, 1, shape.smooth, shape.smoothMonotone, shape.connectNulls) + 1;
      }
    };

    ECPolyline.prototype.getPointOn = function (xOrY, dim) {
      if (!this.path) {
        this.createPathProxy();
        this.buildPath(this.path, this.shape);
      }

      var path = this.path;
      var data = path.data;
      var CMD = PathProxy.CMD;
      var x0;
      var y0;
      var isDimX = dim === 'x';
      var roots = [];

      for (var i = 0; i < data.length;) {
        var cmd = data[i++];
        var x = void 0;
        var y = void 0;
        var x2 = void 0;
        var y2 = void 0;
        var x3 = void 0;
        var y3 = void 0;
        var t = void 0;

        switch (cmd) {
          case CMD.M:
            x0 = data[i++];
            y0 = data[i++];
            break;

          case CMD.L:
            x = data[i++];
            y = data[i++];
            t = isDimX ? (xOrY - x0) / (x - x0) : (xOrY - y0) / (y - y0);

            if (t <= 1 && t >= 0) {
              var val = isDimX ? (y - y0) * t + y0 : (x - x0) * t + x0;
              return isDimX ? [xOrY, val] : [val, xOrY];
            }

            x0 = x;
            y0 = y;
            break;

          case CMD.C:
            x = data[i++];
            y = data[i++];
            x2 = data[i++];
            y2 = data[i++];
            x3 = data[i++];
            y3 = data[i++];
            var nRoot = isDimX ? cubicRootAt(x0, x, x2, x3, xOrY, roots) : cubicRootAt(y0, y, y2, y3, xOrY, roots);

            if (nRoot > 0) {
              for (var i_1 = 0; i_1 < nRoot; i_1++) {
                var t_1 = roots[i_1];

                if (t_1 <= 1 && t_1 >= 0) {
                  var val = isDimX ? cubicAt(y0, y, y2, y3, t_1) : cubicAt(x0, x, x2, x3, t_1);
                  return isDimX ? [xOrY, val] : [val, xOrY];
                }
              }
            }

            x0 = x3;
            y0 = y3;
            break;
        }
      }
    };

    return ECPolyline;
  }(Path);

  var ECPolygonShape = function (_super) {
    __extends(ECPolygonShape, _super);

    function ECPolygonShape() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    return ECPolygonShape;
  }(ECPolylineShape);

  var ECPolygon = function (_super) {
    __extends(ECPolygon, _super);

    function ECPolygon(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'ec-polygon';
      return _this;
    }

    ECPolygon.prototype.getDefaultShape = function () {
      return new ECPolygonShape();
    };

    ECPolygon.prototype.buildPath = function (ctx, shape) {
      var points = shape.points;
      var stackedOnPoints = shape.stackedOnPoints;
      var i = 0;
      var len = points.length / 2;
      var smoothMonotone = shape.smoothMonotone;

      if (shape.connectNulls) {
        for (; len > 0; len--) {
          if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) {
            break;
          }
        }

        for (; i < len; i++) {
          if (!isPointNull(points[i * 2], points[i * 2 + 1])) {
            break;
          }
        }
      }

      while (i < len) {
        var k = drawSegment(ctx, points, i, len, len, 1, shape.smooth, smoothMonotone, shape.connectNulls);
        drawSegment(ctx, stackedOnPoints, i + k - 1, k, len, -1, shape.stackedOnSmooth, smoothMonotone, shape.connectNulls);
        i += k + 1;
        ctx.closePath();
      }
    };

    return ECPolygon;
  }(Path);

  function createGridClipPath(cartesian, hasAnimation, seriesModel, done, during) {
    var rect = cartesian.getArea();
    var x = rect.x;
    var y = rect.y;
    var width = rect.width;
    var height = rect.height;
    var lineWidth = seriesModel.get(['lineStyle', 'width']) || 2;
    x -= lineWidth / 2;
    y -= lineWidth / 2;
    width += lineWidth;
    height += lineWidth;
    x = Math.floor(x);
    width = Math.round(width);
    var clipPath = new Rect({
      shape: {
        x: x,
        y: y,
        width: width,
        height: height
      }
    });

    if (hasAnimation) {
      var baseAxis = cartesian.getBaseAxis();
      var isHorizontal = baseAxis.isHorizontal();
      var isAxisInversed = baseAxis.inverse;

      if (isHorizontal) {
        if (isAxisInversed) {
          clipPath.shape.x += width;
        }

        clipPath.shape.width = 0;
      } else {
        if (!isAxisInversed) {
          clipPath.shape.y += height;
        }

        clipPath.shape.height = 0;
      }

      var duringCb = typeof during === 'function' ? function (percent) {
        during(percent, clipPath);
      } : null;
      initProps(clipPath, {
        shape: {
          width: width,
          height: height,
          x: x,
          y: y
        }
      }, seriesModel, null, done, duringCb);
    }

    return clipPath;
  }

  function createPolarClipPath(polar, hasAnimation, seriesModel) {
    var sectorArea = polar.getArea();
    var r0 = round$1(sectorArea.r0, 1);
    var r = round$1(sectorArea.r, 1);
    var clipPath = new Sector({
      shape: {
        cx: round$1(polar.cx, 1),
        cy: round$1(polar.cy, 1),
        r0: r0,
        r: r,
        startAngle: sectorArea.startAngle,
        endAngle: sectorArea.endAngle,
        clockwise: sectorArea.clockwise
      }
    });

    if (hasAnimation) {
      var isRadial = polar.getBaseAxis().dim === 'angle';

      if (isRadial) {
        clipPath.shape.endAngle = sectorArea.startAngle;
      } else {
        clipPath.shape.r = r0;
      }

      initProps(clipPath, {
        shape: {
          endAngle: sectorArea.endAngle,
          r: r
        }
      }, seriesModel);
    }

    return clipPath;
  }

  function createClipPath(coordSys, hasAnimation, seriesModel, done, during) {
    if (!coordSys) {
      return null;
    } else if (coordSys.type === 'polar') {
      return createPolarClipPath(coordSys, hasAnimation, seriesModel);
    } else if (coordSys.type === 'cartesian2d') {
      return createGridClipPath(coordSys, hasAnimation, seriesModel, done, during);
    }

    return null;
  }

  function isCoordinateSystemType(coordSys, type) {
    return coordSys.type === type;
  }

  function isPointsSame(points1, points2) {
    if (points1.length !== points2.length) {
      return;
    }

    for (var i = 0; i < points1.length; i++) {
      if (points1[i] !== points2[i]) {
        return;
      }
    }

    return true;
  }

  function bboxFromPoints(points) {
    var minX = Infinity;
    var minY = Infinity;
    var maxX = -Infinity;
    var maxY = -Infinity;

    for (var i = 0; i < points.length;) {
      var x = points[i++];
      var y = points[i++];

      if (!isNaN(x)) {
        minX = Math.min(x, minX);
        maxX = Math.max(x, maxX);
      }

      if (!isNaN(y)) {
        minY = Math.min(y, minY);
        maxY = Math.max(y, maxY);
      }
    }

    return [[minX, minY], [maxX, maxY]];
  }

  function getBoundingDiff(points1, points2) {
    var _a = bboxFromPoints(points1),
        min1 = _a[0],
        max1 = _a[1];

    var _b = bboxFromPoints(points2),
        min2 = _b[0],
        max2 = _b[1];

    return Math.max(Math.abs(min1[0] - min2[0]), Math.abs(min1[1] - min2[1]), Math.abs(max1[0] - max2[0]), Math.abs(max1[1] - max2[1]));
  }

  function getSmooth(smooth) {
    return typeof smooth === 'number' ? smooth : smooth ? 0.5 : 0;
  }

  function getStackedOnPoints(coordSys, data, dataCoordInfo) {
    if (!dataCoordInfo.valueDim) {
      return [];
    }

    var len = data.count();
    var points = createFloat32Array(len * 2);

    for (var idx = 0; idx < len; idx++) {
      var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx);
      points[idx * 2] = pt[0];
      points[idx * 2 + 1] = pt[1];
    }

    return points;
  }

  function turnPointsIntoStep(points, coordSys, stepTurnAt) {
    var baseAxis = coordSys.getBaseAxis();
    var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;
    var stepPoints = [];
    var i = 0;
    var stepPt = [];
    var pt = [];
    var nextPt = [];

    for (; i < points.length - 2; i += 2) {
      nextPt[0] = points[i + 2];
      nextPt[1] = points[i + 3];
      pt[0] = points[i];
      pt[1] = points[i + 1];
      stepPoints.push(pt[0], pt[1]);

      switch (stepTurnAt) {
        case 'end':
          stepPt[baseIndex] = nextPt[baseIndex];
          stepPt[1 - baseIndex] = pt[1 - baseIndex];
          stepPoints.push(stepPt[0], stepPt[1]);
          break;

        case 'middle':
          var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2;
          var stepPt2 = [];
          stepPt[baseIndex] = stepPt2[baseIndex] = middle;
          stepPt[1 - baseIndex] = pt[1 - baseIndex];
          stepPt2[1 - baseIndex] = nextPt[1 - baseIndex];
          stepPoints.push(stepPt[0], stepPt[1]);
          stepPoints.push(stepPt2[0], stepPt2[1]);
          break;

        default:
          stepPt[baseIndex] = pt[baseIndex];
          stepPt[1 - baseIndex] = nextPt[1 - baseIndex];
          stepPoints.push(stepPt[0], stepPt[1]);
      }
    }

    stepPoints.push(points[i++], points[i++]);
    return stepPoints;
  }

  function getVisualGradient(data, coordSys) {
    var visualMetaList = data.getVisual('visualMeta');

    if (!visualMetaList || !visualMetaList.length || !data.count()) {
      return;
    }

    if (coordSys.type !== 'cartesian2d') {
      if (true) {
        console.warn('Visual map on line style is only supported on cartesian2d.');
      }

      return;
    }

    var coordDim;
    var visualMeta;

    for (var i = visualMetaList.length - 1; i >= 0; i--) {
      var dimIndex = visualMetaList[i].dimension;
      var dimName = data.dimensions[dimIndex];
      var dimInfo = data.getDimensionInfo(dimName);
      coordDim = dimInfo && dimInfo.coordDim;

      if (coordDim === 'x' || coordDim === 'y') {
        visualMeta = visualMetaList[i];
        break;
      }
    }

    if (!visualMeta) {
      if (true) {
        console.warn('Visual map on line style only support x or y dimension.');
      }

      return;
    }

    var axis = coordSys.getAxis(coordDim);
    var colorStops = map(visualMeta.stops, function (stop) {
      return {
        offset: 0,
        coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
        color: stop.color
      };
    });
    var stopLen = colorStops.length;
    var outerColors = visualMeta.outerColors.slice();

    if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) {
      colorStops.reverse();
      outerColors.reverse();
    }

    var tinyExtent = 10;
    var minCoord = colorStops[0].coord - tinyExtent;
    var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
    var coordSpan = maxCoord - minCoord;

    if (coordSpan < 1e-3) {
      return 'transparent';
    }

    each(colorStops, function (stop) {
      stop.offset = (stop.coord - minCoord) / coordSpan;
    });
    colorStops.push({
      offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
      color: outerColors[1] || 'transparent'
    });
    colorStops.unshift({
      offset: stopLen ? colorStops[0].offset : 0.5,
      color: outerColors[0] || 'transparent'
    });
    var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
    gradient[coordDim] = minCoord;
    gradient[coordDim + '2'] = maxCoord;
    return gradient;
  }

  function getIsIgnoreFunc(seriesModel, data, coordSys) {
    var showAllSymbol = seriesModel.get('showAllSymbol');
    var isAuto = showAllSymbol === 'auto';

    if (showAllSymbol && !isAuto) {
      return;
    }

    var categoryAxis = coordSys.getAxesByScale('ordinal')[0];

    if (!categoryAxis) {
      return;
    }

    if (isAuto && canShowAllSymbolForCategory(categoryAxis, data)) {
      return;
    }

    var categoryDataDim = data.mapDimension(categoryAxis.dim);
    var labelMap = {};
    each(categoryAxis.getViewLabels(), function (labelItem) {
      labelMap[labelItem.tickValue] = 1;
    });
    return function (dataIndex) {
      return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex));
    };
  }

  function canShowAllSymbolForCategory(categoryAxis, data) {
    var axisExtent = categoryAxis.getExtent();
    var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count();
    isNaN(availSize) && (availSize = 0);
    var dataLen = data.count();
    var step = Math.max(1, Math.round(dataLen / 5));

    for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) {
      if (Symbol.getSymbolSize(data, dataIndex)[categoryAxis.isHorizontal() ? 1 : 0] * 1.5 > availSize) {
        return false;
      }
    }

    return true;
  }

  function isPointNull$1(x, y) {
    return isNaN(x) || isNaN(y);
  }

  function getLastIndexNotNull(points) {
    var len = points.length / 2;

    for (; len > 0; len--) {
      if (!isPointNull$1(points[len * 2 - 2], points[len * 2 - 1])) {
        break;
      }
    }

    return len - 1;
  }

  function getPointAtIndex(points, idx) {
    return [points[idx * 2], points[idx * 2 + 1]];
  }

  function getIndexRange(points, xOrY, dim) {
    var len = points.length / 2;
    var dimIdx = dim === 'x' ? 0 : 1;
    var a;
    var b;
    var prevIndex = 0;
    var nextIndex = -1;

    for (var i = 0; i < len; i++) {
      b = points[i * 2 + dimIdx];

      if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) {
        continue;
      }

      if (i === 0) {
        a = b;
        continue;
      }

      if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) {
        nextIndex = i;
        break;
      }

      prevIndex = i;
      a = b;
    }

    return {
      range: [prevIndex, nextIndex],
      t: (xOrY - a) / (b - a)
    };
  }

  function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) {
    if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
      var endLabelModel_1 = seriesModel.getModel('endLabel');
      var showEndLabel = endLabelModel_1.get('show');
      var valueAnimation_1 = endLabelModel_1.get('valueAnimation');
      var data_1 = seriesModel.getData();
      var labelAnimationRecord_1 = {
        lastFrameIndex: 0
      };
      var during = showEndLabel ? function (percent, clipRect) {
        lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys);
      } : null;
      var isHorizontal = coordSys.getBaseAxis().isHorizontal();
      var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () {
        var endLabel = lineView._endLabel;

        if (endLabel && hasAnimation) {
          if (labelAnimationRecord_1.originalX != null) {
            endLabel.attr({
              x: labelAnimationRecord_1.originalX,
              y: labelAnimationRecord_1.originalY
            });
          }
        }
      }, during);

      if (!seriesModel.get('clip', true)) {
        var rectShape = clipPath.shape;
        var expandSize = Math.max(rectShape.width, rectShape.height);

        if (isHorizontal) {
          rectShape.y -= expandSize;
          rectShape.height += expandSize * 2;
        } else {
          rectShape.x -= expandSize;
          rectShape.width += expandSize * 2;
        }
      }

      if (during) {
        during(1, clipPath);
      }

      return clipPath;
    } else {
      if (true) {
        if (seriesModel.get(['endLabel', 'show'])) {
          console.warn('endLabel is not supported for lines in polar systems.');
        }
      }

      return createPolarClipPath(coordSys, hasAnimation, seriesModel);
    }
  }

  function getEndLabelStateSpecified(endLabelModel, coordSys) {
    var baseAxis = coordSys.getBaseAxis();
    var isHorizontal = baseAxis.isHorizontal();
    var isBaseInversed = baseAxis.inverse;
    var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center';
    var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom';
    return {
      normal: {
        align: endLabelModel.get('align') || align,
        verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign,
        padding: endLabelModel.get('distance') || 0
      }
    };
  }

  var LineView = function (_super) {
    __extends(LineView, _super);

    function LineView() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    LineView.prototype.init = function () {
      var lineGroup = new Group();
      var symbolDraw = new SymbolDraw();
      this.group.add(symbolDraw.group);
      this._symbolDraw = symbolDraw;
      this._lineGroup = lineGroup;
    };

    LineView.prototype.render = function (seriesModel, ecModel, api) {
      var _this = this;

      var coordSys = seriesModel.coordinateSystem;
      var group = this.group;
      var data = seriesModel.getData();
      var lineStyleModel = seriesModel.getModel('lineStyle');
      var areaStyleModel = seriesModel.getModel('areaStyle');
      var points = data.getLayout('points') || [];
      var isCoordSysPolar = coordSys.type === 'polar';
      var prevCoordSys = this._coordSys;
      var symbolDraw = this._symbolDraw;
      var polyline = this._polyline;
      var polygon = this._polygon;
      var lineGroup = this._lineGroup;
      var hasAnimation = seriesModel.get('animation');
      var isAreaChart = !areaStyleModel.isEmpty();
      var valueOrigin = areaStyleModel.get('origin');
      var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin);
      var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo);
      var showSymbol = seriesModel.get('showSymbol');
      var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys);
      var oldData = this._data;
      oldData && oldData.eachItemGraphicEl(function (el, idx) {
        if (el.__temp) {
          group.remove(el);
          oldData.setItemGraphicEl(idx, null);
        }
      });

      if (!showSymbol) {
        symbolDraw.remove();
      }

      group.add(lineGroup);
      var step = !isCoordSysPolar ? seriesModel.get('step') : false;
      var clipShapeForSymbol;

      if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
        clipShapeForSymbol = coordSys.getArea();

        if (clipShapeForSymbol.width != null) {
          clipShapeForSymbol.x -= 0.1;
          clipShapeForSymbol.y -= 0.1;
          clipShapeForSymbol.width += 0.2;
          clipShapeForSymbol.height += 0.2;
        } else if (clipShapeForSymbol.r0) {
          clipShapeForSymbol.r0 -= 0.5;
          clipShapeForSymbol.r += 0.5;
        }
      }

      this._clipShapeForSymbol = clipShapeForSymbol;

      if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
        showSymbol && symbolDraw.updateData(data, {
          isIgnore: isIgnoreFunc,
          clipShape: clipShapeForSymbol,
          disableAnimation: true,
          getSymbolPoint: function (idx) {
            return [points[idx * 2], points[idx * 2 + 1]];
          }
        });
        hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol);

        if (step) {
          points = turnPointsIntoStep(points, coordSys, step);

          if (stackedOnPoints) {
            stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
          }
        }

        polyline = this._newPolyline(points);

        if (isAreaChart) {
          polygon = this._newPolygon(points, stackedOnPoints);
        }

        if (!isCoordSysPolar) {
          this._initOrUpdateEndLabel(seriesModel, coordSys);
        }

        lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
      } else {
        if (isAreaChart && !polygon) {
          polygon = this._newPolygon(points, stackedOnPoints);
        } else if (polygon && !isAreaChart) {
          lineGroup.remove(polygon);
          polygon = this._polygon = null;
        }

        if (!isCoordSysPolar) {
          this._initOrUpdateEndLabel(seriesModel, coordSys);
        }

        lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel));
        showSymbol && symbolDraw.updateData(data, {
          isIgnore: isIgnoreFunc,
          clipShape: clipShapeForSymbol,
          disableAnimation: true,
          getSymbolPoint: function (idx) {
            return [points[idx * 2], points[idx * 2 + 1]];
          }
        });

        if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) {
          if (hasAnimation) {
            this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin);
          } else {
            if (step) {
              points = turnPointsIntoStep(points, coordSys, step);

              if (stackedOnPoints) {
                stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
              }
            }

            polyline.setShape({
              points: points
            });
            polygon && polygon.setShape({
              points: points,
              stackedOnPoints: stackedOnPoints
            });
          }
        }
      }

      var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')];
      var focus = seriesModel.get(['emphasis', 'focus']);
      var blurScope = seriesModel.get(['emphasis', 'blurScope']);
      polyline.useStyle(defaults(lineStyleModel.getLineStyle(), {
        fill: 'none',
        stroke: visualColor,
        lineJoin: 'bevel'
      }));
      setStatesStylesFromModel(polyline, seriesModel, 'lineStyle');

      if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') {
        var emphasisLineStyle = polyline.getState('emphasis').style;
        emphasisLineStyle.lineWidth = polyline.style.lineWidth + 1;
      }

      getECData(polyline).seriesIndex = seriesModel.seriesIndex;
      enableHoverEmphasis(polyline, focus, blurScope);
      var smooth = getSmooth(seriesModel.get('smooth'));
      var smoothMonotone = seriesModel.get('smoothMonotone');
      var connectNulls = seriesModel.get('connectNulls');
      polyline.setShape({
        smooth: smooth,
        smoothMonotone: smoothMonotone,
        connectNulls: connectNulls
      });

      if (polygon) {
        var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
        var stackedOnSmooth = 0;
        polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), {
          fill: visualColor,
          opacity: 0.7,
          lineJoin: 'bevel',
          decal: data.getVisual('style').decal
        }));

        if (stackedOnSeries) {
          stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
        }

        polygon.setShape({
          smooth: smooth,
          stackedOnSmooth: stackedOnSmooth,
          smoothMonotone: smoothMonotone,
          connectNulls: connectNulls
        });
        setStatesStylesFromModel(polygon, seriesModel, 'areaStyle');
        getECData(polygon).seriesIndex = seriesModel.seriesIndex;
        enableHoverEmphasis(polygon, focus, blurScope);
      }

      var changePolyState = function (toState) {
        _this._changePolyState(toState);
      };

      data.eachItemGraphicEl(function (el) {
        el && (el.onHoverStateChange = changePolyState);
      });
      this._polyline.onHoverStateChange = changePolyState;
      this._data = data;
      this._coordSys = coordSys;
      this._stackedOnPoints = stackedOnPoints;
      this._points = points;
      this._step = step;
      this._valueOrigin = valueOrigin;
    };

    LineView.prototype.dispose = function () {};

    LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) {
      var data = seriesModel.getData();
      var dataIndex = queryDataIndex(data, payload);

      this._changePolyState('emphasis');

      if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) {
        var points = data.getLayout('points');
        var symbol = data.getItemGraphicEl(dataIndex);

        if (!symbol) {
          var x = points[dataIndex * 2];
          var y = points[dataIndex * 2 + 1];

          if (isNaN(x) || isNaN(y)) {
            return;
          }

          if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) {
            return;
          }

          symbol = new Symbol(data, dataIndex);
          symbol.x = x;
          symbol.y = y;
          symbol.setZ(seriesModel.get('zlevel'), seriesModel.get('z'));
          symbol.__temp = true;
          data.setItemGraphicEl(dataIndex, symbol);
          symbol.stopSymbolAnimation(true);
          this.group.add(symbol);
        }

        symbol.highlight();
      } else {
        ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload);
      }
    };

    LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) {
      var data = seriesModel.getData();
      var dataIndex = queryDataIndex(data, payload);

      this._changePolyState('normal');

      if (dataIndex != null && dataIndex >= 0) {
        var symbol = data.getItemGraphicEl(dataIndex);

        if (symbol) {
          if (symbol.__temp) {
            data.setItemGraphicEl(dataIndex, null);
            this.group.remove(symbol);
          } else {
            symbol.downplay();
          }
        }
      } else {
        ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload);
      }
    };

    LineView.prototype._changePolyState = function (toState) {
      var polygon = this._polygon;
      setStatesFlag(this._polyline, toState);
      polygon && setStatesFlag(polygon, toState);
    };

    LineView.prototype._newPolyline = function (points) {
      var polyline = this._polyline;

      if (polyline) {
        this._lineGroup.remove(polyline);
      }

      polyline = new ECPolyline({
        shape: {
          points: points
        },
        segmentIgnoreThreshold: 2,
        z2: 10
      });

      this._lineGroup.add(polyline);

      this._polyline = polyline;
      return polyline;
    };

    LineView.prototype._newPolygon = function (points, stackedOnPoints) {
      var polygon = this._polygon;

      if (polygon) {
        this._lineGroup.remove(polygon);
      }

      polygon = new ECPolygon({
        shape: {
          points: points,
          stackedOnPoints: stackedOnPoints
        },
        segmentIgnoreThreshold: 2
      });

      this._lineGroup.add(polygon);

      this._polygon = polygon;
      return polygon;
    };

    LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) {
      var isHorizontalOrRadial;
      var isCoordSysPolar;
      var baseAxis = coordSys.getBaseAxis();
      var isAxisInverse = baseAxis.inverse;

      if (coordSys.type === 'cartesian2d') {
        isHorizontalOrRadial = baseAxis.isHorizontal();
        isCoordSysPolar = false;
      } else if (coordSys.type === 'polar') {
        isHorizontalOrRadial = baseAxis.dim === 'angle';
        isCoordSysPolar = true;
      }

      var seriesModel = data.hostModel;
      var seriesDuration = seriesModel.get('animationDuration');

      if (typeof seriesDuration === 'function') {
        seriesDuration = seriesDuration(null);
      }

      var seriesDalay = seriesModel.get('animationDelay') || 0;
      var seriesDalayValue = typeof seriesDalay === 'function' ? seriesDalay(null) : seriesDalay;
      data.eachItemGraphicEl(function (symbol, idx) {
        var el = symbol;

        if (el) {
          var point = [symbol.x, symbol.y];
          var start = void 0;
          var end = void 0;
          var current = void 0;

          if (isCoordSysPolar) {
            var polarClip = clipShape;
            var coord = coordSys.pointToCoord(point);

            if (isHorizontalOrRadial) {
              start = polarClip.startAngle;
              end = polarClip.endAngle;
              current = -coord[1] / 180 * Math.PI;
            } else {
              start = polarClip.r0;
              end = polarClip.r;
              current = coord[0];
            }
          } else {
            var gridClip = clipShape;

            if (isHorizontalOrRadial) {
              start = gridClip.x;
              end = gridClip.x + gridClip.width;
              current = symbol.x;
            } else {
              start = gridClip.y + gridClip.height;
              end = gridClip.y;
              current = symbol.y;
            }
          }

          var ratio = end === start ? 0 : (current - start) / (end - start);

          if (isAxisInverse) {
            ratio = 1 - ratio;
          }

          var delay = typeof seriesDalay === 'function' ? seriesDalay(idx) : seriesDuration * ratio + seriesDalayValue;
          var symbolPath = el.getSymbolPath();
          var text = symbolPath.getTextContent();
          el.attr({
            scaleX: 0,
            scaleY: 0
          });
          el.animateTo({
            scaleX: 1,
            scaleY: 1
          }, {
            duration: 200,
            delay: delay
          });

          if (text) {
            text.animateFrom({
              style: {
                opacity: 0
              }
            }, {
              duration: 300,
              delay: delay
            });
          }

          symbolPath.disableLabelAnimation = true;
        }
      });
    };

    LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys) {
      var endLabelModel = seriesModel.getModel('endLabel');

      if (endLabelModel.get('show')) {
        var data_2 = seriesModel.getData();
        var polyline = this._polyline;
        var endLabel = this._endLabel;

        if (!endLabel) {
          endLabel = this._endLabel = new ZRText({
            z2: 200
          });
          endLabel.ignoreClip = true;
          polyline.setTextContent(this._endLabel);
          polyline.disableLabelAnimation = true;
        }

        var dataIndex = getLastIndexNotNull(data_2.getLayout('points'));

        if (dataIndex >= 0) {
          setLabelStyle(endLabel, getLabelStatesModels(seriesModel, 'endLabel'), {
            labelFetcher: seriesModel,
            labelDataIndex: dataIndex,
            defaultText: function (dataIndex, opt, overrideValue) {
              return overrideValue ? getDefaultInterpolatedLabel(data_2, overrideValue) : getDefaultLabel(data_2, dataIndex);
            },
            enableTextSetter: true
          }, getEndLabelStateSpecified(endLabelModel, coordSys));
        }
      } else if (this._endLabel) {
        this._polyline.removeTextContent();

        this._endLabel = null;
      }
    };

    LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) {
      var endLabel = this._endLabel;
      var polyline = this._polyline;

      if (endLabel) {
        if (percent < 1 && animationRecord.originalX == null) {
          animationRecord.originalX = endLabel.x;
          animationRecord.originalY = endLabel.y;
        }

        var points = data.getLayout('points');
        var seriesModel = data.hostModel;
        var connectNulls = seriesModel.get('connectNulls');
        var precision = endLabelModel.get('precision');
        var baseAxis = coordSys.getBaseAxis();
        var isHorizontal = baseAxis.isHorizontal();
        var isBaseInversed = baseAxis.inverse;
        var clipShape = clipRect.shape;
        var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y;
        var dim = isHorizontal ? 'x' : 'y';
        var dataIndexRange = getIndexRange(points, xOrY, dim);
        var indices = dataIndexRange.range;
        var diff = indices[1] - indices[0];
        var value = void 0;

        if (diff >= 1) {
          if (diff > 1 && !connectNulls) {
            var pt = getPointAtIndex(points, indices[0]);
            endLabel.attr({
              x: pt[0],
              y: pt[1]
            });
            valueAnimation && (value = seriesModel.getRawValue(indices[0]));
          } else {
            var pt = polyline.getPointOn(xOrY, dim);
            pt && endLabel.attr({
              x: pt[0],
              y: pt[1]
            });
            var startValue = seriesModel.getRawValue(indices[0]);
            var endValue = seriesModel.getRawValue(indices[1]);
            valueAnimation && (value = interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t));
          }

          animationRecord.lastFrameIndex = indices[0];
        } else {
          var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0;
          var pt = getPointAtIndex(points, idx);
          valueAnimation && (value = seriesModel.getRawValue(idx));
          endLabel.attr({
            x: pt[0],
            y: pt[1]
          });
        }

        if (valueAnimation) {
          labelInner(endLabel).setLabelText(value);
        }
      }
    };

    LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin) {
      var polyline = this._polyline;
      var polygon = this._polygon;
      var seriesModel = data.hostModel;
      var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin, valueOrigin);
      var current = diff.current;
      var stackedOnCurrent = diff.stackedOnCurrent;
      var next = diff.next;
      var stackedOnNext = diff.stackedOnNext;

      if (step) {
        current = turnPointsIntoStep(diff.current, coordSys, step);
        stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step);
        next = turnPointsIntoStep(diff.next, coordSys, step);
        stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step);
      }

      if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
        polyline.setShape({
          points: next
        });

        if (polygon) {
          polygon.setShape({
            points: next,
            stackedOnPoints: stackedOnNext
          });
        }

        return;
      }

      polyline.shape.__points = diff.current;
      polyline.shape.points = current;
      var target = {
        shape: {
          points: next
        }
      };

      if (diff.current !== current) {
        target.shape.__points = diff.next;
      }

      polyline.stopAnimation();
      updateProps(polyline, target, seriesModel);

      if (polygon) {
        polygon.setShape({
          points: current,
          stackedOnPoints: stackedOnCurrent
        });
        polygon.stopAnimation();
        updateProps(polygon, {
          shape: {
            stackedOnPoints: stackedOnNext
          }
        }, seriesModel);

        if (polyline.shape.points !== polygon.shape.points) {
          polygon.shape.points = polyline.shape.points;
        }
      }

      var updatedDataInfo = [];
      var diffStatus = diff.status;

      for (var i = 0; i < diffStatus.length; i++) {
        var cmd = diffStatus[i].cmd;

        if (cmd === '=') {
          var el = data.getItemGraphicEl(diffStatus[i].idx1);

          if (el) {
            updatedDataInfo.push({
              el: el,
              ptIdx: i
            });
          }
        }
      }

      if (polyline.animators && polyline.animators.length) {
        polyline.animators[0].during(function () {
          polygon && polygon.dirtyShape();
          var points = polyline.shape.__points;

          for (var i = 0; i < updatedDataInfo.length; i++) {
            var el = updatedDataInfo[i].el;
            var offset = updatedDataInfo[i].ptIdx * 2;
            el.x = points[offset];
            el.y = points[offset + 1];
            el.markRedraw();
          }
        });
      }
    };

    LineView.prototype.remove = function (ecModel) {
      var group = this.group;
      var oldData = this._data;

      this._lineGroup.removeAll();

      this._symbolDraw.remove(true);

      oldData && oldData.eachItemGraphicEl(function (el, idx) {
        if (el.__temp) {
          group.remove(el);
          oldData.setItemGraphicEl(idx, null);
        }
      });
      this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null;
    };

    LineView.type = 'line';
    return LineView;
  }(ChartView);

  ChartView.registerClass(LineView);

  function pointsLayout(seriesType, forceStoreInTypedArray) {
    return {
      seriesType: seriesType,
      plan: createRenderPlanner(),
      reset: function (seriesModel) {
        var data = seriesModel.getData();
        var coordSys = seriesModel.coordinateSystem;
        var pipelineContext = seriesModel.pipelineContext;
        var useTypedArray = forceStoreInTypedArray || pipelineContext.large;

        if (!coordSys) {
          return;
        }

        var dims = map(coordSys.dimensions, function (dim) {
          return data.mapDimension(dim);
        }).slice(0, 2);
        var dimLen = dims.length;
        var stackResultDim = data.getCalculationInfo('stackResultDimension');

        if (isDimensionStacked(data, dims[0])) {
          dims[0] = stackResultDim;
        }

        if (isDimensionStacked(data, dims[1])) {
          dims[1] = stackResultDim;
        }

        var dimInfo0 = data.getDimensionInfo(dims[0]);
        var dimInfo1 = data.getDimensionInfo(dims[1]);
        var dimIdx0 = dimInfo0 && dimInfo0.index;
        var dimIdx1 = dimInfo1 && dimInfo1.index;
        return dimLen && {
          progress: function (params, data) {
            var segCount = params.end - params.start;
            var points = useTypedArray && createFloat32Array(segCount * dimLen);
            var tmpIn = [];
            var tmpOut = [];

            for (var i = params.start, offset = 0; i < params.end; i++) {
              var point = void 0;

              if (dimLen === 1) {
                var x = data.getByDimIdx(dimIdx0, i);
                point = coordSys.dataToPoint(x, null, tmpOut);
              } else {
                tmpIn[0] = data.getByDimIdx(dimIdx0, i);
                tmpIn[1] = data.getByDimIdx(dimIdx1, i);
                point = coordSys.dataToPoint(tmpIn, null, tmpOut);
              }

              if (useTypedArray) {
                points[offset++] = point[0];
                points[offset++] = point[1];
              } else {
                data.setItemLayout(i, point.slice());
              }
            }

            useTypedArray && data.setLayout('points', points);
          }
        };
      }
    };
  }

  var samplers = {
    average: function (frame) {
      var sum = 0;
      var count = 0;

      for (var i = 0; i < frame.length; i++) {
        if (!isNaN(frame[i])) {
          sum += frame[i];
          count++;
        }
      }

      return count === 0 ? NaN : sum / count;
    },
    sum: function (frame) {
      var sum = 0;

      for (var i = 0; i < frame.length; i++) {
        sum += frame[i] || 0;
      }

      return sum;
    },
    max: function (frame) {
      var max = -Infinity;

      for (var i = 0; i < frame.length; i++) {
        frame[i] > max && (max = frame[i]);
      }

      return isFinite(max) ? max : NaN;
    },
    min: function (frame) {
      var min = Infinity;

      for (var i = 0; i < frame.length; i++) {
        frame[i] < min && (min = frame[i]);
      }

      return isFinite(min) ? min : NaN;
    },
    nearest: function (frame) {
      return frame[0];
    }
  };

  var indexSampler = function (frame) {
    return Math.round(frame.length / 2);
  };

  function dataSample(seriesType) {
    return {
      seriesType: seriesType,
      reset: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var sampling = seriesModel.get('sampling');
        var coordSys = seriesModel.coordinateSystem;
        var count = data.count();

        if (count > 10 && coordSys.type === 'cartesian2d' && sampling) {
          var baseAxis = coordSys.getBaseAxis();
          var valueAxis = coordSys.getOtherAxis(baseAxis);
          var extent = baseAxis.getExtent();
          var dpr = api.getDevicePixelRatio();
          var size = Math.abs(extent[1] - extent[0]) * (dpr || 1);
          var rate = Math.round(count / size);

          if (rate > 1) {
            if (sampling === 'lttb') {
              seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate));
            }

            var sampler = void 0;

            if (typeof sampling === 'string') {
              sampler = samplers[sampling];
            } else if (typeof sampling === 'function') {
              sampler = sampling;
            }

            if (sampler) {
              seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler));
            }
          }
        }
      }
    };
  }

  var defaultOption = {
    show: true,
    zlevel: 0,
    z: 0,
    inverse: false,
    name: '',
    nameLocation: 'end',
    nameRotate: null,
    nameTruncate: {
      maxWidth: null,
      ellipsis: '...',
      placeholder: '.'
    },
    nameTextStyle: {},
    nameGap: 15,
    silent: false,
    triggerEvent: false,
    tooltip: {
      show: false
    },
    axisPointer: {},
    axisLine: {
      show: true,
      onZero: true,
      onZeroAxisIndex: null,
      lineStyle: {
        color: '#6E7079',
        width: 1,
        type: 'solid'
      },
      symbol: ['none', 'none'],
      symbolSize: [10, 15]
    },
    axisTick: {
      show: true,
      inside: false,
      length: 5,
      lineStyle: {
        width: 1
      }
    },
    axisLabel: {
      show: true,
      inside: false,
      rotate: 0,
      showMinLabel: null,
      showMaxLabel: null,
      margin: 8,
      fontSize: 12
    },
    splitLine: {
      show: true,
      lineStyle: {
        color: ['#E0E6F1'],
        width: 1,
        type: 'solid'
      }
    },
    splitArea: {
      show: false,
      areaStyle: {
        color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
      }
    }
  };
  var categoryAxis = merge({
    boundaryGap: true,
    deduplication: null,
    splitLine: {
      show: false
    },
    axisTick: {
      alignWithLabel: false,
      interval: 'auto'
    },
    axisLabel: {
      interval: 'auto'
    }
  }, defaultOption);
  var valueAxis = merge({
    boundaryGap: [0, 0],
    axisLine: {
      show: 'auto'
    },
    axisTick: {
      show: 'auto'
    },
    splitNumber: 5,
    minorTick: {
      show: false,
      splitNumber: 5,
      length: 3,
      lineStyle: {}
    },
    minorSplitLine: {
      show: false,
      lineStyle: {
        color: '#F4F7FD',
        width: 1
      }
    }
  }, defaultOption);
  var timeAxis = merge({
    scale: true,
    splitNumber: 6,
    axisLabel: {
      showMinLabel: false,
      showMaxLabel: false,
      rich: {
        primary: {
          fontWeight: 'bold'
        }
      }
    },
    splitLine: {
      show: false
    }
  }, valueAxis);
  var logAxis = defaults({
    scale: true,
    logBase: 10
  }, valueAxis);
  var axisDefault = {
    category: categoryAxis,
    value: valueAxis,
    time: timeAxis,
    log: logAxis
  };
  var AXIS_TYPES = {
    value: 1,
    category: 1,
    time: 1,
    log: 1
  };

  function axisModelCreator(axisName, BaseAxisModelClass, extraDefaultOption) {
    each(AXIS_TYPES, function (v, axisType) {
      var defaultOption = merge(merge({}, axisDefault[axisType], true), extraDefaultOption, true);

      var AxisModel = function (_super) {
        __extends(AxisModel, _super);

        function AxisModel() {
          var args = [];

          for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
          }

          var _this = _super.apply(this, args) || this;

          _this.type = axisName + 'Axis.' + axisType;
          return _this;
        }

        AxisModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
          var layoutMode = fetchLayoutMode(this);
          var inputPositionParams = layoutMode ? getLayoutParams(option) : {};
          var themeModel = ecModel.getTheme();
          merge(option, themeModel.get(axisType + 'Axis'));
          merge(option, this.getDefaultOption());
          option.type = getAxisType(option);

          if (layoutMode) {
            mergeLayoutParam(option, inputPositionParams, layoutMode);
          }
        };

        AxisModel.prototype.optionUpdated = function () {
          var thisOption = this.option;

          if (thisOption.type === 'category') {
            this.__ordinalMeta = OrdinalMeta.createByAxisModel(this);
          }
        };

        AxisModel.prototype.getCategories = function (rawData) {
          var option = this.option;

          if (option.type === 'category') {
            if (rawData) {
              return option.data;
            }

            return this.__ordinalMeta.categories;
          }
        };

        AxisModel.prototype.getOrdinalMeta = function () {
          return this.__ordinalMeta;
        };

        AxisModel.type = axisName + 'Axis.' + axisType;
        AxisModel.defaultOption = defaultOption;
        return AxisModel;
      }(BaseAxisModelClass);

      ComponentModel.registerClass(AxisModel);
    });
    ComponentModel.registerSubTypeDefaulter(axisName + 'Axis', getAxisType);
  }

  function getAxisType(option) {
    return option.type || (option.data ? 'category' : 'value');
  }

  var CartesianAxisModel = function (_super) {
    __extends(CartesianAxisModel, _super);

    function CartesianAxisModel() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    CartesianAxisModel.prototype.getCoordSysModel = function () {
      return this.getReferringComponents('grid', SINGLE_REFERRING).models[0];
    };

    CartesianAxisModel.type = 'cartesian2dAxis';
    return CartesianAxisModel;
  }(ComponentModel);

  mixin(CartesianAxisModel, AxisModelCommonMixin);
  var extraOption = {
    offset: 0,
    categorySortInfo: []
  };
  axisModelCreator('x', CartesianAxisModel, extraOption);
  axisModelCreator('y', CartesianAxisModel, extraOption);
  var PI$6 = Math.PI;

  var AxisBuilder = function () {
    function AxisBuilder(axisModel, opt) {
      this.group = new Group();
      this.opt = opt;
      this.axisModel = axisModel;
      defaults(opt, {
        labelOffset: 0,
        nameDirection: 1,
        tickDirection: 1,
        labelDirection: 1,
        silent: true,
        handleAutoShown: function () {
          return true;
        }
      });
      var transformGroup = new Group({
        x: opt.position[0],
        y: opt.position[1],
        rotation: opt.rotation
      });
      transformGroup.updateTransform();
      this._transformGroup = transformGroup;
    }

    AxisBuilder.prototype.hasBuilder = function (name) {
      return !!builders[name];
    };

    AxisBuilder.prototype.add = function (name) {
      builders[name](this.opt, this.axisModel, this.group, this._transformGroup);
    };

    AxisBuilder.prototype.getGroup = function () {
      return this.group;
    };

    AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
      var rotationDiff = remRadian(textRotation - axisRotation);
      var textAlign;
      var textVerticalAlign;

      if (isRadianAroundZero(rotationDiff)) {
        textVerticalAlign = direction > 0 ? 'top' : 'bottom';
        textAlign = 'center';
      } else if (isRadianAroundZero(rotationDiff - PI$6)) {
        textVerticalAlign = direction > 0 ? 'bottom' : 'top';
        textAlign = 'center';
      } else {
        textVerticalAlign = 'middle';

        if (rotationDiff > 0 && rotationDiff < PI$6) {
          textAlign = direction > 0 ? 'right' : 'left';
        } else {
          textAlign = direction > 0 ? 'left' : 'right';
        }
      }

      return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
      };
    };

    AxisBuilder.makeAxisEventDataBase = function (axisModel) {
      var eventData = {
        componentType: axisModel.mainType,
        componentIndex: axisModel.componentIndex
      };
      eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
      return eventData;
    };

    AxisBuilder.isLabelSilent = function (axisModel) {
      var tooltipOpt = axisModel.get('tooltip');
      return axisModel.get('silent') || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show);
    };

    return AxisBuilder;
  }();

  var builders = {
    axisLine: function (opt, axisModel, group, transformGroup) {
      var shown = axisModel.get(['axisLine', 'show']);

      if (shown === 'auto' && opt.handleAutoShown) {
        shown = opt.handleAutoShown('axisLine');
      }

      if (!shown) {
        return;
      }

      var extent = axisModel.axis.getExtent();
      var matrix = transformGroup.transform;
      var pt1 = [extent[0], 0];
      var pt2 = [extent[1], 0];

      if (matrix) {
        applyTransform(pt1, pt1, matrix);
        applyTransform(pt2, pt2, matrix);
      }

      var lineStyle = extend({
        lineCap: 'round'
      }, axisModel.getModel(['axisLine', 'lineStyle']).getLineStyle());
      var line = new Line({
        subPixelOptimize: true,
        shape: {
          x1: pt1[0],
          y1: pt1[1],
          x2: pt2[0],
          y2: pt2[1]
        },
        style: lineStyle,
        strokeContainThreshold: opt.strokeContainThreshold || 5,
        silent: true,
        z2: 1
      });
      line.anid = 'line';
      group.add(line);
      var arrows = axisModel.get(['axisLine', 'symbol']);
      var arrowSize = axisModel.get(['axisLine', 'symbolSize']);
      var arrowOffset = axisModel.get(['axisLine', 'symbolOffset']) || 0;

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

      if (arrows != null) {
        if (typeof arrows === 'string') {
          arrows = [arrows, arrows];
        }

        if (typeof arrowSize === 'string' || typeof arrowSize === 'number') {
          arrowSize = [arrowSize, arrowSize];
        }

        var symbolWidth_1 = arrowSize[0];
        var symbolHeight_1 = arrowSize[1];
        each([{
          rotate: opt.rotation + Math.PI / 2,
          offset: arrowOffset[0],
          r: 0
        }, {
          rotate: opt.rotation - Math.PI / 2,
          offset: arrowOffset[1],
          r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
        }], function (point, index) {
          if (arrows[index] !== 'none' && arrows[index] != null) {
            var symbol = createSymbol(arrows[index], -symbolWidth_1 / 2, -symbolHeight_1 / 2, symbolWidth_1, symbolHeight_1, lineStyle.stroke, true);
            var r = point.r + point.offset;
            symbol.attr({
              rotation: point.rotate,
              x: pt1[0] + r * Math.cos(opt.rotation),
              y: pt1[1] - r * Math.sin(opt.rotation),
              silent: true,
              z2: 11
            });
            group.add(symbol);
          }
        });
      }
    },
    axisTickLabel: function (opt, axisModel, group, transformGroup) {
      var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
      var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
      fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
      buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection);
    },
    axisName: function (opt, axisModel, group, transformGroup) {
      var name = retrieve(opt.axisName, axisModel.get('name'));

      if (!name) {
        return;
      }

      var nameLocation = axisModel.get('nameLocation');
      var nameDirection = opt.nameDirection;
      var textStyleModel = axisModel.getModel('nameTextStyle');
      var gap = axisModel.get('nameGap') || 0;
      var extent = axisModel.axis.getExtent();
      var gapSignal = extent[0] > extent[1] ? -1 : 1;
      var pos = [nameLocation === 'start' ? extent[0] - gapSignal * gap : nameLocation === 'end' ? extent[1] + gapSignal * gap : (extent[0] + extent[1]) / 2, isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0];
      var labelLayout;
      var nameRotation = axisModel.get('nameRotate');

      if (nameRotation != null) {
        nameRotation = nameRotation * PI$6 / 180;
      }

      var axisNameAvailableWidth;

      if (isNameLocationCenter(nameLocation)) {
        labelLayout = AxisBuilder.innerTextLayout(opt.rotation, nameRotation != null ? nameRotation : opt.rotation, nameDirection);
      } else {
        labelLayout = endTextLayout(opt.rotation, nameLocation, nameRotation || 0, extent);
        axisNameAvailableWidth = opt.axisNameAvailableWidth;

        if (axisNameAvailableWidth != null) {
          axisNameAvailableWidth = Math.abs(axisNameAvailableWidth / Math.sin(labelLayout.rotation));
          !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null);
        }
      }

      var textFont = textStyleModel.getFont();
      var truncateOpt = axisModel.get('nameTruncate', true) || {};
      var ellipsis = truncateOpt.ellipsis;
      var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth);
      var tooltipOpt = axisModel.get('tooltip', true);
      var mainType = axisModel.mainType;
      var formatterParams = {
        componentType: mainType,
        name: name,
        $vars: ['name']
      };
      formatterParams[mainType + 'Index'] = axisModel.componentIndex;
      var textEl = new ZRText({
        x: pos[0],
        y: pos[1],
        rotation: labelLayout.rotation,
        silent: AxisBuilder.isLabelSilent(axisModel),
        style: createTextStyle(textStyleModel, {
          text: name,
          font: textFont,
          overflow: 'truncate',
          width: maxWidth,
          ellipsis: ellipsis,
          fill: textStyleModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']),
          align: textStyleModel.get('align') || labelLayout.textAlign,
          verticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign
        }),
        z2: 1
      });
      textEl.tooltip = tooltipOpt && tooltipOpt.show ? extend({
        content: name,
        formatter: function () {
          return name;
        },
        formatterParams: formatterParams
      }, tooltipOpt) : null;
      textEl.__fullText = name;
      textEl.anid = 'name';

      if (axisModel.get('triggerEvent')) {
        var eventData = AxisBuilder.makeAxisEventDataBase(axisModel);
        eventData.targetType = 'axisName';
        eventData.name = name;
        getECData(textEl).eventData = eventData;
      }

      transformGroup.add(textEl);
      textEl.updateTransform();
      group.add(textEl);
      textEl.decomposeTransform();
    }
  };

  function endTextLayout(rotation, textPosition, textRotate, extent) {
    var rotationDiff = remRadian(textRotate - rotation);
    var textAlign;
    var textVerticalAlign;
    var inverse = extent[0] > extent[1];
    var onLeft = textPosition === 'start' && !inverse || textPosition !== 'start' && inverse;

    if (isRadianAroundZero(rotationDiff - PI$6 / 2)) {
      textVerticalAlign = onLeft ? 'bottom' : 'top';
      textAlign = 'center';
    } else if (isRadianAroundZero(rotationDiff - PI$6 * 1.5)) {
      textVerticalAlign = onLeft ? 'top' : 'bottom';
      textAlign = 'center';
    } else {
      textVerticalAlign = 'middle';

      if (rotationDiff < PI$6 * 1.5 && rotationDiff > PI$6 / 2) {
        textAlign = onLeft ? 'left' : 'right';
      } else {
        textAlign = onLeft ? 'right' : 'left';
      }
    }

    return {
      rotation: rotationDiff,
      textAlign: textAlign,
      textVerticalAlign: textVerticalAlign
    };
  }

  function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
    if (shouldShowAllLabels(axisModel.axis)) {
      return;
    }

    var showMinLabel = axisModel.get(['axisLabel', 'showMinLabel']);
    var showMaxLabel = axisModel.get(['axisLabel', 'showMaxLabel']);
    labelEls = labelEls || [];
    tickEls = tickEls || [];
    var firstLabel = labelEls[0];
    var nextLabel = labelEls[1];
    var lastLabel = labelEls[labelEls.length - 1];
    var prevLabel = labelEls[labelEls.length - 2];
    var firstTick = tickEls[0];
    var nextTick = tickEls[1];
    var lastTick = tickEls[tickEls.length - 1];
    var prevTick = tickEls[tickEls.length - 2];

    if (showMinLabel === false) {
      ignoreEl(firstLabel);
      ignoreEl(firstTick);
    } else if (isTwoLabelOverlapped(firstLabel, nextLabel)) {
      if (showMinLabel) {
        ignoreEl(nextLabel);
        ignoreEl(nextTick);
      } else {
        ignoreEl(firstLabel);
        ignoreEl(firstTick);
      }
    }

    if (showMaxLabel === false) {
      ignoreEl(lastLabel);
      ignoreEl(lastTick);
    } else if (isTwoLabelOverlapped(prevLabel, lastLabel)) {
      if (showMaxLabel) {
        ignoreEl(prevLabel);
        ignoreEl(prevTick);
      } else {
        ignoreEl(lastLabel);
        ignoreEl(lastTick);
      }
    }
  }

  function ignoreEl(el) {
    el && (el.ignore = true);
  }

  function isTwoLabelOverlapped(current, next) {
    var firstRect = current && current.getBoundingRect().clone();
    var nextRect = next && next.getBoundingRect().clone();

    if (!firstRect || !nextRect) {
      return;
    }

    var mRotationBack = identity([]);
    rotate(mRotationBack, mRotationBack, -current.rotation);
    firstRect.applyTransform(mul$1([], mRotationBack, current.getLocalTransform()));
    nextRect.applyTransform(mul$1([], mRotationBack, next.getLocalTransform()));
    return firstRect.intersect(nextRect);
  }

  function isNameLocationCenter(nameLocation) {
    return nameLocation === 'middle' || nameLocation === 'center';
  }

  function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, anidPrefix) {
    var tickEls = [];
    var pt1 = [];
    var pt2 = [];

    for (var i = 0; i < ticksCoords.length; i++) {
      var tickCoord = ticksCoords[i].coord;
      pt1[0] = tickCoord;
      pt1[1] = 0;
      pt2[0] = tickCoord;
      pt2[1] = tickEndCoord;

      if (tickTransform) {
        applyTransform(pt1, pt1, tickTransform);
        applyTransform(pt2, pt2, tickTransform);
      }

      var tickEl = new Line({
        subPixelOptimize: true,
        shape: {
          x1: pt1[0],
          y1: pt1[1],
          x2: pt2[0],
          y2: pt2[1]
        },
        style: tickLineStyle,
        z2: 2,
        autoBatch: true,
        silent: true
      });
      tickEl.anid = anidPrefix + '_' + ticksCoords[i].tickValue;
      tickEls.push(tickEl);
    }

    return tickEls;
  }

  function buildAxisMajorTicks(group, transformGroup, axisModel, opt) {
    var axis = axisModel.axis;
    var tickModel = axisModel.getModel('axisTick');
    var shown = tickModel.get('show');

    if (shown === 'auto' && opt.handleAutoShown) {
      shown = opt.handleAutoShown('axisTick');
    }

    if (!shown || axis.scale.isBlank()) {
      return;
    }

    var lineStyleModel = tickModel.getModel('lineStyle');
    var tickEndCoord = opt.tickDirection * tickModel.get('length');
    var ticksCoords = axis.getTicksCoords();
    var ticksEls = createTicks(ticksCoords, transformGroup.transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), {
      stroke: axisModel.get(['axisLine', 'lineStyle', 'color'])
    }), 'ticks');

    for (var i = 0; i < ticksEls.length; i++) {
      group.add(ticksEls[i]);
    }

    return ticksEls;
  }

  function buildAxisMinorTicks(group, transformGroup, axisModel, tickDirection) {
    var axis = axisModel.axis;
    var minorTickModel = axisModel.getModel('minorTick');

    if (!minorTickModel.get('show') || axis.scale.isBlank()) {
      return;
    }

    var minorTicksCoords = axis.getMinorTicksCoords();

    if (!minorTicksCoords.length) {
      return;
    }

    var lineStyleModel = minorTickModel.getModel('lineStyle');
    var tickEndCoord = tickDirection * minorTickModel.get('length');
    var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), {
      stroke: axisModel.get(['axisLine', 'lineStyle', 'color'])
    }));

    for (var i = 0; i < minorTicksCoords.length; i++) {
      var minorTicksEls = createTicks(minorTicksCoords[i], transformGroup.transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i);

      for (var k = 0; k < minorTicksEls.length; k++) {
        group.add(minorTicksEls[k]);
      }
    }
  }

  function buildAxisLabel(group, transformGroup, axisModel, opt) {
    var axis = axisModel.axis;
    var show = retrieve(opt.axisLabelShow, axisModel.get(['axisLabel', 'show']));

    if (!show || axis.scale.isBlank()) {
      return;
    }

    var labelModel = axisModel.getModel('axisLabel');
    var labelMargin = labelModel.get('margin');
    var labels = axis.getViewLabels();
    var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI$6 / 180;
    var labelLayout = AxisBuilder.innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
    var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true);
    var labelEls = [];
    var silent = AxisBuilder.isLabelSilent(axisModel);
    var triggerEvent = axisModel.get('triggerEvent');
    each(labels, function (labelItem, index) {
      var tickValue = axis.scale.type === 'ordinal' ? axis.scale.getRawIndex(labelItem.tickValue) : labelItem.tickValue;
      var formattedLabel = labelItem.formattedLabel;
      var rawLabel = labelItem.rawLabel;
      var itemLabelModel = labelModel;

      if (rawCategoryData && rawCategoryData[tickValue]) {
        var rawCategoryItem = rawCategoryData[tickValue];

        if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) {
          itemLabelModel = new Model(rawCategoryItem.textStyle, labelModel, axisModel.ecModel);
        }
      }

      var textColor = itemLabelModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']);
      var tickCoord = axis.dataToCoord(tickValue);
      var textEl = new ZRText({
        x: tickCoord,
        y: opt.labelOffset + opt.labelDirection * labelMargin,
        rotation: labelLayout.rotation,
        silent: silent,
        z2: 10,
        style: createTextStyle(itemLabelModel, {
          text: formattedLabel,
          align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
          verticalAlign: itemLabelModel.getShallow('verticalAlign', true) || itemLabelModel.getShallow('baseline', true) || labelLayout.textVerticalAlign,
          fill: typeof textColor === 'function' ? textColor(axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, index) : textColor
        })
      });
      textEl.anid = 'label_' + tickValue;

      if (triggerEvent) {
        var eventData = AxisBuilder.makeAxisEventDataBase(axisModel);
        eventData.targetType = 'axisLabel';
        eventData.value = rawLabel;
        getECData(textEl).eventData = eventData;
      }

      transformGroup.add(textEl);
      textEl.updateTransform();
      labelEls.push(textEl);
      group.add(textEl);
      textEl.decomposeTransform();
    });
    return labelEls;
  }

  function collect(ecModel, api) {
    var result = {
      axesInfo: {},
      seriesInvolved: false,
      coordSysAxesInfo: {},
      coordSysMap: {}
    };
    collectAxesInfo(result, ecModel, api);
    result.seriesInvolved && collectSeriesInfo(result, ecModel);
    return result;
  }

  function collectAxesInfo(result, ecModel, api) {
    var globalTooltipModel = ecModel.getComponent('tooltip');
    var globalAxisPointerModel = ecModel.getComponent('axisPointer');
    var linksOption = globalAxisPointerModel.get('link', true) || [];
    var linkGroups = [];
    each(api.getCoordinateSystems(), function (coordSys) {
      if (!coordSys.axisPointerEnabled) {
        return;
      }

      var coordSysKey = makeKey(coordSys.model);
      var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {};
      result.coordSysMap[coordSysKey] = coordSys;
      var coordSysModel = coordSys.model;
      var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel);
      each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null));

      if (coordSys.getTooltipAxes && globalTooltipModel && baseTooltipModel.get('show')) {
        var triggerAxis = baseTooltipModel.get('trigger') === 'axis';
        var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross';
        var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis']));

        if (triggerAxis || cross) {
          each(tooltipAxes.baseAxes, curry(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis));
        }

        if (cross) {
          each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false));
        }
      }

      function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) {
        var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel);
        var axisPointerShow = axisPointerModel.get('show');

        if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) {
          return;
        }

        if (triggerTooltip == null) {
          triggerTooltip = axisPointerModel.get('triggerTooltip');
        }

        axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel;
        var snap = axisPointerModel.get('snap');
        var axisKey = makeKey(axis.model);
        var involveSeries = triggerTooltip || snap || axis.type === 'category';
        var axisInfo = result.axesInfo[axisKey] = {
          key: axisKey,
          axis: axis,
          coordSys: coordSys,
          axisPointerModel: axisPointerModel,
          triggerTooltip: triggerTooltip,
          involveSeries: involveSeries,
          snap: snap,
          useHandle: isHandleTrigger(axisPointerModel),
          seriesModels: [],
          linkGroup: null
        };
        axesInfoInCoordSys[axisKey] = axisInfo;
        result.seriesInvolved = result.seriesInvolved || involveSeries;
        var groupIndex = getLinkGroupIndex(linksOption, axis);

        if (groupIndex != null) {
          var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {
            axesInfo: {}
          });
          linkGroup.axesInfo[axisKey] = axisInfo;
          linkGroup.mapper = linksOption[groupIndex].mapper;
          axisInfo.linkGroup = linkGroup;
        }
      }
    });
  }

  function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) {
    var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer');
    var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z'];
    var volatileOption = {};
    each(fields, function (field) {
      volatileOption[field] = clone(tooltipAxisPointerModel.get(field));
    });
    volatileOption.snap = axis.type !== 'category' && !!triggerTooltip;

    if (tooltipAxisPointerModel.get('type') === 'cross') {
      volatileOption.type = 'line';
    }

    var labelOption = volatileOption.label || (volatileOption.label = {});
    labelOption.show == null && (labelOption.show = false);

    if (fromTooltip === 'cross') {
      var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']);
      labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true;

      if (!triggerTooltip) {
        var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle');
        crossStyle && defaults(labelOption, crossStyle.textStyle);
      }
    }

    return axis.model.getModel('axisPointer', new Model(volatileOption, globalAxisPointerModel, ecModel));
  }

  function collectSeriesInfo(result, ecModel) {
    ecModel.eachSeries(function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true);
      var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true);

      if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) {
        return;
      }

      each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) {
        var axis = axisInfo.axis;

        if (coordSys.getAxis(axis.dim) === axis) {
          axisInfo.seriesModels.push(seriesModel);
          axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0);
          axisInfo.seriesDataCount += seriesModel.getData().count();
        }
      });
    });
  }

  function getLinkGroupIndex(linksOption, axis) {
    var axisModel = axis.model;
    var dim = axis.dim;

    for (var i = 0; i < linksOption.length; i++) {
      var linkOption = linksOption[i] || {};

      if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) {
        return i;
      }
    }
  }

  function checkPropInLink(linkPropValue, axisPropValue) {
    return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue;
  }

  function fixValue(axisModel) {
    var axisInfo = getAxisInfo(axisModel);

    if (!axisInfo) {
      return;
    }

    var axisPointerModel = axisInfo.axisPointerModel;
    var scale = axisInfo.axis.scale;
    var option = axisPointerModel.option;
    var status = axisPointerModel.get('status');
    var value = axisPointerModel.get('value');

    if (value != null) {
      value = scale.parse(value);
    }

    var useHandle = isHandleTrigger(axisPointerModel);

    if (status == null) {
      option.status = useHandle ? 'show' : 'hide';
    }

    var extent = scale.getExtent().slice();
    extent[0] > extent[1] && extent.reverse();

    if (value == null || value > extent[1]) {
      value = extent[1];
    }

    if (value < extent[0]) {
      value = extent[0];
    }

    option.value = value;

    if (useHandle) {
      option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show';
    }
  }

  function getAxisInfo(axisModel) {
    var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo;
    return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)];
  }

  function getAxisPointerModel(axisModel) {
    var axisInfo = getAxisInfo(axisModel);
    return axisInfo && axisInfo.axisPointerModel;
  }

  function isHandleTrigger(axisPointerModel) {
    return !!axisPointerModel.get(['handle', 'show']);
  }

  function makeKey(model) {
    return model.type + '||' + model.id;
  }

  var axisPointerClazz = {};

  var AxisView = function (_super) {
    __extends(AxisView, _super);

    function AxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = AxisView.type;
      return _this;
    }

    AxisView.prototype.render = function (axisModel, ecModel, api, payload) {
      this.axisPointerClass && fixValue(axisModel);

      _super.prototype.render.apply(this, arguments);

      this._doUpdateAxisPointerClass(axisModel, api, true);
    };

    AxisView.prototype.updateAxisPointer = function (axisModel, ecModel, api, payload) {
      this._doUpdateAxisPointerClass(axisModel, api, false);
    };

    AxisView.prototype.remove = function (ecModel, api) {
      var axisPointer = this._axisPointer;
      axisPointer && axisPointer.remove(api);
    };

    AxisView.prototype.dispose = function (ecModel, api) {
      this._disposeAxisPointer(api);

      _super.prototype.dispose.apply(this, arguments);
    };

    AxisView.prototype._doUpdateAxisPointerClass = function (axisModel, api, forceRender) {
      var Clazz = AxisView.getAxisPointerClass(this.axisPointerClass);

      if (!Clazz) {
        return;
      }

      var axisPointerModel = getAxisPointerModel(axisModel);
      axisPointerModel ? (this._axisPointer || (this._axisPointer = new Clazz())).render(axisModel, axisPointerModel, api, forceRender) : this._disposeAxisPointer(api);
    };

    AxisView.prototype._disposeAxisPointer = function (api) {
      this._axisPointer && this._axisPointer.dispose(api);
      this._axisPointer = null;
    };

    AxisView.registerAxisPointerClass = function (type, clazz) {
      if (true) {
        if (axisPointerClazz[type]) {
          throw new Error('axisPointer ' + type + ' exists');
        }
      }

      axisPointerClazz[type] = clazz;
    };

    AxisView.getAxisPointerClass = function (type) {
      return type && axisPointerClazz[type];
    };

    AxisView.type = 'axis';
    return AxisView;
  }(ComponentView);

  function layout$1(gridModel, axisModel, opt) {
    opt = opt || {};
    var grid = gridModel.coordinateSystem;
    var axis = axisModel.axis;
    var layout = {};
    var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0];
    var rawAxisPosition = axis.position;
    var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition;
    var axisDim = axis.dim;
    var rect = grid.getRect();
    var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
    var idx = {
      left: 0,
      right: 1,
      top: 0,
      bottom: 1,
      onZero: 2
    };
    var axisOffset = axisModel.get('offset') || 0;
    var posBound = axisDim === 'x' ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] : [rectBound[0] - axisOffset, rectBound[1] + axisOffset];

    if (otherAxisOnZeroOf) {
      var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0));
      posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]);
    }

    layout.position = [axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]];
    layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1);
    var dirMap = {
      top: -1,
      bottom: 1,
      left: -1,
      right: 1
    };
    layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition];
    layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0;

    if (axisModel.get(['axisTick', 'inside'])) {
      layout.tickDirection = -layout.tickDirection;
    }

    if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) {
      layout.labelDirection = -layout.labelDirection;
    }

    var labelRotate = axisModel.get(['axisLabel', 'rotate']);
    layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate;
    layout.z2 = 1;
    return layout;
  }

  function isCartesian2DSeries(seriesModel) {
    return seriesModel.get('coordinateSystem') === 'cartesian2d';
  }

  function findAxisModels(seriesModel) {
    var axisModelMap = {
      xAxisModel: null,
      yAxisModel: null
    };
    each(axisModelMap, function (v, key) {
      var axisType = key.replace(/Model$/, '');
      var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0];

      if (true) {
        if (!axisModel) {
          throw new Error(axisType + ' "' + retrieve3(seriesModel.get(axisType + 'Index'), seriesModel.get(axisType + 'Id'), 0) + '" not found');
        }
      }

      axisModelMap[key] = axisModel;
    });
    return axisModelMap;
  }

  var inner$5 = makeInner();

  function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
    var axis = axisModel.axis;

    if (axis.scale.isBlank()) {
      return;
    }

    var splitAreaModel = axisModel.getModel('splitArea');
    var areaStyleModel = splitAreaModel.getModel('areaStyle');
    var areaColors = areaStyleModel.get('color');
    var gridRect = gridModel.coordinateSystem.getRect();
    var ticksCoords = axis.getTicksCoords({
      tickModel: splitAreaModel,
      clamp: true
    });

    if (!ticksCoords.length) {
      return;
    }

    var areaColorsLen = areaColors.length;
    var lastSplitAreaColors = inner$5(axisView).splitAreaColors;
    var newSplitAreaColors = createHashMap();
    var colorIndex = 0;

    if (lastSplitAreaColors) {
      for (var i = 0; i < ticksCoords.length; i++) {
        var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);

        if (cIndex != null) {
          colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
          break;
        }
      }
    }

    var prev = axis.toGlobalCoord(ticksCoords[0].coord);
    var areaStyle = areaStyleModel.getAreaStyle();
    areaColors = isArray(areaColors) ? areaColors : [areaColors];

    for (var i = 1; i < ticksCoords.length; i++) {
      var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
      var x = void 0;
      var y = void 0;
      var width = void 0;
      var height = void 0;

      if (axis.isHorizontal()) {
        x = prev;
        y = gridRect.y;
        width = tickCoord - x;
        height = gridRect.height;
        prev = x + width;
      } else {
        x = gridRect.x;
        y = prev;
        width = gridRect.width;
        height = tickCoord - y;
        prev = y + height;
      }

      var tickValue = ticksCoords[i - 1].tickValue;
      tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
      axisGroup.add(new Rect({
        anid: tickValue != null ? 'area_' + tickValue : null,
        shape: {
          x: x,
          y: y,
          width: width,
          height: height
        },
        style: defaults({
          fill: areaColors[colorIndex]
        }, areaStyle),
        autoBatch: true,
        silent: true
      }));
      colorIndex = (colorIndex + 1) % areaColorsLen;
    }

    inner$5(axisView).splitAreaColors = newSplitAreaColors;
  }

  function rectCoordAxisHandleRemove(axisView) {
    inner$5(axisView).splitAreaColors = null;
  }

  var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
  var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine'];

  var CartesianAxisView = function (_super) {
    __extends(CartesianAxisView, _super);

    function CartesianAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CartesianAxisView.type;
      _this.axisPointerClass = 'CartesianAxisPointer';
      return _this;
    }

    CartesianAxisView.prototype.render = function (axisModel, ecModel, api, payload) {
      this.group.removeAll();
      var oldAxisGroup = this._axisGroup;
      this._axisGroup = new Group();
      this.group.add(this._axisGroup);

      if (!axisModel.get('show')) {
        return;
      }

      var gridModel = axisModel.getCoordSysModel();
      var layout = layout$1(gridModel, axisModel);
      var axisBuilder = new AxisBuilder(axisModel, extend({
        handleAutoShown: function (elementType) {
          var cartesians = gridModel.coordinateSystem.getCartesians();

          for (var i = 0; i < cartesians.length; i++) {
            var otherAxisType = cartesians[i].getOtherAxis(axisModel.axis).type;

            if (otherAxisType === 'value' || otherAxisType === 'log') {
              return true;
            }
          }

          return false;
        }
      }, layout));
      each(axisBuilderAttrs, axisBuilder.add, axisBuilder);

      this._axisGroup.add(axisBuilder.getGroup());

      each(selfBuilderAttrs, function (name) {
        if (axisModel.get([name, 'show'])) {
          axisElementBuilders[name](this, this._axisGroup, axisModel, gridModel);
        }
      }, this);
      groupTransition(oldAxisGroup, this._axisGroup, axisModel);

      _super.prototype.render.call(this, axisModel, ecModel, api, payload);
    };

    CartesianAxisView.prototype.remove = function () {
      rectCoordAxisHandleRemove(this);
    };

    CartesianAxisView.type = 'cartesianAxis';
    return CartesianAxisView;
  }(AxisView);

  var axisElementBuilders = {
    splitLine: function (axisView, axisGroup, axisModel, gridModel) {
      var axis = axisModel.axis;

      if (axis.scale.isBlank()) {
        return;
      }

      var splitLineModel = axisModel.getModel('splitLine');
      var lineStyleModel = splitLineModel.getModel('lineStyle');
      var lineColors = lineStyleModel.get('color');
      lineColors = isArray(lineColors) ? lineColors : [lineColors];
      var gridRect = gridModel.coordinateSystem.getRect();
      var isHorizontal = axis.isHorizontal();
      var lineCount = 0;
      var ticksCoords = axis.getTicksCoords({
        tickModel: splitLineModel
      });
      var p1 = [];
      var p2 = [];
      var lineStyle = lineStyleModel.getLineStyle();

      for (var i = 0; i < ticksCoords.length; i++) {
        var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);

        if (isHorizontal) {
          p1[0] = tickCoord;
          p1[1] = gridRect.y;
          p2[0] = tickCoord;
          p2[1] = gridRect.y + gridRect.height;
        } else {
          p1[0] = gridRect.x;
          p1[1] = tickCoord;
          p2[0] = gridRect.x + gridRect.width;
          p2[1] = tickCoord;
        }

        var colorIndex = lineCount++ % lineColors.length;
        var tickValue = ticksCoords[i].tickValue;
        axisGroup.add(new Line({
          anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null,
          subPixelOptimize: true,
          autoBatch: true,
          shape: {
            x1: p1[0],
            y1: p1[1],
            x2: p2[0],
            y2: p2[1]
          },
          style: defaults({
            stroke: lineColors[colorIndex]
          }, lineStyle),
          silent: true
        }));
      }
    },
    minorSplitLine: function (axisView, axisGroup, axisModel, gridModel) {
      var axis = axisModel.axis;
      var minorSplitLineModel = axisModel.getModel('minorSplitLine');
      var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
      var gridRect = gridModel.coordinateSystem.getRect();
      var isHorizontal = axis.isHorizontal();
      var minorTicksCoords = axis.getMinorTicksCoords();

      if (!minorTicksCoords.length) {
        return;
      }

      var p1 = [];
      var p2 = [];
      var lineStyle = lineStyleModel.getLineStyle();

      for (var i = 0; i < minorTicksCoords.length; i++) {
        for (var k = 0; k < minorTicksCoords[i].length; k++) {
          var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord);

          if (isHorizontal) {
            p1[0] = tickCoord;
            p1[1] = gridRect.y;
            p2[0] = tickCoord;
            p2[1] = gridRect.y + gridRect.height;
          } else {
            p1[0] = gridRect.x;
            p1[1] = tickCoord;
            p2[0] = gridRect.x + gridRect.width;
            p2[1] = tickCoord;
          }

          axisGroup.add(new Line({
            anid: 'minor_line_' + minorTicksCoords[i][k].tickValue,
            subPixelOptimize: true,
            autoBatch: true,
            shape: {
              x1: p1[0],
              y1: p1[1],
              x2: p2[0],
              y2: p2[1]
            },
            style: lineStyle,
            silent: true
          }));
        }
      }
    },
    splitArea: function (axisView, axisGroup, axisModel, gridModel) {
      rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel);
    }
  };

  var CartesianXAxisView = function (_super) {
    __extends(CartesianXAxisView, _super);

    function CartesianXAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CartesianXAxisView.type;
      return _this;
    }

    CartesianXAxisView.type = 'xAxis';
    return CartesianXAxisView;
  }(CartesianAxisView);

  var CartesianYAxisView = function (_super) {
    __extends(CartesianYAxisView, _super);

    function CartesianYAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CartesianXAxisView.type;
      return _this;
    }

    CartesianYAxisView.type = 'yAxis';
    return CartesianYAxisView;
  }(CartesianAxisView);

  ComponentView.registerClass(CartesianXAxisView);
  ComponentView.registerClass(CartesianYAxisView);
  registerProcessor(PRIORITY.PROCESSOR.FILTER + 10, {
    getTargetSeries: function (ecModel) {
      var seriesModelMap = createHashMap();
      ecModel.eachSeries(function (seriesModel) {
        isCartesian2DSeries(seriesModel) && seriesModelMap.set(seriesModel.uid, seriesModel);
      });
      return seriesModelMap;
    },
    overallReset: function (ecModel, api) {
      var seriesRecords = [];
      var axisRecordMap = createHashMap();
      prepareDataExtentOnAxis(ecModel, axisRecordMap, seriesRecords);
      calculateFilteredExtent(axisRecordMap, seriesRecords);
      shrinkAxisExtent(axisRecordMap);
    }
  });

  function prepareDataExtentOnAxis(ecModel, axisRecordMap, seriesRecords) {
    ecModel.eachSeries(function (seriesModel) {
      if (!isCartesian2DSeries(seriesModel)) {
        return;
      }

      var axesModelMap = findAxisModels(seriesModel);
      var xAxisModel = axesModelMap.xAxisModel;
      var yAxisModel = axesModelMap.yAxisModel;
      var xAxis = xAxisModel.axis;
      var yAxis = yAxisModel.axis;
      var xRawExtentInfo = xAxis.scale.rawExtentInfo;
      var yRawExtentInfo = yAxis.scale.rawExtentInfo;
      var data = seriesModel.getData();

      if (xRawExtentInfo && xRawExtentInfo.frozen || yRawExtentInfo && yRawExtentInfo.frozen) {
        return;
      }

      seriesRecords.push({
        seriesModel: seriesModel,
        xAxisModel: xAxisModel,
        yAxisModel: yAxisModel
      });
      unionAxisExtentFromData(prepareAxisRecord(axisRecordMap, xAxisModel).condExtent, data, xAxis.dim);
      unionAxisExtentFromData(prepareAxisRecord(axisRecordMap, yAxisModel).condExtent, data, yAxis.dim);
    });
  }

  function calculateFilteredExtent(axisRecordMap, seriesRecords) {
    each(seriesRecords, function (seriesRecord) {
      var xAxisModel = seriesRecord.xAxisModel;
      var yAxisModel = seriesRecord.yAxisModel;
      var xAxis = xAxisModel.axis;
      var yAxis = yAxisModel.axis;
      var xAxisRecord = prepareAxisRecord(axisRecordMap, xAxisModel);
      var yAxisRecord = prepareAxisRecord(axisRecordMap, yAxisModel);
      xAxisRecord.rawExtentInfo = ensureScaleRawExtentInfo(xAxis.scale, xAxisModel, xAxisRecord.condExtent);
      yAxisRecord.rawExtentInfo = ensureScaleRawExtentInfo(yAxis.scale, yAxisModel, yAxisRecord.condExtent);
      xAxisRecord.rawExtentResult = xAxisRecord.rawExtentInfo.calculate();
      yAxisRecord.rawExtentResult = yAxisRecord.rawExtentInfo.calculate();
      var data = seriesRecord.seriesModel.getData();
      var condDimMap = {};
      var tarDimMap = {};
      var condAxis;
      var tarAxisRecord;

      function addCondition(axis, axisRecord) {
        var condExtent = axisRecord.condExtent;
        var rawExtentResult = axisRecord.rawExtentResult;

        if (axis.type === 'category' && (condExtent[0] < rawExtentResult.min || rawExtentResult.max < condExtent[1])) {
          each(getDataDimensionsOnAxis(data, axis.dim), function (dataDim) {
            if (!hasOwn(condDimMap, dataDim)) {
              condDimMap[dataDim] = true;
              condAxis = axis;
            }
          });
        }
      }

      function addTarget(axis, axisRecord) {
        var rawExtentResult = axisRecord.rawExtentResult;

        if (axis.type !== 'category' && (!rawExtentResult.minFixed || !rawExtentResult.maxFixed)) {
          each(getDataDimensionsOnAxis(data, axis.dim), function (dataDim) {
            if (!hasOwn(condDimMap, dataDim) && !hasOwn(tarDimMap, dataDim)) {
              tarDimMap[dataDim] = true;
              tarAxisRecord = axisRecord;
            }
          });
        }
      }

      addCondition(xAxis, xAxisRecord);
      addCondition(yAxis, yAxisRecord);
      addTarget(xAxis, xAxisRecord);
      addTarget(yAxis, yAxisRecord);
      var condDims = keys(condDimMap);
      var tarDims = keys(tarDimMap);
      var tarDimExtents = map(tarDims, function () {
        return initExtent();
      });
      var condDimsLen = condDims.length;
      var tarDimsLen = tarDims.length;

      if (!condDimsLen || !tarDimsLen) {
        return;
      }

      var singleCondDim = condDimsLen === 1 ? condDims[0] : null;
      var singleTarDim = tarDimsLen === 1 ? tarDims[0] : null;
      var dataLen = data.count();

      if (singleCondDim && singleTarDim) {
        for (var dataIdx = 0; dataIdx < dataLen; dataIdx++) {
          var condVal = data.get(singleCondDim, dataIdx);

          if (condAxis.scale.isInExtentRange(condVal)) {
            unionExtent(tarDimExtents[0], data.get(singleTarDim, dataIdx));
          }
        }
      } else {
        for (var dataIdx = 0; dataIdx < dataLen; dataIdx++) {
          for (var j = 0; j < condDimsLen; j++) {
            var condVal = data.get(condDims[j], dataIdx);

            if (condAxis.scale.isInExtentRange(condVal)) {
              for (var k = 0; k < tarDimsLen; k++) {
                unionExtent(tarDimExtents[k], data.get(tarDims[k], dataIdx));
              }

              break;
            }
          }
        }
      }

      each(tarDimExtents, function (tarDimExtent, i) {
        var dim = tarDims[i];
        data.setApproximateExtent(tarDimExtent, dim);
        var tarAxisExtent = tarAxisRecord.tarExtent = tarAxisRecord.tarExtent || initExtent();
        unionExtent(tarAxisExtent, tarDimExtent[0]);
        unionExtent(tarAxisExtent, tarDimExtent[1]);
      });
    });
  }

  function shrinkAxisExtent(axisRecordMap) {
    axisRecordMap.each(function (axisRecord) {
      var tarAxisExtent = axisRecord.tarExtent;

      if (tarAxisExtent) {
        var rawExtentResult = axisRecord.rawExtentResult;
        var rawExtentInfo = axisRecord.rawExtentInfo;

        if (!rawExtentResult.minFixed && tarAxisExtent[0] > rawExtentResult.min) {
          rawExtentInfo.modifyDataMinMax('min', tarAxisExtent[0]);
        }

        if (!rawExtentResult.maxFixed && tarAxisExtent[1] < rawExtentResult.max) {
          rawExtentInfo.modifyDataMinMax('max', tarAxisExtent[1]);
        }
      }
    });
  }

  function prepareAxisRecord(axisRecordMap, axisModel) {
    return axisRecordMap.get(axisModel.uid) || axisRecordMap.set(axisModel.uid, {
      condExtent: initExtent()
    });
  }

  function initExtent() {
    return [Infinity, -Infinity];
  }

  function unionExtent(extent, val) {
    val < extent[0] && (extent[0] = val);
    val > extent[1] && (extent[1] = val);
  }

  var GridModel = function (_super) {
    __extends(GridModel, _super);

    function GridModel() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    GridModel.type = 'grid';
    GridModel.dependencies = ['xAxis', 'yAxis'];
    GridModel.layoutMode = 'box';
    GridModel.defaultOption = {
      show: false,
      zlevel: 0,
      z: 0,
      left: '10%',
      top: 60,
      right: '10%',
      bottom: 70,
      containLabel: false,
      backgroundColor: 'rgba(0,0,0,0)',
      borderWidth: 1,
      borderColor: '#ccc'
    };
    return GridModel;
  }(ComponentModel);

  var GridView = function (_super) {
    __extends(GridView, _super);

    function GridView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'grid';
      return _this;
    }

    GridView.prototype.render = function (gridModel, ecModel) {
      this.group.removeAll();

      if (gridModel.get('show')) {
        this.group.add(new Rect({
          shape: gridModel.coordinateSystem.getRect(),
          style: defaults({
            fill: gridModel.get('backgroundColor')
          }, gridModel.getItemStyle()),
          silent: true,
          z2: -1
        }));
      }
    };

    GridView.type = 'grid';
    return GridView;
  }(ComponentView);

  ComponentView.registerClass(GridView);
  ComponentModel.registerClass(GridModel);
  registerPreprocessor(function (option) {
    if (option.xAxis && option.yAxis && !option.grid) {
      option.grid = {};
    }
  });
  registerLayout(pointsLayout('line', true));
  registerProcessor(PRIORITY.PROCESSOR.STATISTIC, dataSample('line'));

  var Cartesian = function () {
    function Cartesian(name) {
      this.type = 'cartesian';
      this._dimList = [];
      this._axes = {};
      this.name = name || '';
    }

    Cartesian.prototype.getAxis = function (dim) {
      return this._axes[dim];
    };

    Cartesian.prototype.getAxes = function () {
      return map(this._dimList, function (dim) {
        return this._axes[dim];
      }, this);
    };

    Cartesian.prototype.getAxesByScale = function (scaleType) {
      scaleType = scaleType.toLowerCase();
      return filter(this.getAxes(), function (axis) {
        return axis.scale.type === scaleType;
      });
    };

    Cartesian.prototype.addAxis = function (axis) {
      var dim = axis.dim;
      this._axes[dim] = axis;

      this._dimList.push(dim);
    };

    return Cartesian;
  }();

  var cartesian2DDimensions = ['x', 'y'];

  function canCalculateAffineTransform(scale) {
    return scale.type === 'interval' || scale.type === 'time';
  }

  var Cartesian2D = function (_super) {
    __extends(Cartesian2D, _super);

    function Cartesian2D() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'cartesian2d';
      _this.dimensions = cartesian2DDimensions;
      return _this;
    }

    Cartesian2D.prototype.calcAffineTransform = function () {
      this._transform = this._invTransform = null;
      var xAxisScale = this.getAxis('x').scale;
      var yAxisScale = this.getAxis('y').scale;

      if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) {
        return;
      }

      var xScaleExtent = xAxisScale.getExtent();
      var yScaleExtent = yAxisScale.getExtent();
      var start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]);
      var end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]);
      var xScaleSpan = xScaleExtent[1] - xScaleExtent[0];
      var yScaleSpan = yScaleExtent[1] - yScaleExtent[0];

      if (!xScaleSpan || !yScaleSpan) {
        return;
      }

      var scaleX = (end[0] - start[0]) / xScaleSpan;
      var scaleY = (end[1] - start[1]) / yScaleSpan;
      var translateX = start[0] - xScaleExtent[0] * scaleX;
      var translateY = start[1] - yScaleExtent[0] * scaleY;
      var m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY];
      this._invTransform = invert([], m);
    };

    Cartesian2D.prototype.getBaseAxis = function () {
      return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x');
    };

    Cartesian2D.prototype.containPoint = function (point) {
      var axisX = this.getAxis('x');
      var axisY = this.getAxis('y');
      return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1]));
    };

    Cartesian2D.prototype.containData = function (data) {
      return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]);
    };

    Cartesian2D.prototype.dataToPoint = function (data, reserved, out) {
      out = out || [];
      var xVal = data[0];
      var yVal = data[1];

      if (this._transform && xVal != null && isFinite(xVal) && yVal != null && isFinite(yVal)) {
        return applyTransform(out, data, this._transform);
      }

      var xAxis = this.getAxis('x');
      var yAxis = this.getAxis('y');
      out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal));
      out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal));
      return out;
    };

    Cartesian2D.prototype.clampData = function (data, out) {
      var xScale = this.getAxis('x').scale;
      var yScale = this.getAxis('y').scale;
      var xAxisExtent = xScale.getExtent();
      var yAxisExtent = yScale.getExtent();
      var x = xScale.parse(data[0]);
      var y = yScale.parse(data[1]);
      out = out || [];
      out[0] = Math.min(Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1]));
      out[1] = Math.min(Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1]));
      return out;
    };

    Cartesian2D.prototype.pointToData = function (point, out) {
      out = out || [];

      if (this._invTransform) {
        return applyTransform(out, point, this._invTransform);
      }

      var xAxis = this.getAxis('x');
      var yAxis = this.getAxis('y');
      out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]));
      out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]));
      return out;
    };

    Cartesian2D.prototype.getOtherAxis = function (axis) {
      return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
    };

    Cartesian2D.prototype.getArea = function () {
      var xExtent = this.getAxis('x').getGlobalExtent();
      var yExtent = this.getAxis('y').getGlobalExtent();
      var x = Math.min(xExtent[0], xExtent[1]);
      var y = Math.min(yExtent[0], yExtent[1]);
      var width = Math.max(xExtent[0], xExtent[1]) - x;
      var height = Math.max(yExtent[0], yExtent[1]) - y;
      return new BoundingRect(x, y, width, height);
    };

    return Cartesian2D;
  }(Cartesian);

  var Axis2D = function (_super) {
    __extends(Axis2D, _super);

    function Axis2D(dim, scale, coordExtent, axisType, position) {
      var _this = _super.call(this, dim, scale, coordExtent) || this;

      _this.index = 0;
      _this.type = axisType || 'value';
      _this.position = position || 'bottom';
      return _this;
    }

    Axis2D.prototype.isHorizontal = function () {
      var position = this.position;
      return position === 'top' || position === 'bottom';
    };

    Axis2D.prototype.getGlobalExtent = function (asc) {
      var ret = this.getExtent();
      ret[0] = this.toGlobalCoord(ret[0]);
      ret[1] = this.toGlobalCoord(ret[1]);
      asc && ret[0] > ret[1] && ret.reverse();
      return ret;
    };

    Axis2D.prototype.pointToData = function (point, clamp) {
      return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp);
    };

    Axis2D.prototype.setCategorySortInfo = function (info) {
      if (this.type !== 'category') {
        return false;
      }

      this.model.option.categorySortInfo = info;
      this.scale.setCategorySortInfo(info);
    };

    return Axis2D;
  }(Axis);

  var Grid = function () {
    function Grid(gridModel, ecModel, api) {
      this.type = 'grid';
      this._coordsMap = {};
      this._coordsList = [];
      this._axesMap = {};
      this._axesList = [];
      this.axisPointerEnabled = true;
      this.dimensions = cartesian2DDimensions;

      this._initCartesian(gridModel, ecModel, api);

      this.model = gridModel;
    }

    Grid.prototype.getRect = function () {
      return this._rect;
    };

    Grid.prototype.update = function (ecModel, api) {
      var axesMap = this._axesMap;

      this._updateScale(ecModel, this.model);

      each(axesMap.x, function (xAxis) {
        niceScaleExtent(xAxis.scale, xAxis.model);
      });
      each(axesMap.y, function (yAxis) {
        niceScaleExtent(yAxis.scale, yAxis.model);
      });
      var onZeroRecords = {};
      each(axesMap.x, function (xAxis) {
        fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords);
      });
      each(axesMap.y, function (yAxis) {
        fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords);
      });
      this.resize(this.model, api);
    };

    Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) {
      var boxLayoutParams = gridModel.getBoxLayoutParams();
      var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel');
      var gridRect = getLayoutRect(boxLayoutParams, {
        width: api.getWidth(),
        height: api.getHeight()
      });
      this._rect = gridRect;
      var axesList = this._axesList;
      adjustAxes();

      if (isContainLabel) {
        each(axesList, function (axis) {
          if (!axis.model.get(['axisLabel', 'inside'])) {
            var labelUnionRect = estimateLabelUnionRect(axis);

            if (labelUnionRect) {
              var dim = axis.isHorizontal() ? 'height' : 'width';
              var margin = axis.model.get(['axisLabel', 'margin']);
              gridRect[dim] -= labelUnionRect[dim] + margin;

              if (axis.position === 'top') {
                gridRect.y += labelUnionRect.height + margin;
              } else if (axis.position === 'left') {
                gridRect.x += labelUnionRect.width + margin;
              }
            }
          }
        });
        adjustAxes();
      }

      each(this._coordsList, function (coord) {
        coord.calcAffineTransform();
      });

      function adjustAxes() {
        each(axesList, function (axis) {
          var isHorizontal = axis.isHorizontal();
          var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height];
          var idx = axis.inverse ? 1 : 0;
          axis.setExtent(extent[idx], extent[1 - idx]);
          updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y);
        });
      }
    };

    Grid.prototype.getAxis = function (dim, axisIndex) {
      var axesMapOnDim = this._axesMap[dim];

      if (axesMapOnDim != null) {
        return axesMapOnDim[axisIndex || 0];
      }
    };

    Grid.prototype.getAxes = function () {
      return this._axesList.slice();
    };

    Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) {
      if (xAxisIndex != null && yAxisIndex != null) {
        var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
        return this._coordsMap[key];
      }

      if (isObject(xAxisIndex)) {
        yAxisIndex = xAxisIndex.yAxisIndex;
        xAxisIndex = xAxisIndex.xAxisIndex;
      }

      for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) {
        if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) {
          return coordList[i];
        }
      }
    };

    Grid.prototype.getCartesians = function () {
      return this._coordsList.slice();
    };

    Grid.prototype.convertToPixel = function (ecModel, finder, value) {
      var target = this._findConvertTarget(finder);

      return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null;
    };

    Grid.prototype.convertFromPixel = function (ecModel, finder, value) {
      var target = this._findConvertTarget(finder);

      return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null;
    };

    Grid.prototype._findConvertTarget = function (finder) {
      var seriesModel = finder.seriesModel;
      var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0];
      var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0];
      var gridModel = finder.gridModel;
      var coordsList = this._coordsList;
      var cartesian;
      var axis;

      if (seriesModel) {
        cartesian = seriesModel.coordinateSystem;
        indexOf(coordsList, cartesian) < 0 && (cartesian = null);
      } else if (xAxisModel && yAxisModel) {
        cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
      } else if (xAxisModel) {
        axis = this.getAxis('x', xAxisModel.componentIndex);
      } else if (yAxisModel) {
        axis = this.getAxis('y', yAxisModel.componentIndex);
      } else if (gridModel) {
        var grid = gridModel.coordinateSystem;

        if (grid === this) {
          cartesian = this._coordsList[0];
        }
      }

      return {
        cartesian: cartesian,
        axis: axis
      };
    };

    Grid.prototype.containPoint = function (point) {
      var coord = this._coordsList[0];

      if (coord) {
        return coord.containPoint(point);
      }
    };

    Grid.prototype._initCartesian = function (gridModel, ecModel, api) {
      var _this = this;

      var grid = this;
      var axisPositionUsed = {
        left: false,
        right: false,
        top: false,
        bottom: false
      };
      var axesMap = {
        x: {},
        y: {}
      };
      var axesCount = {
        x: 0,
        y: 0
      };
      ecModel.eachComponent('xAxis', createAxisCreator('x'), this);
      ecModel.eachComponent('yAxis', createAxisCreator('y'), this);

      if (!axesCount.x || !axesCount.y) {
        this._axesMap = {};
        this._axesList = [];
        return;
      }

      this._axesMap = axesMap;
      each(axesMap.x, function (xAxis, xAxisIndex) {
        each(axesMap.y, function (yAxis, yAxisIndex) {
          var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
          var cartesian = new Cartesian2D(key);
          cartesian.master = _this;
          cartesian.model = gridModel;
          _this._coordsMap[key] = cartesian;

          _this._coordsList.push(cartesian);

          cartesian.addAxis(xAxis);
          cartesian.addAxis(yAxis);
        });
      });

      function createAxisCreator(dimName) {
        return function (axisModel, idx) {
          if (!isAxisUsedInTheGrid(axisModel, gridModel)) {
            return;
          }

          var axisPosition = axisModel.get('position');

          if (dimName === 'x') {
            if (axisPosition !== 'top' && axisPosition !== 'bottom') {
              axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom';
            }
          } else {
            if (axisPosition !== 'left' && axisPosition !== 'right') {
              axisPosition = axisPositionUsed.left ? 'right' : 'left';
            }
          }

          axisPositionUsed[axisPosition] = true;
          var axis = new Axis2D(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition);
          var isCategory = axis.type === 'category';
          axis.onBand = isCategory && axisModel.get('boundaryGap');
          axis.inverse = axisModel.get('inverse');
          axisModel.axis = axis;
          axis.model = axisModel;
          axis.grid = grid;
          axis.index = idx;

          grid._axesList.push(axis);

          axesMap[dimName][idx] = axis;
          axesCount[dimName]++;
        };
      }
    };

    Grid.prototype._updateScale = function (ecModel, gridModel) {
      each(this._axesList, function (axis) {
        axis.scale.setExtent(Infinity, -Infinity);

        if (axis.type === 'category') {
          var categorySortInfo = axis.model.get('categorySortInfo');
          axis.scale.setCategorySortInfo(categorySortInfo);
        }
      });
      ecModel.eachSeries(function (seriesModel) {
        if (isCartesian2DSeries(seriesModel)) {
          var axesModelMap = findAxisModels(seriesModel);
          var xAxisModel = axesModelMap.xAxisModel;
          var yAxisModel = axesModelMap.yAxisModel;

          if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) {
            return;
          }

          var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
          var data = seriesModel.getData();
          var xAxis = cartesian.getAxis('x');
          var yAxis = cartesian.getAxis('y');

          if (data.type === 'list') {
            unionExtent(data, xAxis);
            unionExtent(data, yAxis);
          }
        }
      }, this);

      function unionExtent(data, axis) {
        each(getDataDimensionsOnAxis(data, axis.dim), function (dim) {
          axis.scale.unionExtentFromData(data, dim);
        });
      }
    };

    Grid.prototype.getTooltipAxes = function (dim) {
      var baseAxes = [];
      var otherAxes = [];
      each(this.getCartesians(), function (cartesian) {
        var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis();
        var otherAxis = cartesian.getOtherAxis(baseAxis);
        indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
        indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
      });
      return {
        baseAxes: baseAxes,
        otherAxes: otherAxes
      };
    };

    Grid.create = function (ecModel, api) {
      var grids = [];
      ecModel.eachComponent('grid', function (gridModel, idx) {
        var grid = new Grid(gridModel, ecModel, api);
        grid.name = 'grid_' + idx;
        grid.resize(gridModel, api, true);
        gridModel.coordinateSystem = grid;
        grids.push(grid);
      });
      ecModel.eachSeries(function (seriesModel) {
        if (!isCartesian2DSeries(seriesModel)) {
          return;
        }

        var axesModelMap = findAxisModels(seriesModel);
        var xAxisModel = axesModelMap.xAxisModel;
        var yAxisModel = axesModelMap.yAxisModel;
        var gridModel = xAxisModel.getCoordSysModel();

        if (true) {
          if (!gridModel) {
            throw new Error('Grid "' + retrieve3(xAxisModel.get('gridIndex'), xAxisModel.get('gridId'), 0) + '" not found');
          }

          if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) {
            throw new Error('xAxis and yAxis must use the same grid');
          }
        }

        var grid = gridModel.coordinateSystem;
        seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
      });
      return grids;
    };

    Grid.dimensions = cartesian2DDimensions;
    return Grid;
  }();

  function isAxisUsedInTheGrid(axisModel, gridModel) {
    return axisModel.getCoordSysModel() === gridModel;
  }

  function fixAxisOnZero(axesMap, otherAxisDim, axis, onZeroRecords) {
    axis.getAxesOnZeroOf = function () {
      return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : [];
    };

    var otherAxes = axesMap[otherAxisDim];
    var otherAxisOnZeroOf;
    var axisModel = axis.model;
    var onZero = axisModel.get(['axisLine', 'onZero']);
    var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']);

    if (!onZero) {
      return;
    }

    if (onZeroAxisIndex != null) {
      if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) {
        otherAxisOnZeroOf = otherAxes[onZeroAxisIndex];
      }
    } else {
      for (var idx in otherAxes) {
        if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) {
          otherAxisOnZeroOf = otherAxes[idx];
          break;
        }
      }
    }

    if (otherAxisOnZeroOf) {
      onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true;
    }

    function getOnZeroRecordKey(axis) {
      return axis.dim + '_' + axis.index;
    }
  }

  function canOnZeroToAxis(axis) {
    return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis);
  }

  function updateAxisTransform(axis, coordBase) {
    var axisExtent = axis.getExtent();
    var axisExtentSum = axisExtent[0] + axisExtent[1];
    axis.toGlobalCoord = axis.dim === 'x' ? function (coord) {
      return coord + coordBase;
    } : function (coord) {
      return axisExtentSum - coord + coordBase;
    };
    axis.toLocalCoord = axis.dim === 'x' ? function (coord) {
      return coord - coordBase;
    } : function (coord) {
      return axisExtentSum - coord + coordBase;
    };
  }

  CoordinateSystemManager.register('cartesian2d', Grid);

  var BaseBarSeriesModel = function (_super) {
    __extends(BaseBarSeriesModel, _super);

    function BaseBarSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BaseBarSeriesModel.type;
      return _this;
    }

    BaseBarSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this, {
        useEncodeDefaulter: true
      });
    };

    BaseBarSeriesModel.prototype.getMarkerPosition = function (value) {
      var coordSys = this.coordinateSystem;

      if (coordSys) {
        var pt = coordSys.dataToPoint(coordSys.clampData(value));
        var data = this.getData();
        var offset = data.getLayout('offset');
        var size = data.getLayout('size');
        var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1;
        pt[offsetIndex] += offset + size / 2;
        return pt;
      }

      return [NaN, NaN];
    };

    BaseBarSeriesModel.type = 'series.__base_bar__';
    BaseBarSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'cartesian2d',
      legendHoverLink: true,
      barMinHeight: 0,
      barMinAngle: 0,
      large: false,
      largeThreshold: 400,
      progressive: 3e3,
      progressiveChunkMode: 'mod'
    };
    return BaseBarSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(BaseBarSeriesModel);

  var BarSeriesModel = function (_super) {
    __extends(BarSeriesModel, _super);

    function BarSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BarSeriesModel.type;
      return _this;
    }

    BarSeriesModel.prototype.getProgressive = function () {
      return this.get('large') ? this.get('progressive') : false;
    };

    BarSeriesModel.prototype.getProgressiveThreshold = function () {
      var progressiveThreshold = this.get('progressiveThreshold');
      var largeThreshold = this.get('largeThreshold');

      if (largeThreshold > progressiveThreshold) {
        progressiveThreshold = largeThreshold;
      }

      return progressiveThreshold;
    };

    BarSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) {
      return selectors.rect(data.getItemLayout(dataIndex));
    };

    BarSeriesModel.type = 'series.bar';
    BarSeriesModel.dependencies = ['grid', 'polar'];
    BarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, {
      clip: true,
      roundCap: false,
      showBackground: false,
      backgroundStyle: {
        color: 'rgba(180, 180, 180, 0.2)',
        borderColor: null,
        borderWidth: 0,
        borderType: 'solid',
        borderRadius: 0,
        shadowBlur: 0,
        shadowColor: null,
        shadowOffsetX: 0,
        shadowOffsetY: 0,
        opacity: 1
      },
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      },
      realtimeSort: false
    });
    return BarSeriesModel;
  }(BaseBarSeriesModel);

  SeriesModel.registerClass(BarSeriesModel);

  var SausageShape = function () {
    function SausageShape() {
      this.cx = 0;
      this.cy = 0;
      this.r0 = 0;
      this.r = 0;
      this.startAngle = 0;
      this.endAngle = Math.PI * 2;
      this.clockwise = true;
    }

    return SausageShape;
  }();

  var SausagePath = function (_super) {
    __extends(SausagePath, _super);

    function SausagePath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'sausage';
      return _this;
    }

    SausagePath.prototype.getDefaultShape = function () {
      return new SausageShape();
    };

    SausagePath.prototype.buildPath = function (ctx, shape) {
      var x = shape.cx;
      var y = shape.cy;
      var r0 = Math.max(shape.r0 || 0, 0);
      var r = Math.max(shape.r, 0);
      var dr = (r - r0) * 0.5;
      var rCenter = r0 + dr;
      var startAngle = shape.startAngle;
      var endAngle = shape.endAngle;
      var clockwise = shape.clockwise;
      var unitStartX = Math.cos(startAngle);
      var unitStartY = Math.sin(startAngle);
      var unitEndX = Math.cos(endAngle);
      var unitEndY = Math.sin(endAngle);
      var lessThanCircle = clockwise ? endAngle - startAngle < Math.PI * 2 : startAngle - endAngle < Math.PI * 2;

      if (lessThanCircle) {
        ctx.moveTo(unitStartX * r0 + x, unitStartY * r0 + y);
        ctx.arc(unitStartX * rCenter + x, unitStartY * rCenter + y, dr, -Math.PI + startAngle, startAngle, !clockwise);
      }

      ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
      ctx.moveTo(unitEndX * r + x, unitEndY * r + y);
      ctx.arc(unitEndX * rCenter + x, unitEndY * rCenter + y, dr, endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise);

      if (r0 !== 0) {
        ctx.arc(x, y, r0, endAngle, startAngle, clockwise);
        ctx.moveTo(unitStartX * r0 + x, unitEndY * r0 + y);
      }

      ctx.closePath();
    };

    return SausagePath;
  }(Path);

  var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'];
  var BAR_BORDER_RADIUS_QUERY = ['itemStyle', 'borderRadius'];
  var _eventPos = [0, 0];
  var mathMax$6 = Math.max;
  var mathMin$6 = Math.min;

  function getClipArea(coord, data) {
    var coordSysClipArea = coord.getArea && coord.getArea();

    if (isCoordinateSystemType(coord, 'cartesian2d')) {
      var baseAxis = coord.getBaseAxis();

      if (baseAxis.type !== 'category' || !baseAxis.onBand) {
        var expandWidth = data.getLayout('bandWidth');

        if (baseAxis.isHorizontal()) {
          coordSysClipArea.x -= expandWidth;
          coordSysClipArea.width += expandWidth * 2;
        } else {
          coordSysClipArea.y -= expandWidth;
          coordSysClipArea.height += expandWidth * 2;
        }
      }
    }

    return coordSysClipArea;
  }

  var BarView = function (_super) {
    __extends(BarView, _super);

    function BarView() {
      var _this = _super.call(this) || this;

      _this.type = BarView.type;
      _this._isFirstFrame = true;
      return _this;
    }

    BarView.prototype.render = function (seriesModel, ecModel, api, payload) {
      this._model = seriesModel;
      this.removeOnRenderedListener(api);

      this._updateDrawMode(seriesModel);

      var coordinateSystemType = seriesModel.get('coordinateSystem');

      if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') {
        this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload);
      } else if (true) {
        console.warn('Only cartesian2d and polar supported for bar.');
      }
    };

    BarView.prototype.incrementalPrepareRender = function (seriesModel) {
      this._clear();

      this._updateDrawMode(seriesModel);

      this._updateLargeClip(seriesModel);
    };

    BarView.prototype.incrementalRender = function (params, seriesModel) {
      this._incrementalRenderLarge(params, seriesModel);
    };

    BarView.prototype._updateDrawMode = function (seriesModel) {
      var isLargeDraw = seriesModel.pipelineContext.large;

      if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) {
        this._isLargeDraw = isLargeDraw;

        this._clear();
      }
    };

    BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) {
      var _this = this;

      var group = this.group;
      var data = seriesModel.getData();
      var oldData = this._data;
      var coord = seriesModel.coordinateSystem;
      var baseAxis = coord.getBaseAxis();
      var isHorizontalOrRadial;

      if (coord.type === 'cartesian2d') {
        isHorizontalOrRadial = baseAxis.isHorizontal();
      } else if (coord.type === 'polar') {
        isHorizontalOrRadial = baseAxis.dim === 'angle';
      }

      var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;
      var axis2DModel = baseAxis.model;
      var realtimeSort = seriesModel.get('realtimeSort');

      if (realtimeSort && data.count()) {
        if (this._isFirstFrame) {
          this._initSort(data, isHorizontalOrRadial, baseAxis, api);

          this._isFirstFrame = false;
          return;
        } else {
          this._onRendered = function () {
            var orderMap = function (idx) {
              var el = data.getItemGraphicEl(idx);

              if (el) {
                var shape = el.shape;
                return (isHorizontalOrRadial ? shape.y + shape.height : shape.x + shape.width) || 0;
              } else {
                return 0;
              }
            };

            _this._updateSort(data, orderMap, baseAxis, api);
          };

          api.getZr().on('rendered', this._onRendered);
        }
      }

      var needsClip = seriesModel.get('clip', true) || realtimeSort;
      var coordSysClipArea = getClipArea(coord, data);
      group.removeClipPath();
      var roundCap = seriesModel.get('roundCap', true);
      var drawBackground = seriesModel.get('showBackground', true);
      var backgroundModel = seriesModel.getModel('backgroundStyle');
      var barBorderRadius = backgroundModel.get('borderRadius') || 0;
      var bgEls = [];
      var oldBgEls = this._backgroundEls;
      var isInitSort = payload && payload.isInitSort;
      var isChangeOrder = payload && payload.type === 'changeAxisOrder';

      function createBackground(dataIndex) {
        var bgLayout = getLayout[coord.type](data, dataIndex);
        var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
        bgEl.useStyle(backgroundModel.getItemStyle());

        if (coord.type === 'cartesian2d') {
          bgEl.setShape('r', barBorderRadius);
        }

        bgEls[dataIndex] = bgEl;
        return bgEl;
      }

      data.diff(oldData).add(function (dataIndex) {
        var itemModel = data.getItemModel(dataIndex);
        var layout = getLayout[coord.type](data, dataIndex, itemModel);

        if (drawBackground) {
          createBackground(dataIndex);
        }

        if (!data.hasValue(dataIndex)) {
          return;
        }

        var isClipped = false;

        if (needsClip) {
          isClipped = clip[coord.type](coordSysClipArea, layout);
        }

        var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap);
        updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');

        if (isInitSort) {
          el.attr({
            shape: layout
          });
        } else if (realtimeSort) {
          updateRealtimeAnimation(seriesModel, axis2DModel, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false);
        } else {
          initProps(el, {
            shape: layout
          }, seriesModel, dataIndex);
        }

        data.setItemGraphicEl(dataIndex, el);
        group.add(el);
        el.ignore = isClipped;
      }).update(function (newIndex, oldIndex) {
        var itemModel = data.getItemModel(newIndex);
        var layout = getLayout[coord.type](data, newIndex, itemModel);

        if (drawBackground) {
          var bgEl = void 0;

          if (oldBgEls.length === 0) {
            bgEl = createBackground(oldIndex);
          } else {
            bgEl = oldBgEls[oldIndex];
            bgEl.useStyle(backgroundModel.getItemStyle());

            if (coord.type === 'cartesian2d') {
              bgEl.setShape('r', barBorderRadius);
            }

            bgEls[newIndex] = bgEl;
          }

          var bgLayout = getLayout[coord.type](data, newIndex);
          var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
          updateProps(bgEl, {
            shape: shape
          }, animationModel, newIndex);
        }

        var el = oldData.getItemGraphicEl(oldIndex);

        if (!data.hasValue(newIndex)) {
          group.remove(el);
          el = null;
          return;
        }

        var isClipped = false;

        if (needsClip) {
          isClipped = clip[coord.type](coordSysClipArea, layout);

          if (isClipped) {
            group.remove(el);
          }
        }

        if (!el) {
          el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap);
        }

        if (!isChangeOrder) {
          updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
        }

        if (isInitSort) {
          el.attr({
            shape: layout
          });
        } else if (realtimeSort) {
          updateRealtimeAnimation(seriesModel, axis2DModel, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder);
        } else {
          updateProps(el, {
            shape: layout
          }, seriesModel, newIndex, null);
        }

        data.setItemGraphicEl(newIndex, el);
        el.ignore = isClipped;
        group.add(el);
      }).remove(function (dataIndex) {
        var el = oldData.getItemGraphicEl(dataIndex);
        el && removeElementWithFadeOut(el, seriesModel, dataIndex);
      }).execute();
      var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
      bgGroup.removeAll();

      for (var i = 0; i < bgEls.length; ++i) {
        bgGroup.add(bgEls[i]);
      }

      group.add(bgGroup);
      this._backgroundEls = bgEls;
      this._data = data;
    };

    BarView.prototype._renderLarge = function (seriesModel, ecModel, api) {
      this._clear();

      createLarge(seriesModel, this.group);

      this._updateLargeClip(seriesModel);
    };

    BarView.prototype._incrementalRenderLarge = function (params, seriesModel) {
      this._removeBackground();

      createLarge(seriesModel, this.group, true);
    };

    BarView.prototype._updateLargeClip = function (seriesModel) {
      var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null;

      if (clipPath) {
        this.group.setClipPath(clipPath);
      } else {
        this.group.removeClipPath();
      }
    };

    BarView.prototype._dataSort = function (data, idxMap) {
      var info = [];
      data.each(function (idx) {
        info.push({
          mappedValue: idxMap(idx),
          ordinalNumber: idx,
          beforeSortIndex: null
        });
      });
      info.sort(function (a, b) {
        return b.mappedValue - a.mappedValue;
      });

      for (var i = 0; i < info.length; ++i) {
        info[info[i].ordinalNumber].beforeSortIndex = i;
      }

      return map(info, function (item) {
        return {
          ordinalNumber: item.ordinalNumber,
          beforeSortIndex: item.beforeSortIndex
        };
      });
    };

    BarView.prototype._isDataOrderChanged = function (data, orderMap, oldOrder) {
      var oldCount = oldOrder ? oldOrder.length : 0;

      if (oldCount !== data.count()) {
        return true;
      }

      var lastValue = Number.MAX_VALUE;

      for (var i = 0; i < oldOrder.length; ++i) {
        var value = orderMap(oldOrder[i].ordinalNumber);

        if (value > lastValue) {
          return true;
        }

        lastValue = value;
      }

      return false;
    };

    BarView.prototype._updateSort = function (data, orderMap, baseAxis, api) {
      var oldOrder = baseAxis.scale.getCategorySortInfo();

      var isOrderChanged = this._isDataOrderChanged(data, orderMap, oldOrder);

      if (isOrderChanged) {
        var newOrder = this._dataSort(data, orderMap);

        var extent = baseAxis.scale.getExtent();

        for (var i = extent[0]; i < extent[1]; ++i) {
          if (!oldOrder[i] || oldOrder[i].ordinalNumber !== newOrder[i].ordinalNumber) {
            this.removeOnRenderedListener(api);
            var action = {
              type: 'changeAxisOrder',
              componentType: baseAxis.dim + 'Axis',
              axisId: baseAxis.index,
              sortInfo: newOrder
            };
            api.dispatchAction(action);
            break;
          }
        }
      }
    };

    BarView.prototype._initSort = function (data, isHorizontal, baseAxis, api) {
      var action = {
        type: 'changeAxisOrder',
        componentType: baseAxis.dim + 'Axis',
        isInitSort: true,
        axisId: baseAxis.index,
        sortInfo: this._dataSort(data, function (idx) {
          return parseFloat(data.get(isHorizontal ? 'y' : 'x', idx)) || 0;
        })
      };
      api.dispatchAction(action);
    };

    BarView.prototype.remove = function (ecModel, api) {
      this._clear(this._model);

      this.removeOnRenderedListener(api);
    };

    BarView.prototype.dispose = function (ecModel, api) {
      this.removeOnRenderedListener(api);
    };

    BarView.prototype.removeOnRenderedListener = function (api) {
      if (this._onRendered) {
        api.getZr().off('rendered', this._onRendered);
        this._onRendered = null;
      }
    };

    BarView.prototype._clear = function (model) {
      var group = this.group;
      var data = this._data;

      if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) {
        this._removeBackground();

        this._backgroundEls = [];
        data.eachItemGraphicEl(function (el) {
          removeElementWithFadeOut(el, model, getECData(el).dataIndex);
        });
      } else {
        group.removeAll();
      }

      this._data = null;
      this._isFirstFrame = true;
    };

    BarView.prototype._removeBackground = function () {
      this.group.remove(this._backgroundGroup);
      this._backgroundGroup = null;
    };

    BarView.type = 'bar';
    return BarView;
  }(ChartView);

  var clip = {
    cartesian2d: function (coordSysBoundingRect, layout) {
      var signWidth = layout.width < 0 ? -1 : 1;
      var signHeight = layout.height < 0 ? -1 : 1;

      if (signWidth < 0) {
        layout.x += layout.width;
        layout.width = -layout.width;
      }

      if (signHeight < 0) {
        layout.y += layout.height;
        layout.height = -layout.height;
      }

      var x = mathMax$6(layout.x, coordSysBoundingRect.x);
      var x2 = mathMin$6(layout.x + layout.width, coordSysBoundingRect.x + coordSysBoundingRect.width);
      var y = mathMax$6(layout.y, coordSysBoundingRect.y);
      var y2 = mathMin$6(layout.y + layout.height, coordSysBoundingRect.y + coordSysBoundingRect.height);
      layout.x = x;
      layout.y = y;
      layout.width = x2 - x;
      layout.height = y2 - y;
      var clipped = layout.width < 0 || layout.height < 0;

      if (signWidth < 0) {
        layout.x += layout.width;
        layout.width = -layout.width;
      }

      if (signHeight < 0) {
        layout.y += layout.height;
        layout.height = -layout.height;
      }

      return clipped;
    },
    polar: function (coordSysClipArea, layout) {
      var signR = layout.r0 <= layout.r ? 1 : -1;

      if (signR < 0) {
        var tmp = layout.r;
        layout.r = layout.r0;
        layout.r0 = tmp;
      }

      var r = mathMin$6(layout.r, coordSysClipArea.r);
      var r0 = mathMax$6(layout.r0, coordSysClipArea.r0);
      layout.r = r;
      layout.r0 = r0;
      var clipped = r - r0 < 0;

      if (signR < 0) {
        var tmp = layout.r;
        layout.r = layout.r0;
        layout.r0 = tmp;
      }

      return clipped;
    }
  };
  var elementCreator = {
    cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) {
      var rect = new Rect({
        shape: extend({}, layout),
        z2: 1
      });
      rect.__dataIndex = newIndex;
      rect.name = 'item';

      if (animationModel) {
        var rectShape = rect.shape;
        var animateProperty = isHorizontal ? 'height' : 'width';
        rectShape[animateProperty] = 0;
      }

      return rect;
    },
    polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
      var clockwise = layout.startAngle < layout.endAngle;
      var ShapeClass = !isRadial && roundCap ? SausagePath : Sector;
      var sector = new ShapeClass({
        shape: defaults({
          clockwise: clockwise
        }, layout),
        z2: 1
      });
      sector.name = 'item';

      if (animationModel) {
        var sectorShape = sector.shape;
        var animateProperty = isRadial ? 'r' : 'endAngle';
        var animateTarget = {};
        sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
        animateTarget[animateProperty] = layout[animateProperty];
        (isUpdate ? updateProps : initProps)(sector, {
          shape: animateTarget
        }, animationModel);
      }

      return sector;
    }
  };

  function updateRealtimeAnimation(seriesModel, axisModel, animationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) {
    if (animationModel || axisModel) {
      var seriesTarget = void 0;
      var axisTarget = void 0;

      if (isHorizontal) {
        axisTarget = {
          x: layout.x,
          width: layout.width
        };
        seriesTarget = {
          y: layout.y,
          height: layout.height
        };
      } else {
        axisTarget = {
          y: layout.y,
          height: layout.height
        };
        seriesTarget = {
          x: layout.x,
          width: layout.width
        };
      }

      if (!isChangeOrder) {
        (isUpdate ? updateProps : initProps)(el, {
          shape: seriesTarget
        }, seriesModel, newIndex, null);
      }

      (isUpdate ? updateProps : initProps)(el, {
        shape: axisTarget
      }, axisModel, newIndex);
    }
  }

  var getLayout = {
    cartesian2d: function (data, dataIndex, itemModel) {
      var layout = data.getItemLayout(dataIndex);
      var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0;
      var signX = layout.width > 0 ? 1 : -1;
      var signY = layout.height > 0 ? 1 : -1;
      return {
        x: layout.x + signX * fixedLineWidth / 2,
        y: layout.y + signY * fixedLineWidth / 2,
        width: layout.width - signX * fixedLineWidth,
        height: layout.height - signY * fixedLineWidth
      };
    },
    polar: function (data, dataIndex, itemModel) {
      var layout = data.getItemLayout(dataIndex);
      return {
        cx: layout.cx,
        cy: layout.cy,
        r0: layout.r0,
        r: layout.r,
        startAngle: layout.startAngle,
        endAngle: layout.endAngle
      };
    }
  };

  function isZeroOnPolar(layout) {
    return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle;
  }

  function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar) {
    var style = data.getItemVisual(dataIndex, 'style');

    if (!isPolar) {
      el.setShape('r', itemModel.get(BAR_BORDER_RADIUS_QUERY) || 0);
    }

    el.useStyle(style);
    var cursorStyle = itemModel.getShallow('cursor');
    cursorStyle && el.attr('cursor', cursorStyle);

    if (!isPolar) {
      var labelPositionOutside = isHorizontal ? layout.height > 0 ? 'bottom' : 'top' : layout.width > 0 ? 'left' : 'right';
      var labelStatesModels = getLabelStatesModels(itemModel);
      setLabelStyle(el, labelStatesModels, {
        labelFetcher: seriesModel,
        labelDataIndex: dataIndex,
        defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
        inheritColor: style.fill,
        defaultOpacity: style.opacity,
        defaultOutsidePosition: labelPositionOutside
      });
      var label = el.getTextContent();
      setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) {
        return getDefaultInterpolatedLabel(data, value);
      });
    }

    var emphasisModel = itemModel.getModel(['emphasis']);
    enableHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
    setStatesStylesFromModel(el, itemModel);

    if (isZeroOnPolar(layout)) {
      el.style.fill = 'none';
      el.style.stroke = 'none';
      each(el.states, function (state) {
        if (state.style) {
          state.style.fill = state.style.stroke = 'none';
        }
      });
    }
  }

  function getLineWidth(itemModel, rawLayout) {
    var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
    var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
    var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
    return Math.min(lineWidth, width, height);
  }

  var LagePathShape = function () {
    function LagePathShape() {}

    return LagePathShape;
  }();

  var LargePath = function (_super) {
    __extends(LargePath, _super);

    function LargePath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'largeBar';
      return _this;
    }

    LargePath.prototype.getDefaultShape = function () {
      return new LagePathShape();
    };

    LargePath.prototype.buildPath = function (ctx, shape) {
      var points = shape.points;
      var startPoint = this.__startPoint;
      var baseDimIdx = this.__baseDimIdx;

      for (var i = 0; i < points.length; i += 2) {
        startPoint[baseDimIdx] = points[i + baseDimIdx];
        ctx.moveTo(startPoint[0], startPoint[1]);
        ctx.lineTo(points[i], points[i + 1]);
      }
    };

    return LargePath;
  }(Path);

  function createLarge(seriesModel, group, incremental) {
    var data = seriesModel.getData();
    var startPoint = [];
    var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
    startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
    var largeDataIndices = data.getLayout('largeDataIndices');
    var barWidth = data.getLayout('barWidth');
    var backgroundModel = seriesModel.getModel('backgroundStyle');
    var drawBackground = seriesModel.get('showBackground', true);

    if (drawBackground) {
      var points = data.getLayout('largeBackgroundPoints');
      var backgroundStartPoint = [];
      backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart');
      var bgEl = new LargePath({
        shape: {
          points: points
        },
        incremental: !!incremental,
        silent: true,
        z2: 0
      });
      bgEl.__startPoint = backgroundStartPoint;
      bgEl.__baseDimIdx = baseDimIdx;
      bgEl.__largeDataIndices = largeDataIndices;
      bgEl.__barWidth = barWidth;
      setLargeBackgroundStyle(bgEl, backgroundModel, data);
      group.add(bgEl);
    }

    var el = new LargePath({
      shape: {
        points: data.getLayout('largePoints')
      },
      incremental: !!incremental
    });
    el.__startPoint = startPoint;
    el.__baseDimIdx = baseDimIdx;
    el.__largeDataIndices = largeDataIndices;
    el.__barWidth = barWidth;
    group.add(el);
    setLargeStyle(el, seriesModel, data);
    getECData(el).seriesIndex = seriesModel.seriesIndex;

    if (!seriesModel.get('silent')) {
      el.on('mousedown', largePathUpdateDataIndex);
      el.on('mousemove', largePathUpdateDataIndex);
    }
  }

  var largePathUpdateDataIndex = throttle(function (event) {
    var largePath = this;
    var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
    getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null;
  }, 30, false);

  function largePathFindDataIndex(largePath, x, y) {
    var baseDimIdx = largePath.__baseDimIdx;
    var valueDimIdx = 1 - baseDimIdx;
    var points = largePath.shape.points;
    var largeDataIndices = largePath.__largeDataIndices;
    var barWidthHalf = Math.abs(largePath.__barWidth / 2);
    var startValueVal = largePath.__startPoint[valueDimIdx];
    _eventPos[0] = x;
    _eventPos[1] = y;
    var pointerBaseVal = _eventPos[baseDimIdx];
    var pointerValueVal = _eventPos[1 - baseDimIdx];
    var baseLowerBound = pointerBaseVal - barWidthHalf;
    var baseUpperBound = pointerBaseVal + barWidthHalf;

    for (var i = 0, len = points.length / 2; i < len; i++) {
      var ii = i * 2;
      var barBaseVal = points[ii + baseDimIdx];
      var barValueVal = points[ii + valueDimIdx];

      if (barBaseVal >= baseLowerBound && barBaseVal <= baseUpperBound && (startValueVal <= barValueVal ? pointerValueVal >= startValueVal && pointerValueVal <= barValueVal : pointerValueVal >= barValueVal && pointerValueVal <= startValueVal)) {
        return largeDataIndices[i];
      }
    }

    return -1;
  }

  function setLargeStyle(el, seriesModel, data) {
    var globalStyle = data.getVisual('style');
    el.useStyle(extend({}, globalStyle));
    el.style.fill = null;
    el.style.stroke = globalStyle.fill;
    el.style.lineWidth = data.getLayout('barWidth');
  }

  function setLargeBackgroundStyle(el, backgroundModel, data) {
    var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color');
    var itemStyle = backgroundModel.getItemStyle();
    el.useStyle(itemStyle);
    el.style.fill = null;
    el.style.stroke = borderColor;
    el.style.lineWidth = data.getLayout('barWidth');
  }

  function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
    if (isCoordinateSystemType(coord, 'cartesian2d')) {
      var rectShape = layout;
      var coordLayout = coord.getArea();
      return {
        x: isHorizontalOrRadial ? rectShape.x : coordLayout.x,
        y: isHorizontalOrRadial ? coordLayout.y : rectShape.y,
        width: isHorizontalOrRadial ? rectShape.width : coordLayout.width,
        height: isHorizontalOrRadial ? coordLayout.height : rectShape.height
      };
    } else {
      var coordLayout = coord.getArea();
      var sectorShape = layout;
      return {
        cx: coordLayout.cx,
        cy: coordLayout.cy,
        r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0,
        r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r,
        startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0,
        endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2
      };
    }
  }

  function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
    var ElementClz = coord.type === 'polar' ? Sector : Rect;
    return new ElementClz({
      shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
      silent: true,
      z2: 0
    });
  }

  ChartView.registerClass(BarView);
  registerAction({
    type: 'changeAxisOrder',
    event: 'changeAxisOrder',
    update: 'update'
  }, function (payload, ecModel) {
    var componentType = payload.componentType || 'series';
    ecModel.eachComponent({
      mainType: componentType,
      query: payload
    }, function (componentModel) {
      if (payload.sortInfo) {
        componentModel.axis.setCategorySortInfo(payload.sortInfo);
      }
    });
  });
  registerLayout(PRIORITY.VISUAL.LAYOUT, curry(layout, 'bar'));
  registerLayout(PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout);
  registerVisual({
    seriesType: 'bar',
    reset: function (seriesModel) {
      seriesModel.getData().setVisual('legendSymbol', 'roundRect');
    }
  });
  registerProcessor(PRIORITY.PROCESSOR.STATISTIC, dataSample('bar'));

  function createListSimply(seriesModel, opt, nameList) {
    opt = isArray(opt) && {
      coordDimensions: opt
    } || extend({}, opt);
    var source = seriesModel.getSource();
    var dimensionsInfo = createDimensions(source, opt);
    var list = new List(dimensionsInfo, seriesModel);
    list.initData(source, nameList);
    return list;
  }

  var LegendVisualProvider = function () {
    function LegendVisualProvider(getDataWithEncodedVisual, getRawData) {
      this._getDataWithEncodedVisual = getDataWithEncodedVisual;
      this._getRawData = getRawData;
    }

    LegendVisualProvider.prototype.getAllNames = function () {
      var rawData = this._getRawData();

      return rawData.mapArray(rawData.getName);
    };

    LegendVisualProvider.prototype.containName = function (name) {
      var rawData = this._getRawData();

      return rawData.indexOfName(name) >= 0;
    };

    LegendVisualProvider.prototype.indexOfName = function (name) {
      var dataWithEncodedVisual = this._getDataWithEncodedVisual();

      return dataWithEncodedVisual.indexOfName(name);
    };

    LegendVisualProvider.prototype.getItemVisual = function (dataIndex, key) {
      var dataWithEncodedVisual = this._getDataWithEncodedVisual();

      return dataWithEncodedVisual.getItemVisual(dataIndex, key);
    };

    return LegendVisualProvider;
  }();

  var PieSeriesModel = function (_super) {
    __extends(PieSeriesModel, _super);

    function PieSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.useColorPaletteOnData = true;
      return _this;
    }

    PieSeriesModel.prototype.init = function (option) {
      _super.prototype.init.apply(this, arguments);

      this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this));

      this._defaultLabelLine(option);
    };

    PieSeriesModel.prototype.mergeOption = function () {
      _super.prototype.mergeOption.apply(this, arguments);
    };

    PieSeriesModel.prototype.getInitialData = function () {
      return createListSimply(this, {
        coordDimensions: ['value'],
        encodeDefaulter: curry(makeSeriesEncodeForNameBased, this)
      });
    };

    PieSeriesModel.prototype.getDataParams = function (dataIndex) {
      var data = this.getData();

      var params = _super.prototype.getDataParams.call(this, dataIndex);

      var valueList = [];
      data.each(data.mapDimension('value'), function (value) {
        valueList.push(value);
      });
      params.percent = getPercentWithPrecision(valueList, dataIndex, data.hostModel.get('percentPrecision'));
      params.$vars.push('percent');
      return params;
    };

    PieSeriesModel.prototype._defaultLabelLine = function (option) {
      defaultEmphasis(option, 'labelLine', ['show']);
      var labelLineNormalOpt = option.labelLine;
      var labelLineEmphasisOpt = option.emphasis.labelLine;
      labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show;
      labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show;
    };

    PieSeriesModel.type = 'series.pie';
    PieSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      center: ['50%', '50%'],
      radius: [0, '75%'],
      clockwise: true,
      startAngle: 90,
      minAngle: 0,
      minShowLabelAngle: 0,
      selectedOffset: 10,
      percentPrecision: 2,
      stillShowZeroSum: true,
      left: 0,
      top: 0,
      right: 0,
      bottom: 0,
      width: null,
      height: null,
      label: {
        rotate: 0,
        show: true,
        overflow: 'truncate',
        position: 'outer',
        alignTo: 'none',
        edgeDistance: '25%',
        bleedMargin: 10,
        distanceToLabelLine: 5
      },
      labelLine: {
        show: true,
        length: 15,
        length2: 15,
        smooth: false,
        minTurnAngle: 90,
        maxSurfaceAngle: 90,
        lineStyle: {
          width: 1,
          type: 'solid'
        }
      },
      itemStyle: {
        borderWidth: 1
      },
      labelLayout: {
        hideOverlap: true
      },
      emphasis: {
        scale: true,
        scaleSize: 5
      },
      avoidLabelOverlap: true,
      animationType: 'expansion',
      animationDuration: 1000,
      animationTypeUpdate: 'transition',
      animationEasingUpdate: 'cubicInOut',
      animationDurationUpdate: 500,
      animationEasing: 'cubicInOut'
    };
    return PieSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(PieSeriesModel);
  var RADIAN = Math.PI / 180;

  function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) {
    if (list.length < 2) {
      return;
    }

    function recalculateXOnSemiToAlignOnEllipseCurve(semi) {
      var rB = semi.rB;
      var rB2 = rB * rB;

      for (var i = 0; i < semi.list.length; i++) {
        var item = semi.list[i];
        var dy = Math.abs(item.label.y - cy);
        var rA = r + item.len;
        var rA2 = rA * rA;
        var dx = Math.sqrt((1 - Math.abs(dy * dy / rB2)) * rA2);
        item.label.x = cx + (dx + item.len2) * dir;
      }
    }

    function recalculateX(items) {
      var topSemi = {
        list: [],
        maxY: 0
      };
      var bottomSemi = {
        list: [],
        maxY: 0
      };

      for (var i = 0; i < items.length; i++) {
        if (items[i].labelAlignTo !== 'none') {
          continue;
        }

        var item = items[i];
        var semi = item.label.y > cy ? bottomSemi : topSemi;
        var dy = Math.abs(item.label.y - cy);

        if (dy > semi.maxY) {
          var dx = item.label.x - cx - item.len2 * dir;
          var rA = r + item.len;
          var rB = dx < rA ? Math.sqrt(dy * dy / (1 - dx * dx / rA / rA)) : rA;
          semi.rB = rB;
          semi.maxY = dy;
        }

        semi.list.push(item);
      }

      recalculateXOnSemiToAlignOnEllipseCurve(topSemi);
      recalculateXOnSemiToAlignOnEllipseCurve(bottomSemi);
    }

    var len = list.length;

    for (var i = 0; i < len; i++) {
      if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') {
        var dx = list[i].label.x - farthestX;
        list[i].linePoints[1][0] += dx;
        list[i].label.x = farthestX;
      }
    }

    if (shiftLayoutOnY(list, viewTop, viewTop + viewHeight)) {
      recalculateX(list);
    }
  }

  function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) {
    var leftList = [];
    var rightList = [];
    var leftmostX = Number.MAX_VALUE;
    var rightmostX = -Number.MAX_VALUE;

    for (var i = 0; i < labelLayoutList.length; i++) {
      var label = labelLayoutList[i].label;

      if (isPositionCenter(labelLayoutList[i])) {
        continue;
      }

      if (label.x < cx) {
        leftmostX = Math.min(leftmostX, label.x);
        leftList.push(labelLayoutList[i]);
      } else {
        rightmostX = Math.max(rightmostX, label.x);
        rightList.push(labelLayoutList[i]);
      }
    }

    adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX);
    adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX);

    for (var i = 0; i < labelLayoutList.length; i++) {
      var layout = labelLayoutList[i];
      var label = layout.label;

      if (isPositionCenter(layout)) {
        continue;
      }

      var linePoints = layout.linePoints;

      if (linePoints) {
        var isAlignToEdge = layout.labelAlignTo === 'edge';
        var realTextWidth = layout.rect.width;
        var targetTextWidth = void 0;

        if (isAlignToEdge) {
          if (label.x < cx) {
            targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.edgeDistance;
          } else {
            targetTextWidth = viewLeft + viewWidth - layout.edgeDistance - linePoints[2][0] - layout.labelDistance;
          }
        } else {
          if (label.x < cx) {
            targetTextWidth = label.x - viewLeft - layout.bleedMargin;
          } else {
            targetTextWidth = viewLeft + viewWidth - label.x - layout.bleedMargin;
          }
        }

        if (targetTextWidth < layout.rect.width) {
          layout.label.style.width = targetTextWidth;

          if (layout.labelAlignTo === 'edge') {
            realTextWidth = targetTextWidth;
          }
        }

        var dist = linePoints[1][0] - linePoints[2][0];

        if (isAlignToEdge) {
          if (label.x < cx) {
            linePoints[2][0] = viewLeft + layout.edgeDistance + realTextWidth + layout.labelDistance;
          } else {
            linePoints[2][0] = viewLeft + viewWidth - layout.edgeDistance - realTextWidth - layout.labelDistance;
          }
        } else {
          if (label.x < cx) {
            linePoints[2][0] = label.x + layout.labelDistance;
          } else {
            linePoints[2][0] = label.x - layout.labelDistance;
          }

          linePoints[1][0] = linePoints[2][0] + dist;
        }

        linePoints[1][1] = linePoints[2][1] = label.y;
      }
    }
  }

  function isPositionCenter(sectorShape) {
    return sectorShape.position === 'center';
  }

  function pieLabelLayout(seriesModel) {
    var data = seriesModel.getData();
    var labelLayoutList = [];
    var cx;
    var cy;
    var hasLabelRotate = false;
    var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN;
    var viewRect = data.getLayout('viewRect');
    var r = data.getLayout('r');
    var viewWidth = viewRect.width;
    var viewLeft = viewRect.x;
    var viewTop = viewRect.y;
    var viewHeight = viewRect.height;

    function setNotShow(el) {
      el.ignore = true;
    }

    function isLabelShown(label) {
      if (!label.ignore) {
        return true;
      }

      for (var key in label.states) {
        if (label.states[key].ignore === false) {
          return true;
        }
      }

      return false;
    }

    data.each(function (idx) {
      var sector = data.getItemGraphicEl(idx);
      var sectorShape = sector.shape;
      var label = sector.getTextContent();
      var labelLine = sector.getTextGuideLine();
      var itemModel = data.getItemModel(idx);
      var labelModel = itemModel.getModel('label');
      var labelPosition = labelModel.get('position') || itemModel.get(['emphasis', 'label', 'position']);
      var labelDistance = labelModel.get('distanceToLabelLine');
      var labelAlignTo = labelModel.get('alignTo');
      var edgeDistance = parsePercent$2(labelModel.get('edgeDistance'), viewWidth);
      var bleedMargin = labelModel.get('bleedMargin');
      var labelLineModel = itemModel.getModel('labelLine');
      var labelLineLen = labelLineModel.get('length');
      labelLineLen = parsePercent$2(labelLineLen, viewWidth);
      var labelLineLen2 = labelLineModel.get('length2');
      labelLineLen2 = parsePercent$2(labelLineLen2, viewWidth);

      if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) {
        each(label.states, setNotShow);
        label.ignore = true;
        return;
      }

      if (!isLabelShown(label)) {
        return;
      }

      var midAngle = (sectorShape.startAngle + sectorShape.endAngle) / 2;
      var nx = Math.cos(midAngle);
      var ny = Math.sin(midAngle);
      var textX;
      var textY;
      var linePoints;
      var textAlign;
      cx = sectorShape.cx;
      cy = sectorShape.cy;
      var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';

      if (labelPosition === 'center') {
        textX = sectorShape.cx;
        textY = sectorShape.cy;
        textAlign = 'center';
      } else {
        var x1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * nx : sectorShape.r * nx) + cx;
        var y1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * ny : sectorShape.r * ny) + cy;
        textX = x1 + nx * 3;
        textY = y1 + ny * 3;

        if (!isLabelInside) {
          var x2 = x1 + nx * (labelLineLen + r - sectorShape.r);
          var y2 = y1 + ny * (labelLineLen + r - sectorShape.r);
          var x3 = x2 + (nx < 0 ? -1 : 1) * labelLineLen2;
          var y3 = y2;

          if (labelAlignTo === 'edge') {
            textX = nx < 0 ? viewLeft + edgeDistance : viewLeft + viewWidth - edgeDistance;
          } else {
            textX = x3 + (nx < 0 ? -labelDistance : labelDistance);
          }

          textY = y3;
          linePoints = [[x1, y1], [x2, y2], [x3, y3]];
        }

        textAlign = isLabelInside ? 'center' : labelAlignTo === 'edge' ? nx > 0 ? 'right' : 'left' : nx > 0 ? 'left' : 'right';
      }

      var labelRotate;
      var rotate = labelModel.get('rotate');

      if (typeof rotate === 'number') {
        labelRotate = rotate * (Math.PI / 180);
      } else {
        labelRotate = rotate ? nx < 0 ? -midAngle + Math.PI : -midAngle : 0;
      }

      hasLabelRotate = !!labelRotate;
      label.x = textX;
      label.y = textY;
      label.rotation = labelRotate;
      label.setStyle({
        verticalAlign: 'middle'
      });

      if (!isLabelInside) {
        var textRect = label.getBoundingRect().clone();
        textRect.applyTransform(label.getComputedTransform());
        var margin = (label.style.margin || 0) + 2.1;
        textRect.y -= margin / 2;
        textRect.height += margin;
        labelLayoutList.push({
          label: label,
          labelLine: labelLine,
          position: labelPosition,
          len: labelLineLen,
          len2: labelLineLen2,
          minTurnAngle: labelLineModel.get('minTurnAngle'),
          maxSurfaceAngle: labelLineModel.get('maxSurfaceAngle'),
          surfaceNormal: new Point(nx, ny),
          linePoints: linePoints,
          textAlign: textAlign,
          labelDistance: labelDistance,
          labelAlignTo: labelAlignTo,
          edgeDistance: edgeDistance,
          bleedMargin: bleedMargin,
          rect: textRect
        });
      } else {
        label.setStyle({
          align: textAlign
        });
        var selectState = label.states.select;

        if (selectState) {
          selectState.x += label.x;
          selectState.y += label.y;
        }
      }

      sector.setTextConfig({
        inside: isLabelInside
      });
    });

    if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
      avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop);
    }

    for (var i = 0; i < labelLayoutList.length; i++) {
      var layout = labelLayoutList[i];
      var label = layout.label;
      var labelLine = layout.labelLine;
      var notShowLabel = isNaN(label.x) || isNaN(label.y);

      if (label) {
        label.setStyle({
          align: layout.textAlign
        });

        if (notShowLabel) {
          each(label.states, setNotShow);
          label.ignore = true;
        }

        var selectState = label.states.select;

        if (selectState) {
          selectState.x += label.x;
          selectState.y += label.y;
        }
      }

      if (labelLine) {
        var linePoints = layout.linePoints;

        if (notShowLabel || !linePoints) {
          each(labelLine.states, setNotShow);
          labelLine.ignore = true;
        } else {
          limitTurnAngle(linePoints, layout.minTurnAngle);
          limitSurfaceAngle(linePoints, layout.surfaceNormal, layout.maxSurfaceAngle);
          labelLine.setShape({
            points: linePoints
          });
          label.__hostTarget.textGuideLineConfig = {
            anchor: new Point(linePoints[0][0], linePoints[0][1])
          };
        }
      }
    }
  }

  function getSectorCornerRadius(model, shape) {
    var cornerRadius = model.get('borderRadius');

    if (cornerRadius == null) {
      return null;
    }

    if (!isArray(cornerRadius)) {
      cornerRadius = [cornerRadius, cornerRadius];
    }

    return {
      innerCornerRadius: parsePercent(cornerRadius[0], shape.r0),
      cornerRadius: parsePercent(cornerRadius[1], shape.r)
    };
  }

  var PiePiece = function (_super) {
    __extends(PiePiece, _super);

    function PiePiece(data, idx, startAngle) {
      var _this = _super.call(this) || this;

      _this.z2 = 2;
      var polyline = new Polyline();
      var text = new ZRText();

      _this.setTextGuideLine(polyline);

      _this.setTextContent(text);

      _this.updateData(data, idx, startAngle, true);

      return _this;
    }

    PiePiece.prototype.updateData = function (data, idx, startAngle, firstCreate) {
      var sector = this;
      var seriesModel = data.hostModel;
      var itemModel = data.getItemModel(idx);
      var emphasisModel = itemModel.getModel('emphasis');
      var layout = data.getItemLayout(idx);
      var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout) || {}, layout);

      if (firstCreate) {
        sector.setShape(sectorShape);
        var animationType = seriesModel.getShallow('animationType');

        if (animationType === 'scale') {
          sector.shape.r = layout.r0;
          initProps(sector, {
            shape: {
              r: layout.r
            }
          }, seriesModel, idx);
        } else {
          if (startAngle != null) {
            sector.setShape({
              startAngle: startAngle,
              endAngle: startAngle
            });
            initProps(sector, {
              shape: {
                startAngle: layout.startAngle,
                endAngle: layout.endAngle
              }
            }, seriesModel, idx);
          } else {
            sector.shape.endAngle = layout.startAngle;
            updateProps(sector, {
              shape: {
                endAngle: layout.endAngle
              }
            }, seriesModel, idx);
          }
        }
      } else {
        updateProps(sector, {
          shape: sectorShape
        }, seriesModel, idx);
      }

      sector.useStyle(data.getItemVisual(idx, 'style'));
      setStatesStylesFromModel(sector, itemModel);
      var midAngle = (layout.startAngle + layout.endAngle) / 2;
      var offset = seriesModel.get('selectedOffset');
      var dx = Math.cos(midAngle) * offset;
      var dy = Math.sin(midAngle) * offset;
      var cursorStyle = itemModel.getShallow('cursor');
      cursorStyle && sector.attr('cursor', cursorStyle);

      this._updateLabel(seriesModel, data, idx);

      sector.ensureState('emphasis').shape = __assign({
        r: layout.r + (emphasisModel.get('scale') ? emphasisModel.get('scaleSize') || 0 : 0)
      }, getSectorCornerRadius(emphasisModel.getModel('itemStyle'), layout));
      extend(sector.ensureState('select'), {
        x: dx,
        y: dy,
        shape: getSectorCornerRadius(itemModel.getModel(['select', 'itemStyle']), layout)
      });
      extend(sector.ensureState('blur'), {
        shape: getSectorCornerRadius(itemModel.getModel(['blur', 'itemStyle']), layout)
      });
      var labelLine = sector.getTextGuideLine();
      var labelText = sector.getTextContent();
      extend(labelLine.ensureState('select'), {
        x: dx,
        y: dy
      });
      extend(labelText.ensureState('select'), {
        x: dx,
        y: dy
      });
      enableHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
    };

    PiePiece.prototype._updateLabel = function (seriesModel, data, idx) {
      var sector = this;
      var itemModel = data.getItemModel(idx);
      var labelLineModel = itemModel.getModel('labelLine');
      var style = data.getItemVisual(idx, 'style');
      var visualColor = style && style.fill;
      var visualOpacity = style && style.opacity;
      setLabelStyle(sector, getLabelStatesModels(itemModel), {
        labelFetcher: data.hostModel,
        labelDataIndex: idx,
        inheritColor: visualColor,
        defaultOpacity: visualOpacity,
        defaultText: seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx)
      });
      var labelText = sector.getTextContent();
      sector.setTextConfig({
        position: null,
        rotation: null
      });
      labelText.attr({
        z2: 10
      });
      setLabelLineStyle(this, getLabelLineStatesModels(itemModel), {
        stroke: visualColor,
        opacity: retrieve3(labelLineModel.get(['lineStyle', 'opacity']), visualOpacity, 1)
      });
    };

    return PiePiece;
  }(Sector);

  var PieView = function (_super) {
    __extends(PieView, _super);

    function PieView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.ignoreLabelLineUpdate = true;
      return _this;
    }

    PieView.prototype.init = function () {
      var sectorGroup = new Group();
      this._sectorGroup = sectorGroup;
    };

    PieView.prototype.render = function (seriesModel, ecModel, api, payload) {
      var data = seriesModel.getData();
      var oldData = this._data;
      var group = this.group;
      var startAngle;

      if (!oldData && data.count() > 0) {
        var shape = data.getItemLayout(0);

        for (var s = 1; isNaN(shape && shape.startAngle) && s < data.count(); ++s) {
          shape = data.getItemLayout(s);
        }

        if (shape) {
          startAngle = shape.startAngle;
        }
      }

      data.diff(oldData).add(function (idx) {
        var piePiece = new PiePiece(data, idx, startAngle);
        data.setItemGraphicEl(idx, piePiece);
        group.add(piePiece);
      }).update(function (newIdx, oldIdx) {
        var piePiece = oldData.getItemGraphicEl(oldIdx);
        piePiece.updateData(data, newIdx, startAngle);
        piePiece.off('click');
        group.add(piePiece);
        data.setItemGraphicEl(newIdx, piePiece);
      }).remove(function (idx) {
        var piePiece = oldData.getItemGraphicEl(idx);
        removeElementWithFadeOut(piePiece, seriesModel, idx);
      }).execute();
      pieLabelLayout(seriesModel);

      if (seriesModel.get('animationTypeUpdate') !== 'expansion') {
        this._data = data;
      }
    };

    PieView.prototype.dispose = function () {};

    PieView.prototype.containPoint = function (point, seriesModel) {
      var data = seriesModel.getData();
      var itemLayout = data.getItemLayout(0);

      if (itemLayout) {
        var dx = point[0] - itemLayout.cx;
        var dy = point[1] - itemLayout.cy;
        var radius = Math.sqrt(dx * dx + dy * dy);
        return radius <= itemLayout.r && radius >= itemLayout.r0;
      }
    };

    PieView.type = 'pie';
    return PieView;
  }(ChartView);

  ChartView.registerClass(PieView);
  var PI2$8 = Math.PI * 2;
  var RADIAN$1 = Math.PI / 180;

  function getViewRect(seriesModel, api) {
    return getLayoutRect(seriesModel.getBoxLayoutParams(), {
      width: api.getWidth(),
      height: api.getHeight()
    });
  }

  function pieLayout(seriesType, ecModel, api) {
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
      var data = seriesModel.getData();
      var valueDim = data.mapDimension('value');
      var viewRect = getViewRect(seriesModel, api);
      var center = seriesModel.get('center');
      var radius = seriesModel.get('radius');

      if (!isArray(radius)) {
        radius = [0, radius];
      }

      if (!isArray(center)) {
        center = [center, center];
      }

      var width = parsePercent$2(viewRect.width, api.getWidth());
      var height = parsePercent$2(viewRect.height, api.getHeight());
      var size = Math.min(width, height);
      var cx = parsePercent$2(center[0], width) + viewRect.x;
      var cy = parsePercent$2(center[1], height) + viewRect.y;
      var r0 = parsePercent$2(radius[0], size / 2);
      var r = parsePercent$2(radius[1], size / 2);
      var startAngle = -seriesModel.get('startAngle') * RADIAN$1;
      var minAngle = seriesModel.get('minAngle') * RADIAN$1;
      var validDataCount = 0;
      data.each(valueDim, function (value) {
        !isNaN(value) && validDataCount++;
      });
      var sum = data.getSum(valueDim);
      var unitRadian = Math.PI / (sum || validDataCount) * 2;
      var clockwise = seriesModel.get('clockwise');
      var roseType = seriesModel.get('roseType');
      var stillShowZeroSum = seriesModel.get('stillShowZeroSum');
      var extent = data.getDataExtent(valueDim);
      extent[0] = 0;
      var restAngle = PI2$8;
      var valueSumLargerThanMinAngle = 0;
      var currentAngle = startAngle;
      var dir = clockwise ? 1 : -1;
      data.setLayout({
        viewRect: viewRect,
        r: r
      });
      data.each(valueDim, function (value, idx) {
        var angle;

        if (isNaN(value)) {
          data.setItemLayout(idx, {
            angle: NaN,
            startAngle: NaN,
            endAngle: NaN,
            clockwise: clockwise,
            cx: cx,
            cy: cy,
            r0: r0,
            r: roseType ? NaN : r
          });
          return;
        }

        if (roseType !== 'area') {
          angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian;
        } else {
          angle = PI2$8 / validDataCount;
        }

        if (angle < minAngle) {
          angle = minAngle;
          restAngle -= minAngle;
        } else {
          valueSumLargerThanMinAngle += value;
        }

        var endAngle = currentAngle + dir * angle;
        data.setItemLayout(idx, {
          angle: angle,
          startAngle: currentAngle,
          endAngle: endAngle,
          clockwise: clockwise,
          cx: cx,
          cy: cy,
          r0: r0,
          r: roseType ? linearMap(value, extent, [r0, r]) : r
        });
        currentAngle = endAngle;
      });

      if (restAngle < PI2$8 && validDataCount) {
        if (restAngle <= 1e-3) {
          var angle_1 = PI2$8 / validDataCount;
          data.each(valueDim, function (value, idx) {
            if (!isNaN(value)) {
              var layout_1 = data.getItemLayout(idx);
              layout_1.angle = angle_1;
              layout_1.startAngle = startAngle + dir * idx * angle_1;
              layout_1.endAngle = startAngle + dir * (idx + 1) * angle_1;
            }
          });
        } else {
          unitRadian = restAngle / valueSumLargerThanMinAngle;
          currentAngle = startAngle;
          data.each(valueDim, function (value, idx) {
            if (!isNaN(value)) {
              var layout_2 = data.getItemLayout(idx);
              var angle = layout_2.angle === minAngle ? minAngle : value * unitRadian;
              layout_2.startAngle = currentAngle;
              layout_2.endAngle = currentAngle + dir * angle;
              currentAngle += dir * angle;
            }
          });
        }
      }
    });
  }

  function dataFilter(seriesType) {
    return {
      seriesType: seriesType,
      reset: function (seriesModel, ecModel) {
        var legendModels = ecModel.findComponents({
          mainType: 'legend'
        });

        if (!legendModels || !legendModels.length) {
          return;
        }

        var data = seriesModel.getData();
        data.filterSelf(function (idx) {
          var name = data.getName(idx);

          for (var i = 0; i < legendModels.length; i++) {
            if (!legendModels[i].isSelected(name)) {
              return false;
            }
          }

          return true;
        });
      }
    };
  }

  createLegacyDataSelectAction('pie', registerAction);
  registerLayout(curry(pieLayout, 'pie'));
  registerProcessor(dataFilter('pie'));

  var ScatterSeriesModel = function (_super) {
    __extends(ScatterSeriesModel, _super);

    function ScatterSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ScatterSeriesModel.type;
      _this.hasSymbolVisual = true;
      return _this;
    }

    ScatterSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this, {
        useEncodeDefaulter: true
      });
    };

    ScatterSeriesModel.prototype.getProgressive = function () {
      var progressive = this.option.progressive;

      if (progressive == null) {
        return this.option.large ? 5e3 : this.get('progressive');
      }

      return progressive;
    };

    ScatterSeriesModel.prototype.getProgressiveThreshold = function () {
      var progressiveThreshold = this.option.progressiveThreshold;

      if (progressiveThreshold == null) {
        return this.option.large ? 1e4 : this.get('progressiveThreshold');
      }

      return progressiveThreshold;
    };

    ScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) {
      return selectors.point(data.getItemLayout(dataIndex));
    };

    ScatterSeriesModel.type = 'series.scatter';
    ScatterSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar'];
    ScatterSeriesModel.defaultOption = {
      coordinateSystem: 'cartesian2d',
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      symbolSize: 10,
      large: false,
      largeThreshold: 2000,
      itemStyle: {
        opacity: 0.8
      },
      emphasis: {
        scale: true
      },
      clip: true,
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      }
    };
    return ScatterSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(ScatterSeriesModel);
  var BOOST_SIZE_THRESHOLD = 4;

  var LargeSymbolPathShape = function () {
    function LargeSymbolPathShape() {}

    return LargeSymbolPathShape;
  }();

  var LargeSymbolPath = function (_super) {
    __extends(LargeSymbolPath, _super);

    function LargeSymbolPath(opts) {
      return _super.call(this, opts) || this;
    }

    LargeSymbolPath.prototype.getDefaultShape = function () {
      return new LargeSymbolPathShape();
    };

    LargeSymbolPath.prototype.buildPath = function (path, shape) {
      var points = shape.points;
      var size = shape.size;
      var symbolProxy = this.symbolProxy;
      var symbolProxyShape = symbolProxy.shape;
      var ctx = path.getContext ? path.getContext() : path;
      var canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD;

      if (canBoost) {
        this._ctx = ctx;
        return;
      }

      this._ctx = null;

      for (var i = 0; i < points.length;) {
        var x = points[i++];
        var y = points[i++];

        if (isNaN(x) || isNaN(y)) {
          continue;
        }

        if (this.softClipShape && !this.softClipShape.contain(x, y)) {
          continue;
        }

        symbolProxyShape.x = x - size[0] / 2;
        symbolProxyShape.y = y - size[1] / 2;
        symbolProxyShape.width = size[0];
        symbolProxyShape.height = size[1];
        symbolProxy.buildPath(path, symbolProxyShape, true);
      }
    };

    LargeSymbolPath.prototype.afterBrush = function () {
      var shape = this.shape;
      var points = shape.points;
      var size = shape.size;
      var ctx = this._ctx;

      if (!ctx) {
        return;
      }

      for (var i = 0; i < points.length;) {
        var x = points[i++];
        var y = points[i++];

        if (isNaN(x) || isNaN(y)) {
          continue;
        }

        if (this.softClipShape && !this.softClipShape.contain(x, y)) {
          continue;
        }

        ctx.fillRect(x - size[0] / 2, y - size[1] / 2, size[0], size[1]);
      }
    };

    LargeSymbolPath.prototype.findDataIndex = function (x, y) {
      var shape = this.shape;
      var points = shape.points;
      var size = shape.size;
      var w = Math.max(size[0], 4);
      var h = Math.max(size[1], 4);

      for (var idx = points.length / 2 - 1; idx >= 0; idx--) {
        var i = idx * 2;
        var x0 = points[i] - w / 2;
        var y0 = points[i + 1] - h / 2;

        if (x >= x0 && y >= y0 && x <= x0 + w && y <= y0 + h) {
          return idx;
        }
      }

      return -1;
    };

    return LargeSymbolPath;
  }(Path);

  var LargeSymbolDraw = function () {
    function LargeSymbolDraw() {
      this.group = new Group();
    }

    LargeSymbolDraw.prototype.isPersistent = function () {
      return !this._incremental;
    };

    LargeSymbolDraw.prototype.updateData = function (data, opt) {
      this.group.removeAll();
      var symbolEl = new LargeSymbolPath({
        rectHover: true,
        cursor: 'default'
      });
      symbolEl.setShape({
        points: data.getLayout('points')
      });

      this._setCommon(symbolEl, data, false, opt);

      this.group.add(symbolEl);
      this._incremental = null;
    };

    LargeSymbolDraw.prototype.updateLayout = function (data) {
      if (this._incremental) {
        return;
      }

      var points = data.getLayout('points');
      this.group.eachChild(function (child) {
        if (child.startIndex != null) {
          var len = (child.endIndex - child.startIndex) * 2;
          var byteOffset = child.startIndex * 4 * 2;
          points = new Float32Array(points.buffer, byteOffset, len);
        }

        child.setShape('points', points);
      });
    };

    LargeSymbolDraw.prototype.incrementalPrepareUpdate = function (data) {
      this.group.removeAll();

      this._clearIncremental();

      if (data.count() > 2e6) {
        if (!this._incremental) {
          this._incremental = new IncrementalDisplayble({
            silent: true
          });
        }

        this.group.add(this._incremental);
      } else {
        this._incremental = null;
      }
    };

    LargeSymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) {
      var symbolEl;

      if (this._incremental) {
        symbolEl = new LargeSymbolPath();

        this._incremental.addDisplayable(symbolEl, true);
      } else {
        symbolEl = new LargeSymbolPath({
          rectHover: true,
          cursor: 'default',
          startIndex: taskParams.start,
          endIndex: taskParams.end
        });
        symbolEl.incremental = true;
        this.group.add(symbolEl);
      }

      symbolEl.setShape({
        points: data.getLayout('points')
      });

      this._setCommon(symbolEl, data, !!this._incremental, opt);
    };

    LargeSymbolDraw.prototype._setCommon = function (symbolEl, data, isIncremental, opt) {
      var hostModel = data.hostModel;
      opt = opt || {};
      var size = data.getVisual('symbolSize');
      symbolEl.setShape('size', size instanceof Array ? size : [size, size]);
      symbolEl.softClipShape = opt.clipShape || null;
      symbolEl.symbolProxy = createSymbol(data.getVisual('symbol'), 0, 0, 0, 0);
      symbolEl.setColor = symbolEl.symbolProxy.setColor;
      var extrudeShadow = symbolEl.shape.size[0] < BOOST_SIZE_THRESHOLD;
      symbolEl.useStyle(hostModel.getModel('itemStyle').getItemStyle(extrudeShadow ? ['color', 'shadowBlur', 'shadowColor'] : ['color']));
      var globalStyle = data.getVisual('style');
      var visualColor = globalStyle && globalStyle.fill;

      if (visualColor) {
        symbolEl.setColor(visualColor);
      }

      if (!isIncremental) {
        var ecData_1 = getECData(symbolEl);
        ecData_1.seriesIndex = hostModel.seriesIndex;
        symbolEl.on('mousemove', function (e) {
          ecData_1.dataIndex = null;
          var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);

          if (dataIndex >= 0) {
            ecData_1.dataIndex = dataIndex + (symbolEl.startIndex || 0);
          }
        });
      }
    };

    LargeSymbolDraw.prototype.remove = function () {
      this._clearIncremental();

      this._incremental = null;
      this.group.removeAll();
    };

    LargeSymbolDraw.prototype._clearIncremental = function () {
      var incremental = this._incremental;

      if (incremental) {
        incremental.clearDisplaybles();
      }
    };

    return LargeSymbolDraw;
  }();

  var ScatterView = function (_super) {
    __extends(ScatterView, _super);

    function ScatterView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ScatterView.type;
      return _this;
    }

    ScatterView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();

      var symbolDraw = this._updateSymbolDraw(data, seriesModel);

      symbolDraw.updateData(data, {
        clipShape: this._getClipShape(seriesModel)
      });
      this._finished = true;
    };

    ScatterView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();

      var symbolDraw = this._updateSymbolDraw(data, seriesModel);

      symbolDraw.incrementalPrepareUpdate(data);
      this._finished = false;
    };

    ScatterView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) {
      this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData(), {
        clipShape: this._getClipShape(seriesModel)
      });

      this._finished = taskParams.end === seriesModel.getData().count();
    };

    ScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      this.group.dirty();

      if (!this._finished || data.count() > 1e4 || !this._symbolDraw.isPersistent()) {
        return {
          update: true
        };
      } else {
        var res = pointsLayout('').reset(seriesModel, ecModel, api);

        if (res.progress) {
          res.progress({
            start: 0,
            end: data.count(),
            count: data.count()
          }, data);
        }

        this._symbolDraw.updateLayout(data);
      }
    };

    ScatterView.prototype._getClipShape = function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var clipArea = coordSys && coordSys.getArea && coordSys.getArea();
      return seriesModel.get('clip', true) ? clipArea : null;
    };

    ScatterView.prototype._updateSymbolDraw = function (data, seriesModel) {
      var symbolDraw = this._symbolDraw;
      var pipelineContext = seriesModel.pipelineContext;
      var isLargeDraw = pipelineContext.large;

      if (!symbolDraw || isLargeDraw !== this._isLargeDraw) {
        symbolDraw && symbolDraw.remove();
        symbolDraw = this._symbolDraw = isLargeDraw ? new LargeSymbolDraw() : new SymbolDraw();
        this._isLargeDraw = isLargeDraw;
        this.group.removeAll();
      }

      this.group.add(symbolDraw.group);
      return symbolDraw;
    };

    ScatterView.prototype.remove = function (ecModel, api) {
      this._symbolDraw && this._symbolDraw.remove(true);
      this._symbolDraw = null;
    };

    ScatterView.prototype.dispose = function () {};

    ScatterView.type = 'scatter';
    return ScatterView;
  }(ChartView);

  ChartView.registerClass(ScatterView);
  registerLayout(pointsLayout('scatter'));

  var IndicatorAxis = function (_super) {
    __extends(IndicatorAxis, _super);

    function IndicatorAxis(dim, scale, radiusExtent) {
      var _this = _super.call(this, dim, scale, radiusExtent) || this;

      _this.type = 'value';
      _this.angle = 0;
      _this.name = '';
      return _this;
    }

    return IndicatorAxis;
  }(Axis);

  var Radar = function () {
    function Radar(radarModel, ecModel, api) {
      this.dimensions = [];
      this._model = radarModel;
      this._indicatorAxes = map(radarModel.getIndicatorModels(), function (indicatorModel, idx) {
        var dim = 'indicator_' + idx;
        var indicatorAxis = new IndicatorAxis(dim, new IntervalScale());
        indicatorAxis.name = indicatorModel.get('name');
        indicatorAxis.model = indicatorModel;
        indicatorModel.axis = indicatorAxis;
        this.dimensions.push(dim);
        return indicatorAxis;
      }, this);
      this.resize(radarModel, api);
    }

    Radar.prototype.getIndicatorAxes = function () {
      return this._indicatorAxes;
    };

    Radar.prototype.dataToPoint = function (value, indicatorIndex) {
      var indicatorAxis = this._indicatorAxes[indicatorIndex];
      return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex);
    };

    Radar.prototype.coordToPoint = function (coord, indicatorIndex) {
      var indicatorAxis = this._indicatorAxes[indicatorIndex];
      var angle = indicatorAxis.angle;
      var x = this.cx + coord * Math.cos(angle);
      var y = this.cy - coord * Math.sin(angle);
      return [x, y];
    };

    Radar.prototype.pointToData = function (pt) {
      var dx = pt[0] - this.cx;
      var dy = pt[1] - this.cy;
      var radius = Math.sqrt(dx * dx + dy * dy);
      dx /= radius;
      dy /= radius;
      var radian = Math.atan2(-dy, dx);
      var minRadianDiff = Infinity;
      var closestAxis;
      var closestAxisIdx = -1;

      for (var i = 0; i < this._indicatorAxes.length; i++) {
        var indicatorAxis = this._indicatorAxes[i];
        var diff = Math.abs(radian - indicatorAxis.angle);

        if (diff < minRadianDiff) {
          closestAxis = indicatorAxis;
          closestAxisIdx = i;
          minRadianDiff = diff;
        }
      }

      return [closestAxisIdx, +(closestAxis && closestAxis.coordToData(radius))];
    };

    Radar.prototype.resize = function (radarModel, api) {
      var center = radarModel.get('center');
      var viewWidth = api.getWidth();
      var viewHeight = api.getHeight();
      var viewSize = Math.min(viewWidth, viewHeight) / 2;
      this.cx = parsePercent$2(center[0], viewWidth);
      this.cy = parsePercent$2(center[1], viewHeight);
      this.startAngle = radarModel.get('startAngle') * Math.PI / 180;
      var radius = radarModel.get('radius');

      if (typeof radius === 'string' || typeof radius === 'number') {
        radius = [0, radius];
      }

      this.r0 = parsePercent$2(radius[0], viewSize);
      this.r = parsePercent$2(radius[1], viewSize);
      each(this._indicatorAxes, function (indicatorAxis, idx) {
        indicatorAxis.setExtent(this.r0, this.r);
        var angle = this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length;
        angle = Math.atan2(Math.sin(angle), Math.cos(angle));
        indicatorAxis.angle = angle;
      }, this);
    };

    Radar.prototype.update = function (ecModel, api) {
      var indicatorAxes = this._indicatorAxes;
      var radarModel = this._model;
      each(indicatorAxes, function (indicatorAxis) {
        indicatorAxis.scale.setExtent(Infinity, -Infinity);
      });
      ecModel.eachSeriesByType('radar', function (radarSeries, idx) {
        if (radarSeries.get('coordinateSystem') !== 'radar' || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel) {
          return;
        }

        var data = radarSeries.getData();
        each(indicatorAxes, function (indicatorAxis) {
          indicatorAxis.scale.unionExtentFromData(data, data.mapDimension(indicatorAxis.dim));
        });
      }, this);
      var splitNumber = radarModel.get('splitNumber');

      function increaseInterval(interval) {
        var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10));
        var f = interval / exp10;

        if (f === 2) {
          f = 5;
        } else {
          f *= 2;
        }

        return f * exp10;
      }

      each(indicatorAxes, function (indicatorAxis, idx) {
        var rawExtent = getScaleExtent(indicatorAxis.scale, indicatorAxis.model).extent;
        niceScaleExtent(indicatorAxis.scale, indicatorAxis.model);
        var axisModel = indicatorAxis.model;
        var scale = indicatorAxis.scale;
        var fixedMin = parseAxisModelMinMax(scale, axisModel.get('min', true));
        var fixedMax = parseAxisModelMinMax(scale, axisModel.get('max', true));
        var interval = scale.getInterval();

        if (fixedMin != null && fixedMax != null) {
          scale.setExtent(+fixedMin, +fixedMax);
          scale.setInterval((fixedMax - fixedMin) / splitNumber);
        } else if (fixedMin != null) {
          var max = void 0;

          do {
            max = fixedMin + interval * splitNumber;
            scale.setExtent(+fixedMin, max);
            scale.setInterval(interval);
            interval = increaseInterval(interval);
          } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1]));
        } else if (fixedMax != null) {
          var min = void 0;

          do {
            min = fixedMax - interval * splitNumber;
            scale.setExtent(min, +fixedMax);
            scale.setInterval(interval);
            interval = increaseInterval(interval);
          } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0]));
        } else {
          var nicedSplitNumber = scale.getTicks().length - 1;

          if (nicedSplitNumber > splitNumber) {
            interval = increaseInterval(interval);
          }

          var max = Math.ceil(rawExtent[1] / interval) * interval;
          var min = round$1(max - interval * splitNumber);
          scale.setExtent(min, max);
          scale.setInterval(interval);
        }
      });
    };

    Radar.prototype.convertToPixel = function (ecModel, finder, value) {
      console.warn('Not implemented.');
      return null;
    };

    Radar.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      console.warn('Not implemented.');
      return null;
    };

    Radar.prototype.containPoint = function (point) {
      console.warn('Not implemented.');
      return false;
    };

    Radar.create = function (ecModel, api) {
      var radarList = [];
      ecModel.eachComponent('radar', function (radarModel) {
        var radar = new Radar(radarModel, ecModel, api);
        radarList.push(radar);
        radarModel.coordinateSystem = radar;
      });
      ecModel.eachSeriesByType('radar', function (radarSeries) {
        if (radarSeries.get('coordinateSystem') === 'radar') {
          radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0];
        }
      });
      return radarList;
    };

    Radar.dimensions = [];
    return Radar;
  }();

  CoordinateSystemManager.register('radar', Radar);
  var valueAxisDefault = axisDefault.value;

  function defaultsShow(opt, show) {
    return defaults({
      show: show
    }, opt);
  }

  var RadarModel = function (_super) {
    __extends(RadarModel, _super);

    function RadarModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadarModel.type;
      return _this;
    }

    RadarModel.prototype.optionUpdated = function () {
      var boundaryGap = this.get('boundaryGap');
      var splitNumber = this.get('splitNumber');
      var scale = this.get('scale');
      var axisLine = this.get('axisLine');
      var axisTick = this.get('axisTick');
      var axisLabel = this.get('axisLabel');
      var nameTextStyle = this.get('axisName');
      var showName = this.get(['axisName', 'show']);
      var nameFormatter = this.get(['axisName', 'formatter']);
      var nameGap = this.get('axisNameGap');
      var triggerEvent = this.get('triggerEvent');
      var indicatorModels = map(this.get('indicator') || [], function (indicatorOpt) {
        if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) {
          indicatorOpt.min = 0;
        } else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) {
          indicatorOpt.max = 0;
        }

        var iNameTextStyle = nameTextStyle;

        if (indicatorOpt.color != null) {
          iNameTextStyle = defaults({
            color: indicatorOpt.color
          }, nameTextStyle);
        }

        var innerIndicatorOpt = merge(clone(indicatorOpt), {
          boundaryGap: boundaryGap,
          splitNumber: splitNumber,
          scale: scale,
          axisLine: axisLine,
          axisTick: axisTick,
          axisLabel: axisLabel,
          name: indicatorOpt.text,
          nameLocation: 'end',
          nameGap: nameGap,
          nameTextStyle: iNameTextStyle,
          triggerEvent: triggerEvent
        }, false);

        if (!showName) {
          innerIndicatorOpt.name = '';
        }

        if (typeof nameFormatter === 'string') {
          var indName = innerIndicatorOpt.name;
          innerIndicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : '');
        } else if (typeof nameFormatter === 'function') {
          innerIndicatorOpt.name = nameFormatter(innerIndicatorOpt.name, innerIndicatorOpt);
        }

        var model = new Model(innerIndicatorOpt, null, this.ecModel);
        mixin(model, AxisModelCommonMixin.prototype);
        model.mainType = 'radar';
        model.componentIndex = this.componentIndex;
        return model;
      }, this);
      this._indicatorModels = indicatorModels;
    };

    RadarModel.prototype.getIndicatorModels = function () {
      return this._indicatorModels;
    };

    RadarModel.type = 'radar';
    RadarModel.defaultOption = {
      zlevel: 0,
      z: 0,
      center: ['50%', '50%'],
      radius: '75%',
      startAngle: 90,
      axisName: {
        show: true
      },
      boundaryGap: [0, 0],
      splitNumber: 5,
      axisNameGap: 15,
      scale: false,
      shape: 'polygon',
      axisLine: merge({
        lineStyle: {
          color: '#bbb'
        }
      }, valueAxisDefault.axisLine),
      axisLabel: defaultsShow(valueAxisDefault.axisLabel, false),
      axisTick: defaultsShow(valueAxisDefault.axisTick, false),
      splitLine: defaultsShow(valueAxisDefault.splitLine, true),
      splitArea: defaultsShow(valueAxisDefault.splitArea, true),
      indicator: []
    };
    return RadarModel;
  }(ComponentModel);

  ComponentModel.registerClass(RadarModel);
  var axisBuilderAttrs$1 = ['axisLine', 'axisTickLabel', 'axisName'];

  var RadarView = function (_super) {
    __extends(RadarView, _super);

    function RadarView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadarView.type;
      return _this;
    }

    RadarView.prototype.render = function (radarModel, ecModel, api) {
      var group = this.group;
      group.removeAll();

      this._buildAxes(radarModel);

      this._buildSplitLineAndArea(radarModel);
    };

    RadarView.prototype._buildAxes = function (radarModel) {
      var radar = radarModel.coordinateSystem;
      var indicatorAxes = radar.getIndicatorAxes();
      var axisBuilders = map(indicatorAxes, function (indicatorAxis) {
        var axisBuilder = new AxisBuilder(indicatorAxis.model, {
          position: [radar.cx, radar.cy],
          rotation: indicatorAxis.angle,
          labelDirection: -1,
          tickDirection: -1,
          nameDirection: 1
        });
        return axisBuilder;
      });
      each(axisBuilders, function (axisBuilder) {
        each(axisBuilderAttrs$1, axisBuilder.add, axisBuilder);
        this.group.add(axisBuilder.getGroup());
      }, this);
    };

    RadarView.prototype._buildSplitLineAndArea = function (radarModel) {
      var radar = radarModel.coordinateSystem;
      var indicatorAxes = radar.getIndicatorAxes();

      if (!indicatorAxes.length) {
        return;
      }

      var shape = radarModel.get('shape');
      var splitLineModel = radarModel.getModel('splitLine');
      var splitAreaModel = radarModel.getModel('splitArea');
      var lineStyleModel = splitLineModel.getModel('lineStyle');
      var areaStyleModel = splitAreaModel.getModel('areaStyle');
      var showSplitLine = splitLineModel.get('show');
      var showSplitArea = splitAreaModel.get('show');
      var splitLineColors = lineStyleModel.get('color');
      var splitAreaColors = areaStyleModel.get('color');
      var splitLineColorsArr = isArray(splitLineColors) ? splitLineColors : [splitLineColors];
      var splitAreaColorsArr = isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors];
      var splitLines = [];
      var splitAreas = [];

      function getColorIndex(areaOrLine, areaOrLineColorList, idx) {
        var colorIndex = idx % areaOrLineColorList.length;
        areaOrLine[colorIndex] = areaOrLine[colorIndex] || [];
        return colorIndex;
      }

      if (shape === 'circle') {
        var ticksRadius = indicatorAxes[0].getTicksCoords();
        var cx = radar.cx;
        var cy = radar.cy;

        for (var i = 0; i < ticksRadius.length; i++) {
          if (showSplitLine) {
            var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i);
            splitLines[colorIndex].push(new Circle({
              shape: {
                cx: cx,
                cy: cy,
                r: ticksRadius[i].coord
              }
            }));
          }

          if (showSplitArea && i < ticksRadius.length - 1) {
            var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i);
            splitAreas[colorIndex].push(new Ring({
              shape: {
                cx: cx,
                cy: cy,
                r0: ticksRadius[i].coord,
                r: ticksRadius[i + 1].coord
              }
            }));
          }
        }
      } else {
        var realSplitNumber_1;
        var axesTicksPoints = map(indicatorAxes, function (indicatorAxis, idx) {
          var ticksCoords = indicatorAxis.getTicksCoords();
          realSplitNumber_1 = realSplitNumber_1 == null ? ticksCoords.length - 1 : Math.min(ticksCoords.length - 1, realSplitNumber_1);
          return map(ticksCoords, function (tickCoord) {
            return radar.coordToPoint(tickCoord.coord, idx);
          });
        });
        var prevPoints = [];

        for (var i = 0; i <= realSplitNumber_1; i++) {
          var points = [];

          for (var j = 0; j < indicatorAxes.length; j++) {
            points.push(axesTicksPoints[j][i]);
          }

          if (points[0]) {
            points.push(points[0].slice());
          } else {
            if (true) {
              console.error('Can\'t draw value axis ' + i);
            }
          }

          if (showSplitLine) {
            var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i);
            splitLines[colorIndex].push(new Polyline({
              shape: {
                points: points
              }
            }));
          }

          if (showSplitArea && prevPoints) {
            var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i - 1);
            splitAreas[colorIndex].push(new Polygon({
              shape: {
                points: points.concat(prevPoints)
              }
            }));
          }

          prevPoints = points.slice().reverse();
        }
      }

      var lineStyle = lineStyleModel.getLineStyle();
      var areaStyle = areaStyleModel.getAreaStyle();
      each(splitAreas, function (splitAreas, idx) {
        this.group.add(mergePath$1(splitAreas, {
          style: defaults({
            stroke: 'none',
            fill: splitAreaColorsArr[idx % splitAreaColorsArr.length]
          }, areaStyle),
          silent: true
        }));
      }, this);
      each(splitLines, function (splitLines, idx) {
        this.group.add(mergePath$1(splitLines, {
          style: defaults({
            fill: 'none',
            stroke: splitLineColorsArr[idx % splitLineColorsArr.length]
          }, lineStyle),
          silent: true
        }));
      }, this);
    };

    RadarView.type = 'radar';
    return RadarView;
  }(ComponentView);

  ComponentView.registerClass(RadarView);

  var RadarSeriesModel = function (_super) {
    __extends(RadarSeriesModel, _super);

    function RadarSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadarSeriesModel.type;
      _this.useColorPaletteOnData = true;
      _this.hasSymbolVisual = true;
      return _this;
    }

    RadarSeriesModel.prototype.init = function (option) {
      _super.prototype.init.apply(this, arguments);

      this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this));
    };

    RadarSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListSimply(this, {
        generateCoord: 'indicator_',
        generateCoordCount: Infinity
      });
    };

    RadarSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var coordSys = this.coordinateSystem;
      var indicatorAxes = coordSys.getIndicatorAxes();
      var name = this.getData().getName(dataIndex);
      var nameToDisplay = name === '' ? this.name : name;
      var markerColor = retrieveVisualColorForTooltipMarker(this, dataIndex);
      return createTooltipMarkup('section', {
        header: nameToDisplay,
        sortBlocks: true,
        blocks: map(indicatorAxes, function (axis) {
          var val = data.get(data.mapDimension(axis.dim), dataIndex);
          return createTooltipMarkup('nameValue', {
            markerType: 'subItem',
            markerColor: markerColor,
            name: axis.name,
            value: val,
            sortParam: val
          });
        })
      });
    };

    RadarSeriesModel.prototype.getTooltipPosition = function (dataIndex) {
      if (dataIndex != null) {
        var data_1 = this.getData();
        var coordSys = this.coordinateSystem;
        var values = data_1.getValues(map(coordSys.dimensions, function (dim) {
          return data_1.mapDimension(dim);
        }), dataIndex);

        for (var i = 0, len = values.length; i < len; i++) {
          if (!isNaN(values[i])) {
            var indicatorAxes = coordSys.getIndicatorAxes();
            return coordSys.coordToPoint(indicatorAxes[i].dataToCoord(values[i]), i);
          }
        }
      }
    };

    RadarSeriesModel.type = 'series.radar';
    RadarSeriesModel.dependencies = ['radar'];
    RadarSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'radar',
      legendHoverLink: true,
      radarIndex: 0,
      lineStyle: {
        width: 2,
        type: 'solid'
      },
      label: {
        position: 'top'
      },
      symbol: 'emptyCircle',
      symbolSize: 4
    };
    return RadarSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(RadarSeriesModel);

  function normalizeSymbolSize(symbolSize) {
    if (!isArray(symbolSize)) {
      symbolSize = [+symbolSize, +symbolSize];
    }

    return symbolSize;
  }

  var RadarView$1 = function (_super) {
    __extends(RadarView, _super);

    function RadarView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadarView.type;
      return _this;
    }

    RadarView.prototype.render = function (seriesModel, ecModel, api) {
      var polar = seriesModel.coordinateSystem;
      var group = this.group;
      var data = seriesModel.getData();
      var oldData = this._data;

      function createSymbol$1(data, idx) {
        var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';

        if (symbolType === 'none') {
          return;
        }

        var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
        var symbolPath = createSymbol(symbolType, -1, -1, 2, 2);
        var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0;
        symbolPath.attr({
          style: {
            strokeNoScale: true
          },
          z2: 100,
          scaleX: symbolSize[0] / 2,
          scaleY: symbolSize[1] / 2,
          rotation: symbolRotate * Math.PI / 180 || 0
        });
        return symbolPath;
      }

      function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) {
        symbolGroup.removeAll();

        for (var i = 0; i < newPoints.length - 1; i++) {
          var symbolPath = createSymbol$1(data, idx);

          if (symbolPath) {
            symbolPath.__dimIdx = i;

            if (oldPoints[i]) {
              symbolPath.setPosition(oldPoints[i]);
              graphic[isInit ? 'initProps' : 'updateProps'](symbolPath, {
                x: newPoints[i][0],
                y: newPoints[i][1]
              }, seriesModel, idx);
            } else {
              symbolPath.setPosition(newPoints[i]);
            }

            symbolGroup.add(symbolPath);
          }
        }
      }

      function getInitialPoints(points) {
        return map(points, function (pt) {
          return [polar.cx, polar.cy];
        });
      }

      data.diff(oldData).add(function (idx) {
        var points = data.getItemLayout(idx);

        if (!points) {
          return;
        }

        var polygon = new Polygon();
        var polyline = new Polyline();
        var target = {
          shape: {
            points: points
          }
        };
        polygon.shape.points = getInitialPoints(points);
        polyline.shape.points = getInitialPoints(points);
        initProps(polygon, target, seriesModel, idx);
        initProps(polyline, target, seriesModel, idx);
        var itemGroup = new Group();
        var symbolGroup = new Group();
        itemGroup.add(polyline);
        itemGroup.add(polygon);
        itemGroup.add(symbolGroup);
        updateSymbols(polyline.shape.points, points, symbolGroup, data, idx, true);
        data.setItemGraphicEl(idx, itemGroup);
      }).update(function (newIdx, oldIdx) {
        var itemGroup = oldData.getItemGraphicEl(oldIdx);
        var polyline = itemGroup.childAt(0);
        var polygon = itemGroup.childAt(1);
        var symbolGroup = itemGroup.childAt(2);
        var target = {
          shape: {
            points: data.getItemLayout(newIdx)
          }
        };

        if (!target.shape.points) {
          return;
        }

        updateSymbols(polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false);
        updateProps(polyline, target, seriesModel);
        updateProps(polygon, target, seriesModel);
        data.setItemGraphicEl(newIdx, itemGroup);
      }).remove(function (idx) {
        group.remove(oldData.getItemGraphicEl(idx));
      }).execute();
      data.eachItemGraphicEl(function (itemGroup, idx) {
        var itemModel = data.getItemModel(idx);
        var polyline = itemGroup.childAt(0);
        var polygon = itemGroup.childAt(1);
        var symbolGroup = itemGroup.childAt(2);
        var itemStyle = data.getItemVisual(idx, 'style');
        var color = itemStyle.fill;
        group.add(itemGroup);
        polyline.useStyle(defaults(itemModel.getModel('lineStyle').getLineStyle(), {
          fill: 'none',
          stroke: color
        }));
        setStatesStylesFromModel(polyline, itemModel, 'lineStyle');
        setStatesStylesFromModel(polygon, itemModel, 'areaStyle');
        var areaStyleModel = itemModel.getModel('areaStyle');
        var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty();
        polygon.ignore = polygonIgnore;
        each(['emphasis', 'select', 'blur'], function (stateName) {
          var stateModel = itemModel.getModel([stateName, 'areaStyle']);
          var stateIgnore = stateModel.isEmpty() && stateModel.parentModel.isEmpty();
          polygon.ensureState(stateName).ignore = stateIgnore && polygonIgnore;
        });
        polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), {
          fill: color,
          opacity: 0.7,
          decal: itemStyle.decal
        }));
        var emphasisModel = itemModel.getModel('emphasis');
        var itemHoverStyle = emphasisModel.getModel('itemStyle').getItemStyle();
        symbolGroup.eachChild(function (symbolPath) {
          if (symbolPath instanceof ZRImage) {
            var pathStyle = symbolPath.style;
            symbolPath.useStyle(extend({
              image: pathStyle.image,
              x: pathStyle.x,
              y: pathStyle.y,
              width: pathStyle.width,
              height: pathStyle.height
            }, itemStyle));
          } else {
            symbolPath.useStyle(itemStyle);
            symbolPath.setColor(color);
          }

          var pathEmphasisState = symbolPath.ensureState('emphasis');
          pathEmphasisState.style = clone(itemHoverStyle);
          var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
          (defaultText == null || isNaN(defaultText)) && (defaultText = '');
          setLabelStyle(symbolPath, getLabelStatesModels(itemModel), {
            labelFetcher: data.hostModel,
            labelDataIndex: idx,
            labelDimIndex: symbolPath.__dimIdx,
            defaultText: defaultText,
            inheritColor: color,
            defaultOpacity: itemStyle.opacity
          });
        });
        enableHoverEmphasis(itemGroup, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
      });
      this._data = data;
    };

    RadarView.prototype.remove = function () {
      this.group.removeAll();
      this._data = null;
    };

    RadarView.type = 'radar';
    return RadarView;
  }(ChartView);

  ChartView.registerClass(RadarView$1);

  function radarLayout(ecModel) {
    ecModel.eachSeriesByType('radar', function (seriesModel) {
      var data = seriesModel.getData();
      var points = [];
      var coordSys = seriesModel.coordinateSystem;

      if (!coordSys) {
        return;
      }

      var axes = coordSys.getIndicatorAxes();
      each(axes, function (axis, axisIndex) {
        data.each(data.mapDimension(axes[axisIndex].dim), function (val, dataIndex) {
          points[dataIndex] = points[dataIndex] || [];
          var point = coordSys.dataToPoint(val, axisIndex);
          points[dataIndex][axisIndex] = isValidPoint(point) ? point : getValueMissingPoint(coordSys);
        });
      });
      data.each(function (idx) {
        var firstPoint = find(points[idx], function (point) {
          return isValidPoint(point);
        }) || getValueMissingPoint(coordSys);
        points[idx].push(firstPoint.slice());
        data.setItemLayout(idx, points[idx]);
      });
    });
  }

  function isValidPoint(point) {
    return !isNaN(point[0]) && !isNaN(point[1]);
  }

  function getValueMissingPoint(coordSys) {
    return [coordSys.cx, coordSys.cy];
  }

  function radarBackwardCompat(option) {
    var polarOptArr = option.polar;

    if (polarOptArr) {
      if (!isArray(polarOptArr)) {
        polarOptArr = [polarOptArr];
      }

      var polarNotRadar_1 = [];
      each(polarOptArr, function (polarOpt, idx) {
        if (polarOpt.indicator) {
          if (polarOpt.type && !polarOpt.shape) {
            polarOpt.shape = polarOpt.type;
          }

          option.radar = option.radar || [];

          if (!isArray(option.radar)) {
            option.radar = [option.radar];
          }

          option.radar.push(polarOpt);
        } else {
          polarNotRadar_1.push(polarOpt);
        }
      });
      option.polar = polarNotRadar_1;
    }

    each(option.series, function (seriesOpt) {
      if (seriesOpt && seriesOpt.type === 'radar' && seriesOpt.polarIndex) {
        seriesOpt.radarIndex = seriesOpt.polarIndex;
      }
    });
  }

  registerLayout(radarLayout);
  registerProcessor(dataFilter('radar'));
  registerPreprocessor(radarBackwardCompat);
  var geoCoord = [126, 25];
  var points$1 = [[[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7], [37, 70.7]], [[48, 51.1], [51, 45.5], [53, 45.5], [50, 51.1], [48, 51.1]], [[51, 35], [51, 28.7], [53, 28.7], [53, 35], [51, 35]], [[52, 22.4], [55, 17.5], [56, 17.5], [53, 22.4], [52, 22.4]], [[58, 12.6], [62, 7], [63, 7], [60, 12.6], [58, 12.6]], [[0, 3.5], [0, 93.1], [64, 93.1], [64, 0], [63, 0], [63, 92.4], [1, 92.4], [1, 3.5], [0, 3.5]]];

  for (var i = 0; i < points$1.length; i++) {
    for (var k = 0; k < points$1[i].length; k++) {
      points$1[i][k][0] /= 10.5;
      points$1[i][k][1] /= -10.5 / 0.75;
      points$1[i][k][0] += geoCoord[0];
      points$1[i][k][1] += geoCoord[1];
    }
  }

  function fixNanhai(mapType, regions) {
    if (mapType === 'china') {
      regions.push(new Region('南海诸岛', map(points$1, function (exterior) {
        return {
          type: 'polygon',
          exterior: exterior
        };
      }), geoCoord));
    }
  }

  var coordsOffsetMap = {
    '南海诸岛': [32, 80],
    '广东': [0, -10],
    '香港': [10, 5],
    '澳门': [-10, 10],
    '天津': [5, 5]
  };

  function fixTextCoords(mapType, region) {
    if (mapType === 'china') {
      var coordFix = coordsOffsetMap[region.name];

      if (coordFix) {
        var cp = region.center;
        cp[0] += coordFix[0] / 10.5;
        cp[1] += -coordFix[1] / (10.5 / 0.75);
      }
    }
  }

  var geoCoordMap = {
    'Russia': [100, 60],
    'United States': [-99, 38],
    'United States of America': [-99, 38]
  };

  function fixGeoCoords(mapType, region) {
    if (mapType === 'world') {
      var geoCoord = geoCoordMap[region.name];

      if (geoCoord) {
        var cp = region.center;
        cp[0] = geoCoord[0];
        cp[1] = geoCoord[1];
      }
    }
  }

  var points$2 = [[[123.45165252685547, 25.73527164402261], [123.49731445312499, 25.73527164402261], [123.49731445312499, 25.750734064600884], [123.45165252685547, 25.750734064600884], [123.45165252685547, 25.73527164402261]]];

  function fixDiaoyuIsland(mapType, region) {
    if (mapType === 'china' && region.name === '台湾') {
      region.geometries.push({
        type: 'polygon',
        exterior: points$2[0]
      });
    }
  }

  var inner$6 = makeInner();
  var geoJSONLoader = {
    load: function (mapName, mapRecord, nameProperty) {
      var parsed = inner$6(mapRecord).parsed;

      if (parsed) {
        return parsed;
      }

      var specialAreas = mapRecord.specialAreas || {};
      var geoJSON = mapRecord.geoJSON;
      var regions;

      try {
        regions = geoJSON ? parseGeoJSON(geoJSON, nameProperty) : [];
      } catch (e) {
        throw new Error('Invalid geoJson format\n' + e.message);
      }

      fixNanhai(mapName, regions);
      each(regions, function (region) {
        var regionName = region.name;
        fixTextCoords(mapName, region);
        fixGeoCoords(mapName, region);
        fixDiaoyuIsland(mapName, region);
        var specialArea = specialAreas[regionName];

        if (specialArea) {
          region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
        }
      });
      return inner$6(mapRecord).parsed = {
        regions: regions,
        boundingRect: getBoundingRect$1(regions)
      };
    }
  };

  function getBoundingRect$1(regions) {
    var rect;

    for (var i = 0; i < regions.length; i++) {
      var regionRect = regions[i].getBoundingRect();
      rect = rect || regionRect.clone();
      rect.union(regionRect);
    }

    return rect;
  }

  var inner$7 = makeInner();
  var geoSVGLoader = {
    load: function (mapName, mapRecord) {
      var originRoot = inner$7(mapRecord).originRoot;

      if (originRoot) {
        return {
          root: originRoot,
          boundingRect: inner$7(mapRecord).boundingRect
        };
      }

      var graphic = buildGraphic(mapRecord);
      inner$7(mapRecord).originRoot = graphic.root;
      inner$7(mapRecord).boundingRect = graphic.boundingRect;
      return graphic;
    },
    makeGraphic: function (mapName, mapRecord, hostKey) {
      var field = inner$7(mapRecord);
      var rootMap = field.rootMap || (field.rootMap = createHashMap());
      var root = rootMap.get(hostKey);

      if (root) {
        return root;
      }

      var originRoot = field.originRoot;
      var boundingRect = field.boundingRect;

      if (!field.originRootHostKey) {
        field.originRootHostKey = hostKey;
        root = originRoot;
      } else {
        root = buildGraphic(mapRecord, boundingRect).root;
      }

      return rootMap.set(hostKey, root);
    },
    removeGraphic: function (mapName, mapRecord, hostKey) {
      var field = inner$7(mapRecord);
      var rootMap = field.rootMap;
      rootMap && rootMap.removeKey(hostKey);

      if (hostKey === field.originRootHostKey) {
        field.originRootHostKey = null;
      }
    }
  };

  function buildGraphic(mapRecord, boundingRect) {
    var svgXML = mapRecord.svgXML;
    var result;
    var root;

    try {
      result = svgXML && parseSVG(svgXML, {
        ignoreViewBox: true,
        ignoreRootClip: true
      }) || {};
      root = result.root;
      assert(root != null);
    } catch (e) {
      throw new Error('Invalid svg format\n' + e.message);
    }

    var svgWidth = result.width;
    var svgHeight = result.height;
    var viewBoxRect = result.viewBoxRect;

    if (!boundingRect) {
      boundingRect = svgWidth == null || svgHeight == null ? root.getBoundingRect() : new BoundingRect(0, 0, 0, 0);

      if (svgWidth != null) {
        boundingRect.width = svgWidth;
      }

      if (svgHeight != null) {
        boundingRect.height = svgHeight;
      }
    }

    if (viewBoxRect) {
      var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect.width, boundingRect.height);
      var elRoot = root;
      root = new Group();
      root.add(elRoot);
      elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
      elRoot.x = viewBoxTransform.x;
      elRoot.y = viewBoxTransform.y;
    }

    root.setClipPath(new Rect({
      shape: boundingRect.plain()
    }));
    return {
      root: root,
      boundingRect: boundingRect
    };
  }

  var loaders = {
    geoJSON: geoJSONLoader,
    svg: geoSVGLoader
  };
  var geoSourceManager = {
    load: function (mapName, nameMap, nameProperty) {
      var regions = [];
      var regionsMap = createHashMap();
      var nameCoordMap = createHashMap();
      var boundingRect;
      var mapRecords = retrieveMap(mapName);
      each(mapRecords, function (record) {
        var singleSource = loaders[record.type].load(mapName, record, nameProperty);
        each(singleSource.regions, function (region) {
          var regionName = region.name;

          if (nameMap && nameMap.hasOwnProperty(regionName)) {
            region = region.cloneShallow(regionName = nameMap[regionName]);
          }

          regions.push(region);
          regionsMap.set(regionName, region);
          nameCoordMap.set(regionName, region.center);
        });
        var rect = singleSource.boundingRect;

        if (rect) {
          boundingRect ? boundingRect.union(rect) : boundingRect = rect.clone();
        }
      });
      return {
        regions: regions,
        regionsMap: regionsMap,
        nameCoordMap: nameCoordMap,
        boundingRect: boundingRect || new BoundingRect(0, 0, 0, 0)
      };
    },
    makeGraphic: function (mapName, hostKey) {
      var mapRecords = retrieveMap(mapName);
      var results = [];
      each(mapRecords, function (record) {
        var method = loaders[record.type].makeGraphic;
        method && results.push(method(mapName, record, hostKey));
      });
      return results;
    },
    removeGraphic: function (mapName, hostKey) {
      var mapRecords = retrieveMap(mapName);
      each(mapRecords, function (record) {
        var method = loaders[record.type].makeGraphic;
        method && method(mapName, record, hostKey);
      });
    }
  };

  function mapNotExistsError(mapName) {
    if (true) {
      console.error('Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.');
    }
  }

  function retrieveMap(mapName) {
    var mapRecords = mapDataStorage.retrieveMap(mapName) || [];

    if (true) {
      if (!mapRecords.length) {
        mapNotExistsError(mapName);
      }
    }

    return mapRecords;
  }

  var MapSeries = function (_super) {
    __extends(MapSeries, _super);

    function MapSeries() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MapSeries.type;
      _this.needsDrawMap = false;
      _this.seriesGroup = [];

      _this.getTooltipPosition = function (dataIndex) {
        if (dataIndex != null) {
          var name_1 = this.getData().getName(dataIndex);
          var geo = this.coordinateSystem;
          var region = geo.getRegion(name_1);
          return region && geo.dataToPoint(region.center);
        }
      };

      return _this;
    }

    MapSeries.prototype.getInitialData = function (option) {
      var data = createListSimply(this, {
        coordDimensions: ['value'],
        encodeDefaulter: curry(makeSeriesEncodeForNameBased, this)
      });
      var dataNameMap = createHashMap();
      var toAppendNames = [];

      for (var i = 0, len = data.count(); i < len; i++) {
        var name_2 = data.getName(i);
        dataNameMap.set(name_2, true);
      }

      var geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap, this.option.nameProperty);
      each(geoSource.regions, function (region) {
        var name = region.name;

        if (!dataNameMap.get(name)) {
          toAppendNames.push(name);
        }
      });
      data.appendValues([], toAppendNames);
      return data;
    };

    MapSeries.prototype.getHostGeoModel = function () {
      var geoIndex = this.option.geoIndex;
      return geoIndex != null ? this.ecModel.getComponent('geo', geoIndex) : null;
    };

    MapSeries.prototype.getMapType = function () {
      return (this.getHostGeoModel() || this).option.map;
    };

    MapSeries.prototype.getRawValue = function (dataIndex) {
      var data = this.getData();
      return data.get(data.mapDimension('value'), dataIndex);
    };

    MapSeries.prototype.getRegionModel = function (regionName) {
      var data = this.getData();
      return data.getItemModel(data.indexOfName(regionName));
    };

    MapSeries.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var value = this.getRawValue(dataIndex);
      var name = data.getName(dataIndex);
      var seriesGroup = this.seriesGroup;
      var seriesNames = [];

      for (var i = 0; i < seriesGroup.length; i++) {
        var otherIndex = seriesGroup[i].originalData.indexOfName(name);
        var valueDim = data.mapDimension('value');

        if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) {
          seriesNames.push(seriesGroup[i].name);
        }
      }

      return createTooltipMarkup('section', {
        header: seriesNames.join(', '),
        noHeader: !seriesNames.length,
        blocks: [createTooltipMarkup('nameValue', {
          name: name,
          value: value
        })]
      });
    };

    MapSeries.prototype.setZoom = function (zoom) {
      this.option.zoom = zoom;
    };

    MapSeries.prototype.setCenter = function (center) {
      this.option.center = center;
    };

    MapSeries.type = 'series.map';
    MapSeries.dependencies = ['geo'];
    MapSeries.layoutMode = 'box';
    MapSeries.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'geo',
      map: '',
      left: 'center',
      top: 'center',
      aspectScale: 0.75,
      showLegendSymbol: true,
      boundingCoords: null,
      center: null,
      zoom: 1,
      scaleLimit: null,
      selectedMode: true,
      label: {
        show: false,
        color: '#000'
      },
      itemStyle: {
        borderWidth: 0.5,
        borderColor: '#444',
        areaColor: '#eee'
      },
      emphasis: {
        label: {
          show: true,
          color: 'rgb(100,0,0)'
        },
        itemStyle: {
          areaColor: 'rgba(255,215,0,0.8)'
        }
      },
      select: {
        label: {
          show: true,
          color: 'rgb(100,0,0)'
        },
        itemStyle: {
          color: 'rgba(255,215,0,0.8)'
        }
      },
      nameProperty: 'name'
    };
    return MapSeries;
  }(SeriesModel);

  SeriesModel.registerClass(MapSeries);
  var ATTR = '\0_ec_interaction_mutex';

  function take(zr, resourceKey, userKey) {
    var store = getStore(zr);
    store[resourceKey] = userKey;
  }

  function release(zr, resourceKey, userKey) {
    var store = getStore(zr);
    var uKey = store[resourceKey];

    if (uKey === userKey) {
      store[resourceKey] = null;
    }
  }

  function isTaken(zr, resourceKey) {
    return !!getStore(zr)[resourceKey];
  }

  function getStore(zr) {
    return zr[ATTR] || (zr[ATTR] = {});
  }

  registerAction({
    type: 'takeGlobalCursor',
    event: 'globalCursorTaken',
    update: 'update'
  }, function () {});

  var RoamController = function (_super) {
    __extends(RoamController, _super);

    function RoamController(zr) {
      var _this = _super.call(this) || this;

      _this._zr = zr;
      var mousedownHandler = bind(_this._mousedownHandler, _this);
      var mousemoveHandler = bind(_this._mousemoveHandler, _this);
      var mouseupHandler = bind(_this._mouseupHandler, _this);
      var mousewheelHandler = bind(_this._mousewheelHandler, _this);
      var pinchHandler = bind(_this._pinchHandler, _this);

      _this.enable = function (controlType, opt) {
        this.disable();
        this._opt = defaults(clone(opt) || {}, {
          zoomOnMouseWheel: true,
          moveOnMouseMove: true,
          moveOnMouseWheel: false,
          preventDefaultMouseMove: true
        });

        if (controlType == null) {
          controlType = true;
        }

        if (controlType === true || controlType === 'move' || controlType === 'pan') {
          zr.on('mousedown', mousedownHandler);
          zr.on('mousemove', mousemoveHandler);
          zr.on('mouseup', mouseupHandler);
        }

        if (controlType === true || controlType === 'scale' || controlType === 'zoom') {
          zr.on('mousewheel', mousewheelHandler);
          zr.on('pinch', pinchHandler);
        }
      };

      _this.disable = function () {
        zr.off('mousedown', mousedownHandler);
        zr.off('mousemove', mousemoveHandler);
        zr.off('mouseup', mouseupHandler);
        zr.off('mousewheel', mousewheelHandler);
        zr.off('pinch', pinchHandler);
      };

      return _this;
    }

    RoamController.prototype.isDragging = function () {
      return this._dragging;
    };

    RoamController.prototype.isPinching = function () {
      return this._pinching;
    };

    RoamController.prototype.setPointerChecker = function (pointerChecker) {
      this.pointerChecker = pointerChecker;
    };

    RoamController.prototype.dispose = function () {
      this.disable();
    };

    RoamController.prototype._mousedownHandler = function (e) {
      if (isMiddleOrRightButtonOnMouseUpDown(e) || e.target && e.target.draggable) {
        return;
      }

      var x = e.offsetX;
      var y = e.offsetY;

      if (this.pointerChecker && this.pointerChecker(e, x, y)) {
        this._x = x;
        this._y = y;
        this._dragging = true;
      }
    };

    RoamController.prototype._mousemoveHandler = function (e) {
      if (!this._dragging || !isAvailableBehavior('moveOnMouseMove', e, this._opt) || e.gestureEvent === 'pinch' || isTaken(this._zr, 'globalPan')) {
        return;
      }

      var x = e.offsetX;
      var y = e.offsetY;
      var oldX = this._x;
      var oldY = this._y;
      var dx = x - oldX;
      var dy = y - oldY;
      this._x = x;
      this._y = y;
      this._opt.preventDefaultMouseMove && stop(e.event);
      trigger(this, 'pan', 'moveOnMouseMove', e, {
        dx: dx,
        dy: dy,
        oldX: oldX,
        oldY: oldY,
        newX: x,
        newY: y,
        isAvailableBehavior: null
      });
    };

    RoamController.prototype._mouseupHandler = function (e) {
      if (!isMiddleOrRightButtonOnMouseUpDown(e)) {
        this._dragging = false;
      }
    };

    RoamController.prototype._mousewheelHandler = function (e) {
      var shouldZoom = isAvailableBehavior('zoomOnMouseWheel', e, this._opt);
      var shouldMove = isAvailableBehavior('moveOnMouseWheel', e, this._opt);
      var wheelDelta = e.wheelDelta;
      var absWheelDeltaDelta = Math.abs(wheelDelta);
      var originX = e.offsetX;
      var originY = e.offsetY;

      if (wheelDelta === 0 || !shouldZoom && !shouldMove) {
        return;
      }

      if (shouldZoom) {
        var factor = absWheelDeltaDelta > 3 ? 1.4 : absWheelDeltaDelta > 1 ? 1.2 : 1.1;
        var scale = wheelDelta > 0 ? factor : 1 / factor;
        checkPointerAndTrigger(this, 'zoom', 'zoomOnMouseWheel', e, {
          scale: scale,
          originX: originX,
          originY: originY,
          isAvailableBehavior: null
        });
      }

      if (shouldMove) {
        var absDelta = Math.abs(wheelDelta);
        var scrollDelta = (wheelDelta > 0 ? 1 : -1) * (absDelta > 3 ? 0.4 : absDelta > 1 ? 0.15 : 0.05);
        checkPointerAndTrigger(this, 'scrollMove', 'moveOnMouseWheel', e, {
          scrollDelta: scrollDelta,
          originX: originX,
          originY: originY,
          isAvailableBehavior: null
        });
      }
    };

    RoamController.prototype._pinchHandler = function (e) {
      if (isTaken(this._zr, 'globalPan')) {
        return;
      }

      var scale = e.pinchScale > 1 ? 1.1 : 1 / 1.1;
      checkPointerAndTrigger(this, 'zoom', null, e, {
        scale: scale,
        originX: e.pinchX,
        originY: e.pinchY,
        isAvailableBehavior: null
      });
    };

    return RoamController;
  }(Eventful);

  function checkPointerAndTrigger(controller, eventName, behaviorToCheck, e, contollerEvent) {
    if (controller.pointerChecker && controller.pointerChecker(e, contollerEvent.originX, contollerEvent.originY)) {
      stop(e.event);
      trigger(controller, eventName, behaviorToCheck, e, contollerEvent);
    }
  }

  function trigger(controller, eventName, behaviorToCheck, e, contollerEvent) {
    contollerEvent.isAvailableBehavior = bind(isAvailableBehavior, null, behaviorToCheck, e);
    controller.trigger(eventName, contollerEvent);
  }

  function isAvailableBehavior(behaviorToCheck, e, settings) {
    var setting = settings[behaviorToCheck];
    return !behaviorToCheck || setting && (!isString(setting) || e.event[setting + 'Key']);
  }

  function updateViewOnPan(controllerHost, dx, dy) {
    var target = controllerHost.target;
    target.x += dx;
    target.y += dy;
    target.dirty();
  }

  function updateViewOnZoom(controllerHost, zoomDelta, zoomX, zoomY) {
    var target = controllerHost.target;
    var zoomLimit = controllerHost.zoomLimit;
    var newZoom = controllerHost.zoom = controllerHost.zoom || 1;
    newZoom *= zoomDelta;

    if (zoomLimit) {
      var zoomMin = zoomLimit.min || 0;
      var zoomMax = zoomLimit.max || Infinity;
      newZoom = Math.max(Math.min(zoomMax, newZoom), zoomMin);
    }

    var zoomScale = newZoom / controllerHost.zoom;
    controllerHost.zoom = newZoom;
    target.x -= (zoomX - target.x) * (zoomScale - 1);
    target.y -= (zoomY - target.y) * (zoomScale - 1);
    target.scaleX *= zoomScale;
    target.scaleY *= zoomScale;
    target.dirty();
  }

  var IRRELEVANT_EXCLUDES = {
    'axisPointer': 1,
    'tooltip': 1,
    'brush': 1
  };

  function onIrrelevantElement(e, api, targetCoordSysModel) {
    var model = api.getComponentByElement(e.topTarget);
    var coordSys = model && model.coordinateSystem;
    return model && model !== targetCoordSysModel && !IRRELEVANT_EXCLUDES.hasOwnProperty(model.mainType) && coordSys && coordSys.model !== targetCoordSysModel;
  }

  function getFixedItemStyle(model) {
    var itemStyle = model.getItemStyle();
    var areaColor = model.get('areaColor');

    if (areaColor != null) {
      itemStyle.fill = areaColor;
    }

    return itemStyle;
  }

  var MapDraw = function () {
    function MapDraw(api) {
      var group = new Group();
      this.uid = getUID('ec_map_draw');
      this._controller = new RoamController(api.getZr());
      this._controllerHost = {
        target: group
      };
      this.group = group;
      group.add(this._regionsGroup = new Group());
      group.add(this._backgroundGroup = new Group());
    }

    MapDraw.prototype.draw = function (mapOrGeoModel, ecModel, api, fromView, payload) {
      var isGeo = mapOrGeoModel.mainType === 'geo';
      var data = mapOrGeoModel.getData && mapOrGeoModel.getData();
      isGeo && ecModel.eachComponent({
        mainType: 'series',
        subType: 'map'
      }, function (mapSeries) {
        if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) {
          data = mapSeries.getData();
        }
      });
      var geo = mapOrGeoModel.coordinateSystem;

      this._updateBackground(geo);

      var regionsGroup = this._regionsGroup;
      var group = this.group;
      var transformInfo = geo.getTransformInfo();
      var isFirstDraw = !regionsGroup.childAt(0) || payload;
      var targetScaleX;
      var targetScaleY;

      if (isFirstDraw) {
        group.transform = transformInfo.roamTransform;
        group.decomposeTransform();
        group.dirty();
      } else {
        var target = new Transformable();
        target.transform = transformInfo.roamTransform;
        target.decomposeTransform();
        var props = {
          scaleX: target.scaleX,
          scaleY: target.scaleY,
          x: target.x,
          y: target.y
        };
        targetScaleX = target.scaleX;
        targetScaleY = target.scaleY;
        updateProps(group, props, mapOrGeoModel);
      }

      regionsGroup.removeAll();
      var nameMap = createHashMap();
      var isVisualEncodedByVisualMap = data && data.getVisual('visualMeta') && data.getVisual('visualMeta').length > 0;
      each(geo.regions, function (region) {
        var regionGroup = nameMap.get(region.name) || nameMap.set(region.name, new Group());
        var compoundPath = new CompoundPath({
          segmentIgnoreThreshold: 1,
          shape: {
            paths: []
          }
        });
        regionGroup.add(compoundPath);
        var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
        var itemStyleModel = regionModel.getModel('itemStyle');
        var emphasisModel = regionModel.getModel('emphasis');
        var emphasisItemStyleModel = emphasisModel.getModel('itemStyle');
        var blurItemStyleModel = regionModel.getModel(['blur', 'itemStyle']);
        var selectItemStyleModel = regionModel.getModel(['select', 'itemStyle']);
        var itemStyle = getFixedItemStyle(itemStyleModel);
        var emphasisItemStyle = getFixedItemStyle(emphasisItemStyleModel);
        var blurItemStyle = getFixedItemStyle(blurItemStyleModel);
        var selectItemStyle = getFixedItemStyle(selectItemStyleModel);
        var dataIdx;

        if (data) {
          dataIdx = data.indexOfName(region.name);
          var style = data.getItemVisual(dataIdx, 'style');
          var decal = data.getItemVisual(dataIdx, 'decal');

          if (isVisualEncodedByVisualMap && style.fill) {
            itemStyle.fill = style.fill;
          }

          if (decal) {
            itemStyle.decal = createOrUpdatePatternFromDecal(decal, api);
          }
        }

        var sx = transformInfo.rawScaleX;
        var sy = transformInfo.rawScaleY;
        var offsetX = transformInfo.rawX;
        var offsetY = transformInfo.rawY;

        var transformPoint = function (point) {
          return [point[0] * sx + offsetX, point[1] * sy + offsetY];
        };

        each(region.geometries, function (geometry) {
          if (geometry.type !== 'polygon') {
            return;
          }

          var points = [];

          for (var i = 0; i < geometry.exterior.length; ++i) {
            points.push(transformPoint(geometry.exterior[i]));
          }

          compoundPath.shape.paths.push(new Polygon({
            segmentIgnoreThreshold: 1,
            shape: {
              points: points
            }
          }));

          for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); ++i) {
            var interior = geometry.interiors[i];
            var points_1 = [];

            for (var j = 0; j < interior.length; ++j) {
              points_1.push(transformPoint(interior[j]));
            }

            compoundPath.shape.paths.push(new Polygon({
              segmentIgnoreThreshold: 1,
              shape: {
                points: points_1
              }
            }));
          }
        });
        compoundPath.setStyle(itemStyle);
        compoundPath.style.strokeNoScale = true;
        compoundPath.culling = true;
        compoundPath.ensureState('emphasis').style = emphasisItemStyle;
        compoundPath.ensureState('blur').style = blurItemStyle;
        compoundPath.ensureState('select').style = selectItemStyle;
        var showLabel = false;

        for (var i = 0; i < DISPLAY_STATES.length; i++) {
          var stateName = DISPLAY_STATES[i];

          if (regionModel.get(stateName === 'normal' ? ['label', 'show'] : [stateName, 'label', 'show'])) {
            showLabel = true;
            break;
          }
        }

        var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx));
        var itemLayout = data && data.getItemLayout(dataIdx);

        if (isGeo || isDataNaN && showLabel || itemLayout && itemLayout.showLabel) {
          var query = !isGeo ? dataIdx : region.name;
          var labelFetcher = void 0;

          if (!data || dataIdx >= 0) {
            labelFetcher = mapOrGeoModel;
          }

          var centerPt = transformPoint(region.center);
          var textEl = new ZRText({
            x: centerPt[0],
            y: centerPt[1],
            scaleX: 1 / group.scaleX,
            scaleY: 1 / group.scaleY,
            z2: 10,
            silent: true
          });
          setLabelStyle(textEl, getLabelStatesModels(regionModel), {
            labelFetcher: labelFetcher,
            labelDataIndex: query,
            defaultText: region.name
          }, {
            normal: {
              align: 'center',
              verticalAlign: 'middle'
            }
          });
          compoundPath.setTextContent(textEl);
          compoundPath.setTextConfig({
            local: true
          });
          compoundPath.disableLabelAnimation = true;

          if (!isFirstDraw) {
            updateProps(textEl, {
              scaleX: 1 / targetScaleX,
              scaleY: 1 / targetScaleY
            }, mapOrGeoModel);
          }
        }

        if (data) {
          data.setItemGraphicEl(dataIdx, regionGroup);
        } else {
          var regionModel_1 = mapOrGeoModel.getRegionModel(region.name);
          getECData(compoundPath).eventData = {
            componentType: 'geo',
            componentIndex: mapOrGeoModel.componentIndex,
            geoIndex: mapOrGeoModel.componentIndex,
            name: region.name,
            region: regionModel_1 && regionModel_1.option || {}
          };
        }

        var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
        groupRegions.push(region);
        regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
        enableHoverEmphasis(regionGroup, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
        regionsGroup.add(regionGroup);
      });

      this._updateController(mapOrGeoModel, ecModel, api);

      this._updateMapSelectHandler(mapOrGeoModel, regionsGroup, api, fromView);
    };

    MapDraw.prototype.remove = function () {
      this._regionsGroup.removeAll();

      this._backgroundGroup.removeAll();

      this._controller.dispose();

      this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid);
      this._mapName = null;
      this._controllerHost = null;
    };

    MapDraw.prototype._updateBackground = function (geo) {
      var mapName = geo.map;

      if (this._mapName !== mapName) {
        each(geoSourceManager.makeGraphic(mapName, this.uid), function (root) {
          this._backgroundGroup.add(root);
        }, this);
      }

      this._mapName = mapName;
    };

    MapDraw.prototype._updateController = function (mapOrGeoModel, ecModel, api) {
      var geo = mapOrGeoModel.coordinateSystem;
      var controller = this._controller;
      var controllerHost = this._controllerHost;
      controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit');
      controllerHost.zoom = geo.getZoom();
      controller.enable(mapOrGeoModel.get('roam') || false);
      var mainType = mapOrGeoModel.mainType;

      function makeActionBase() {
        var action = {
          type: 'geoRoam',
          componentType: mainType
        };
        action[mainType + 'Id'] = mapOrGeoModel.id;
        return action;
      }

      controller.off('pan').on('pan', function (e) {
        this._mouseDownFlag = false;
        updateViewOnPan(controllerHost, e.dx, e.dy);
        api.dispatchAction(extend(makeActionBase(), {
          dx: e.dx,
          dy: e.dy
        }));
      }, this);
      controller.off('zoom').on('zoom', function (e) {
        this._mouseDownFlag = false;
        updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
        api.dispatchAction(extend(makeActionBase(), {
          zoom: e.scale,
          originX: e.originX,
          originY: e.originY
        }));
        var group = this.group;

        this._regionsGroup.traverse(function (el) {
          var textContent = el.getTextContent();

          if (textContent) {
            textContent.scaleX = 1 / group.scaleX;
            textContent.scaleY = 1 / group.scaleY;
            textContent.markRedraw();
          }
        });
      }, this);
      controller.setPointerChecker(function (e, x, y) {
        return geo.getViewRectAfterRoam().contain(x, y) && !onIrrelevantElement(e, api, mapOrGeoModel);
      });
    };

    MapDraw.prototype._updateMapSelectHandler = function (mapOrGeoModel, regionsGroup, api, fromView) {
      var mapDraw = this;
      regionsGroup.off('mousedown');

      if (mapOrGeoModel.get('selectedMode')) {
        regionsGroup.on('mousedown', function () {
          mapDraw._mouseDownFlag = true;
        });
        regionsGroup.on('click', function (e) {
          if (!mapDraw._mouseDownFlag) {
            return;
          }

          mapDraw._mouseDownFlag = false;
        });
      }
    };

    return MapDraw;
  }();

  var MapView = function (_super) {
    __extends(MapView, _super);

    function MapView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MapView.type;
      return _this;
    }

    MapView.prototype.render = function (mapModel, ecModel, api, payload) {
      if (payload && payload.type === 'mapToggleSelect' && payload.from === this.uid) {
        return;
      }

      var group = this.group;
      group.removeAll();

      if (mapModel.getHostGeoModel()) {
        return;
      }

      if (!(payload && payload.type === 'geoRoam' && payload.componentType === 'series' && payload.seriesId === mapModel.id)) {
        if (mapModel.needsDrawMap) {
          var mapDraw = this._mapDraw || new MapDraw(api);
          group.add(mapDraw.group);
          mapDraw.draw(mapModel, ecModel, api, this, payload);
          this._mapDraw = mapDraw;
        } else {
          this._mapDraw && this._mapDraw.remove();
          this._mapDraw = null;
        }
      } else {
        var mapDraw = this._mapDraw;
        mapDraw && group.add(mapDraw.group);
      }

      mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') && this._renderSymbols(mapModel, ecModel, api);
    };

    MapView.prototype.remove = function () {
      this._mapDraw && this._mapDraw.remove();
      this._mapDraw = null;
      this.group.removeAll();
    };

    MapView.prototype.dispose = function () {
      this._mapDraw && this._mapDraw.remove();
      this._mapDraw = null;
    };

    MapView.prototype._renderSymbols = function (mapModel, ecModel, api) {
      var originalData = mapModel.originalData;
      var group = this.group;
      originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) {
        if (isNaN(value)) {
          return;
        }

        var layout = originalData.getItemLayout(originalDataIndex);

        if (!layout || !layout.point) {
          return;
        }

        var point = layout.point;
        var offset = layout.offset;
        var circle = new Circle({
          style: {
            fill: mapModel.getData().getVisual('style').fill
          },
          shape: {
            cx: point[0] + offset * 9,
            cy: point[1],
            r: 3
          },
          silent: true,
          z2: 8 + (!offset ? Z2_EMPHASIS_LIFT + 1 : 0)
        });

        if (!offset) {
          var fullData = mapModel.mainSeries.getData();
          var name_1 = originalData.getName(originalDataIndex);
          var fullIndex_1 = fullData.indexOfName(name_1);
          var itemModel = originalData.getItemModel(originalDataIndex);
          var labelModel = itemModel.getModel('label');
          var regionGroup = fullData.getItemGraphicEl(fullIndex_1);
          setLabelStyle(circle, getLabelStatesModels(itemModel), {
            labelFetcher: {
              getFormattedLabel: function (idx, state) {
                return mapModel.getFormattedLabel(fullIndex_1, state);
              }
            }
          });
          circle.disableLabelAnimation = true;

          if (!labelModel.get('position')) {
            circle.setTextConfig({
              position: 'bottom'
            });
          }

          regionGroup.onHoverStateChange = function (toState) {
            circle.useState(toState);
          };
        }

        group.add(circle);
      });
    };

    MapView.type = 'map';
    return MapView;
  }(ChartView);

  ChartView.registerClass(MapView);

  function updateCenterAndZoom(view, payload, zoomLimit) {
    var previousZoom = view.getZoom();
    var center = view.getCenter();
    var zoom = payload.zoom;
    var point = view.dataToPoint(center);

    if (payload.dx != null && payload.dy != null) {
      point[0] -= payload.dx;
      point[1] -= payload.dy;
      view.setCenter(view.pointToData(point));
    }

    if (zoom != null) {
      if (zoomLimit) {
        var zoomMin = zoomLimit.min || 0;
        var zoomMax = zoomLimit.max || Infinity;
        zoom = Math.max(Math.min(previousZoom * zoom, zoomMax), zoomMin) / previousZoom;
      }

      view.scaleX *= zoom;
      view.scaleY *= zoom;
      var fixX = (payload.originX - view.x) * (zoom - 1);
      var fixY = (payload.originY - view.y) * (zoom - 1);
      view.x -= fixX;
      view.y -= fixY;
      view.updateTransform();
      view.setCenter(view.pointToData(point));
      view.setZoom(zoom * previousZoom);
    }

    return {
      center: view.getCenter(),
      zoom: view.getZoom()
    };
  }

  registerAction({
    type: 'geoRoam',
    event: 'geoRoam',
    update: 'updateTransform'
  }, function (payload, ecModel) {
    var componentType = payload.componentType || 'series';
    ecModel.eachComponent({
      mainType: componentType,
      query: payload
    }, function (componentModel) {
      var geo = componentModel.coordinateSystem;

      if (geo.type !== 'geo') {
        return;
      }

      var res = updateCenterAndZoom(geo, payload, componentModel.get('scaleLimit'));
      componentModel.setCenter && componentModel.setCenter(res.center);
      componentModel.setZoom && componentModel.setZoom(res.zoom);

      if (componentType === 'series') {
        each(componentModel.seriesGroup, function (seriesModel) {
          seriesModel.setCenter(res.center);
          seriesModel.setZoom(res.zoom);
        });
      }
    });
  });
  var v2ApplyTransform = applyTransform;

  var View = function (_super) {
    __extends(View, _super);

    function View(name) {
      var _this = _super.call(this) || this;

      _this.type = 'view';
      _this.dimensions = ['x', 'y'];
      _this._roamTransformable = new Transformable();
      _this._rawTransformable = new Transformable();
      _this.name = name;
      return _this;
    }

    View.prototype.setBoundingRect = function (x, y, width, height) {
      this._rect = new BoundingRect(x, y, width, height);
      return this._rect;
    };

    View.prototype.getBoundingRect = function () {
      return this._rect;
    };

    View.prototype.setViewRect = function (x, y, width, height) {
      this.transformTo(x, y, width, height);
      this._viewRect = new BoundingRect(x, y, width, height);
    };

    View.prototype.transformTo = function (x, y, width, height) {
      var rect = this.getBoundingRect();
      var rawTransform = this._rawTransformable;
      rawTransform.transform = rect.calculateTransform(new BoundingRect(x, y, width, height));
      rawTransform.decomposeTransform();

      this._updateTransform();
    };

    View.prototype.setCenter = function (centerCoord) {
      if (!centerCoord) {
        return;
      }

      this._center = centerCoord;

      this._updateCenterAndZoom();
    };

    View.prototype.setZoom = function (zoom) {
      zoom = zoom || 1;
      var zoomLimit = this.zoomLimit;

      if (zoomLimit) {
        if (zoomLimit.max != null) {
          zoom = Math.min(zoomLimit.max, zoom);
        }

        if (zoomLimit.min != null) {
          zoom = Math.max(zoomLimit.min, zoom);
        }
      }

      this._zoom = zoom;

      this._updateCenterAndZoom();
    };

    View.prototype.getDefaultCenter = function () {
      var rawRect = this.getBoundingRect();
      var cx = rawRect.x + rawRect.width / 2;
      var cy = rawRect.y + rawRect.height / 2;
      return [cx, cy];
    };

    View.prototype.getCenter = function () {
      return this._center || this.getDefaultCenter();
    };

    View.prototype.getZoom = function () {
      return this._zoom || 1;
    };

    View.prototype.getRoamTransform = function () {
      return this._roamTransformable.getLocalTransform();
    };

    View.prototype._updateCenterAndZoom = function () {
      var rawTransformMatrix = this._rawTransformable.getLocalTransform();

      var roamTransform = this._roamTransformable;
      var defaultCenter = this.getDefaultCenter();
      var center = this.getCenter();
      var zoom = this.getZoom();
      center = applyTransform([], center, rawTransformMatrix);
      defaultCenter = applyTransform([], defaultCenter, rawTransformMatrix);
      roamTransform.originX = center[0];
      roamTransform.originY = center[1];
      roamTransform.x = defaultCenter[0] - center[0];
      roamTransform.y = defaultCenter[1] - center[1];
      roamTransform.scaleX = roamTransform.scaleY = zoom;

      this._updateTransform();
    };

    View.prototype._updateTransform = function () {
      var roamTransformable = this._roamTransformable;
      var rawTransformable = this._rawTransformable;
      rawTransformable.parent = roamTransformable;
      roamTransformable.updateTransform();
      rawTransformable.updateTransform();
      copy$1(this.transform || (this.transform = []), rawTransformable.transform || create$1());
      this._rawTransform = rawTransformable.getLocalTransform();
      this.invTransform = this.invTransform || [];
      invert(this.invTransform, this.transform);
      this.decomposeTransform();
    };

    View.prototype.getTransformInfo = function () {
      var roamTransform = this._roamTransformable.transform;
      var rawTransformable = this._rawTransformable;
      return {
        roamTransform: roamTransform ? slice(roamTransform) : create$1(),
        rawScaleX: rawTransformable.scaleX,
        rawScaleY: rawTransformable.scaleY,
        rawX: rawTransformable.x,
        rawY: rawTransformable.y
      };
    };

    View.prototype.getViewRect = function () {
      return this._viewRect;
    };

    View.prototype.getViewRectAfterRoam = function () {
      var rect = this.getBoundingRect().clone();
      rect.applyTransform(this.transform);
      return rect;
    };

    View.prototype.dataToPoint = function (data, noRoam, out) {
      var transform = noRoam ? this._rawTransform : this.transform;
      out = out || [];
      return transform ? v2ApplyTransform(out, data, transform) : copy(out, data);
    };

    View.prototype.pointToData = function (point) {
      var invTransform = this.invTransform;
      return invTransform ? v2ApplyTransform([], point, invTransform) : [point[0], point[1]];
    };

    View.prototype.convertToPixel = function (ecModel, finder, value) {
      var coordSys = getCoordSys(finder);
      return coordSys === this ? coordSys.dataToPoint(value) : null;
    };

    View.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      var coordSys = getCoordSys(finder);
      return coordSys === this ? coordSys.pointToData(pixel) : null;
    };

    View.prototype.containPoint = function (point) {
      return this.getViewRectAfterRoam().contain(point[0], point[1]);
    };

    View.dimensions = ['x', 'y'];
    return View;
  }(Transformable);

  function getCoordSys(finder) {
    var seriesModel = finder.seriesModel;
    return seriesModel ? seriesModel.coordinateSystem : null;
  }

  var Geo = function (_super) {
    __extends(Geo, _super);

    function Geo(name, map, nameMap, invertLongitute) {
      var _this = _super.call(this, name) || this;

      _this.dimensions = ['lng', 'lat'];
      _this.type = 'geo';
      _this.map = map;
      var source = geoSourceManager.load(map, nameMap);
      _this._nameCoordMap = source.nameCoordMap;
      _this._regionsMap = source.regionsMap;
      _this._invertLongitute = invertLongitute == null ? true : invertLongitute;
      _this.regions = source.regions;
      _this._rect = source.boundingRect;
      return _this;
    }

    Geo.prototype.containCoord = function (coord) {
      var regions = this.regions;

      for (var i = 0; i < regions.length; i++) {
        if (regions[i].contain(coord)) {
          return true;
        }
      }

      return false;
    };

    Geo.prototype.transformTo = function (x, y, width, height) {
      var rect = this.getBoundingRect();
      var invertLongitute = this._invertLongitute;
      rect = rect.clone();

      if (invertLongitute) {
        rect.y = -rect.y - rect.height;
      }

      var rawTransformable = this._rawTransformable;
      rawTransformable.transform = rect.calculateTransform(new BoundingRect(x, y, width, height));
      rawTransformable.decomposeTransform();

      if (invertLongitute) {
        rawTransformable.scaleY = -rawTransformable.scaleY;
      }

      rawTransformable.updateTransform();

      this._updateTransform();
    };

    Geo.prototype.getRegion = function (name) {
      return this._regionsMap.get(name);
    };

    Geo.prototype.getRegionByCoord = function (coord) {
      var regions = this.regions;

      for (var i = 0; i < regions.length; i++) {
        if (regions[i].contain(coord)) {
          return regions[i];
        }
      }
    };

    Geo.prototype.addGeoCoord = function (name, geoCoord) {
      this._nameCoordMap.set(name, geoCoord);
    };

    Geo.prototype.getGeoCoord = function (name) {
      return this._nameCoordMap.get(name);
    };

    Geo.prototype.getBoundingRect = function () {
      return this._rect;
    };

    Geo.prototype.dataToPoint = function (data, noRoam, out) {
      if (typeof data === 'string') {
        data = this.getGeoCoord(data);
      }

      if (data) {
        return View.prototype.dataToPoint.call(this, data, noRoam, out);
      }
    };

    Geo.prototype.convertToPixel = function (ecModel, finder, value) {
      var coordSys = getCoordSys$1(finder);
      return coordSys === this ? coordSys.dataToPoint(value) : null;
    };

    Geo.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      var coordSys = getCoordSys$1(finder);
      return coordSys === this ? coordSys.pointToData(pixel) : null;
    };

    return Geo;
  }(View);

  mixin(Geo, View);

  function getCoordSys$1(finder) {
    var geoModel = finder.geoModel;
    var seriesModel = finder.seriesModel;
    return geoModel ? geoModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem || (seriesModel.getReferringComponents('geo', SINGLE_REFERRING).models[0] || {}).coordinateSystem : null;
  }

  function resizeGeo(geoModel, api) {
    var boundingCoords = geoModel.get('boundingCoords');

    if (boundingCoords != null) {
      var leftTop = boundingCoords[0];
      var rightBottom = boundingCoords[1];

      if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) {
        if (true) {
          console.error('Invalid boundingCoords');
        }
      } else {
        this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]);
      }
    }

    var rect = this.getBoundingRect();
    var centerOption = geoModel.get('layoutCenter');
    var sizeOption = geoModel.get('layoutSize');
    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();
    var aspect = rect.width / rect.height * this.aspectScale;
    var useCenterAndSize = false;
    var center;
    var size;

    if (centerOption && sizeOption) {
      center = [parsePercent$2(centerOption[0], viewWidth), parsePercent$2(centerOption[1], viewHeight)];
      size = parsePercent$2(sizeOption, Math.min(viewWidth, viewHeight));

      if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) {
        useCenterAndSize = true;
      } else {
        if (true) {
          console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.');
        }
      }
    }

    var viewRect;

    if (useCenterAndSize) {
      viewRect = {};

      if (aspect > 1) {
        viewRect.width = size;
        viewRect.height = size / aspect;
      } else {
        viewRect.height = size;
        viewRect.width = size * aspect;
      }

      viewRect.y = center[1] - viewRect.height / 2;
      viewRect.x = center[0] - viewRect.width / 2;
    } else {
      var boxLayoutOption = geoModel.getBoxLayoutParams();
      boxLayoutOption.aspect = aspect;
      viewRect = getLayoutRect(boxLayoutOption, {
        width: viewWidth,
        height: viewHeight
      });
    }

    this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
    this.setCenter(geoModel.get('center'));
    this.setZoom(geoModel.get('zoom'));
  }

  function setGeoCoords(geo, model) {
    each(model.get('geoCoord'), function (geoCoord, name) {
      geo.addGeoCoord(name, geoCoord);
    });
  }

  var GeoCreator = function () {
    function GeoCreator() {
      this.dimensions = Geo.prototype.dimensions;
    }

    GeoCreator.prototype.create = function (ecModel, api) {
      var geoList = [];
      ecModel.eachComponent('geo', function (geoModel, idx) {
        var name = geoModel.get('map');
        var aspectScale = geoModel.get('aspectScale');
        var invertLongitute = true;
        var mapRecords = mapDataStorage.retrieveMap(name);

        if (mapRecords && mapRecords[0] && mapRecords[0].type === 'svg') {
          aspectScale == null && (aspectScale = 1);
          invertLongitute = false;
        } else {
          aspectScale == null && (aspectScale = 0.75);
        }

        var geo = new Geo(name + idx, name, geoModel.get('nameMap'), invertLongitute);
        geo.aspectScale = aspectScale;
        geo.zoomLimit = geoModel.get('scaleLimit');
        geoList.push(geo);
        geoModel.coordinateSystem = geo;
        geo.model = geoModel;
        geo.resize = resizeGeo;
        geo.resize(geoModel, api);
      });
      ecModel.eachSeries(function (seriesModel) {
        var coordSys = seriesModel.get('coordinateSystem');

        if (coordSys === 'geo') {
          var geoIndex = seriesModel.get('geoIndex') || 0;
          seriesModel.coordinateSystem = geoList[geoIndex];
        }
      });
      var mapModelGroupBySeries = {};
      ecModel.eachSeriesByType('map', function (seriesModel) {
        if (!seriesModel.getHostGeoModel()) {
          var mapType = seriesModel.getMapType();
          mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || [];
          mapModelGroupBySeries[mapType].push(seriesModel);
        }
      });
      each(mapModelGroupBySeries, function (mapSeries, mapType) {
        var nameMapList = map(mapSeries, function (singleMapSeries) {
          return singleMapSeries.get('nameMap');
        });
        var geo = new Geo(mapType, mapType, mergeAll(nameMapList));
        geo.zoomLimit = retrieve.apply(null, map(mapSeries, function (singleMapSeries) {
          return singleMapSeries.get('scaleLimit');
        }));
        geoList.push(geo);
        geo.resize = resizeGeo;
        geo.aspectScale = mapSeries[0].get('aspectScale');
        geo.resize(mapSeries[0], api);
        each(mapSeries, function (singleMapSeries) {
          singleMapSeries.coordinateSystem = geo;
          setGeoCoords(geo, singleMapSeries);
        });
      });
      return geoList;
    };

    GeoCreator.prototype.getFilledRegions = function (originRegionArr, mapName, nameMap) {
      var regionsArr = (originRegionArr || []).slice();
      var dataNameMap = createHashMap();

      for (var i = 0; i < regionsArr.length; i++) {
        dataNameMap.set(regionsArr[i].name, regionsArr[i]);
      }

      var source = geoSourceManager.load(mapName, nameMap);
      each(source.regions, function (region) {
        var name = region.name;
        !dataNameMap.get(name) && regionsArr.push({
          name: name
        });
      });
      return regionsArr;
    };

    return GeoCreator;
  }();

  var geoCreator = new GeoCreator();
  registerCoordinateSystem('geo', geoCreator);

  function mapSymbolLayout(ecModel) {
    var processedMapType = {};
    ecModel.eachSeriesByType('map', function (mapSeries) {
      var mapType = mapSeries.getMapType();

      if (mapSeries.getHostGeoModel() || processedMapType[mapType]) {
        return;
      }

      var mapSymbolOffsets = {};
      each(mapSeries.seriesGroup, function (subMapSeries) {
        var geo = subMapSeries.coordinateSystem;
        var data = subMapSeries.originalData;

        if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) {
          data.each(data.mapDimension('value'), function (value, idx) {
            var name = data.getName(idx);
            var region = geo.getRegion(name);

            if (!region || isNaN(value)) {
              return;
            }

            var offset = mapSymbolOffsets[name] || 0;
            var point = geo.dataToPoint(region.center);
            mapSymbolOffsets[name] = offset + 1;
            data.setItemLayout(idx, {
              point: point,
              offset: offset
            });
          });
        }
      });
      var data = mapSeries.getData();
      data.each(function (idx) {
        var name = data.getName(idx);
        var layout = data.getItemLayout(idx) || {};
        layout.showLabel = !mapSymbolOffsets[name];
        data.setItemLayout(idx, layout);
      });
      processedMapType[mapType] = true;
    });
  }

  function dataStatistics(datas, statisticType) {
    var dataNameMap = {};
    each(datas, function (data) {
      data.each(data.mapDimension('value'), function (value, idx) {
        var mapKey = 'ec-' + data.getName(idx);
        dataNameMap[mapKey] = dataNameMap[mapKey] || [];

        if (!isNaN(value)) {
          dataNameMap[mapKey].push(value);
        }
      });
    });
    return datas[0].map(datas[0].mapDimension('value'), function (value, idx) {
      var mapKey = 'ec-' + datas[0].getName(idx);
      var sum = 0;
      var min = Infinity;
      var max = -Infinity;
      var len = dataNameMap[mapKey].length;

      for (var i = 0; i < len; i++) {
        min = Math.min(min, dataNameMap[mapKey][i]);
        max = Math.max(max, dataNameMap[mapKey][i]);
        sum += dataNameMap[mapKey][i];
      }

      var result;

      if (statisticType === 'min') {
        result = min;
      } else if (statisticType === 'max') {
        result = max;
      } else if (statisticType === 'average') {
        result = sum / len;
      } else {
        result = sum;
      }

      return len === 0 ? NaN : result;
    });
  }

  function mapDataStatistic(ecModel) {
    var seriesGroups = {};
    ecModel.eachSeriesByType('map', function (seriesModel) {
      var hostGeoModel = seriesModel.getHostGeoModel();
      var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType();
      (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel);
    });
    each(seriesGroups, function (seriesList, key) {
      var data = dataStatistics(map(seriesList, function (seriesModel) {
        return seriesModel.getData();
      }), seriesList[0].get('mapValueCalculation'));

      for (var i = 0; i < seriesList.length; i++) {
        seriesList[i].originalData = seriesList[i].getData();
      }

      for (var i = 0; i < seriesList.length; i++) {
        seriesList[i].seriesGroup = seriesList;
        seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel();
        seriesList[i].setData(data.cloneShallow());
        seriesList[i].mainSeries = seriesList[0];
      }
    });
  }

  registerLayout(mapSymbolLayout);
  registerProcessor(PRIORITY.PROCESSOR.STATISTIC, mapDataStatistic);
  createLegacyDataSelectAction('map', registerAction);
  var inner$8 = makeInner();

  function linkList(opt) {
    var mainData = opt.mainData;
    var datas = opt.datas;

    if (!datas) {
      datas = {
        main: mainData
      };
      opt.datasAttr = {
        main: 'data'
      };
    }

    opt.datas = opt.mainData = null;
    linkAll(mainData, datas, opt);
    each(datas, function (data) {
      each(mainData.TRANSFERABLE_METHODS, function (methodName) {
        data.wrapMethod(methodName, curry(transferInjection, opt));
      });
    });
    mainData.wrapMethod('cloneShallow', curry(cloneShallowInjection, opt));
    each(mainData.CHANGABLE_METHODS, function (methodName) {
      mainData.wrapMethod(methodName, curry(changeInjection, opt));
    });
    assert(datas[mainData.dataType] === mainData);
  }

  function transferInjection(opt, res) {
    if (isMainData(this)) {
      var datas = extend({}, inner$8(this).datas);
      datas[this.dataType] = res;
      linkAll(res, datas, opt);
    } else {
      linkSingle(res, this.dataType, inner$8(this).mainData, opt);
    }

    return res;
  }

  function changeInjection(opt, res) {
    opt.struct && opt.struct.update();
    return res;
  }

  function cloneShallowInjection(opt, res) {
    each(inner$8(res).datas, function (data, dataType) {
      data !== res && linkSingle(data.cloneShallow(), dataType, res, opt);
    });
    return res;
  }

  function getLinkedData(dataType) {
    var mainData = inner$8(this).mainData;
    return dataType == null || mainData == null ? mainData : inner$8(mainData).datas[dataType];
  }

  function getLinkedDataAll() {
    var mainData = inner$8(this).mainData;
    return mainData == null ? [{
      data: mainData
    }] : map(keys(inner$8(mainData).datas), function (type) {
      return {
        type: type,
        data: inner$8(mainData).datas[type]
      };
    });
  }

  function isMainData(data) {
    return inner$8(data).mainData === data;
  }

  function linkAll(mainData, datas, opt) {
    inner$8(mainData).datas = {};
    each(datas, function (data, dataType) {
      linkSingle(data, dataType, mainData, opt);
    });
  }

  function linkSingle(data, dataType, mainData, opt) {
    inner$8(mainData).datas[dataType] = data;
    inner$8(data).mainData = mainData;
    data.dataType = dataType;

    if (opt.struct) {
      data[opt.structAttr] = opt.struct;
      opt.struct[opt.datasAttr[dataType]] = data;
    }

    data.getLinkedData = getLinkedData;
    data.getLinkedDataAll = getLinkedDataAll;
  }

  var TreeNode = function () {
    function TreeNode(name, hostTree) {
      this.depth = 0;
      this.height = 0;
      this.dataIndex = -1;
      this.children = [];
      this.viewChildren = [];
      this.isExpand = false;
      this.name = name || '';
      this.hostTree = hostTree;
    }

    TreeNode.prototype.isRemoved = function () {
      return this.dataIndex < 0;
    };

    TreeNode.prototype.eachNode = function (options, cb, context) {
      if (typeof options === 'function') {
        context = cb;
        cb = options;
        options = null;
      }

      options = options || {};

      if (isString(options)) {
        options = {
          order: options
        };
      }

      var order = options.order || 'preorder';
      var children = this[options.attr || 'children'];
      var suppressVisitSub;
      order === 'preorder' && (suppressVisitSub = cb.call(context, this));

      for (var i = 0; !suppressVisitSub && i < children.length; i++) {
        children[i].eachNode(options, cb, context);
      }

      order === 'postorder' && cb.call(context, this);
    };

    TreeNode.prototype.updateDepthAndHeight = function (depth) {
      var height = 0;
      this.depth = depth;

      for (var i = 0; i < this.children.length; i++) {
        var child = this.children[i];
        child.updateDepthAndHeight(depth + 1);

        if (child.height > height) {
          height = child.height;
        }
      }

      this.height = height + 1;
    };

    TreeNode.prototype.getNodeById = function (id) {
      if (this.getId() === id) {
        return this;
      }

      for (var i = 0, children = this.children, len = children.length; i < len; i++) {
        var res = children[i].getNodeById(id);

        if (res) {
          return res;
        }
      }
    };

    TreeNode.prototype.contains = function (node) {
      if (node === this) {
        return true;
      }

      for (var i = 0, children = this.children, len = children.length; i < len; i++) {
        var res = children[i].contains(node);

        if (res) {
          return res;
        }
      }
    };

    TreeNode.prototype.getAncestors = function (includeSelf) {
      var ancestors = [];
      var node = includeSelf ? this : this.parentNode;

      while (node) {
        ancestors.push(node);
        node = node.parentNode;
      }

      ancestors.reverse();
      return ancestors;
    };

    TreeNode.prototype.getAncestorsIndices = function () {
      var indices = [];
      var currNode = this;

      while (currNode) {
        indices.push(currNode.dataIndex);
        currNode = currNode.parentNode;
      }

      indices.reverse();
      return indices;
    };

    TreeNode.prototype.getDescendantIndices = function () {
      var indices = [];
      this.eachNode(function (childNode) {
        indices.push(childNode.dataIndex);
      });
      return indices;
    };

    TreeNode.prototype.getValue = function (dimension) {
      var data = this.hostTree.data;
      return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
    };

    TreeNode.prototype.setLayout = function (layout, merge) {
      this.dataIndex >= 0 && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge);
    };

    TreeNode.prototype.getLayout = function () {
      return this.hostTree.data.getItemLayout(this.dataIndex);
    };

    TreeNode.prototype.getModel = function (path) {
      if (this.dataIndex < 0) {
        return;
      }

      var hostTree = this.hostTree;
      var itemModel = hostTree.data.getItemModel(this.dataIndex);
      return itemModel.getModel(path);
    };

    TreeNode.prototype.getLevelModel = function () {
      return (this.hostTree.levelModels || [])[this.depth];
    };

    TreeNode.prototype.setVisual = function (key, value) {
      this.dataIndex >= 0 && this.hostTree.data.setItemVisual(this.dataIndex, key, value);
    };

    TreeNode.prototype.getVisual = function (key) {
      return this.hostTree.data.getItemVisual(this.dataIndex, key);
    };

    TreeNode.prototype.getRawIndex = function () {
      return this.hostTree.data.getRawIndex(this.dataIndex);
    };

    TreeNode.prototype.getId = function () {
      return this.hostTree.data.getId(this.dataIndex);
    };

    TreeNode.prototype.isAncestorOf = function (node) {
      var parent = node.parentNode;

      while (parent) {
        if (parent === this) {
          return true;
        }

        parent = parent.parentNode;
      }

      return false;
    };

    TreeNode.prototype.isDescendantOf = function (node) {
      return node !== this && node.isAncestorOf(this);
    };

    return TreeNode;
  }();

  var Tree = function () {
    function Tree(hostModel) {
      this.type = 'tree';
      this._nodes = [];
      this.hostModel = hostModel;
    }

    Tree.prototype.eachNode = function (options, cb, context) {
      this.root.eachNode(options, cb, context);
    };

    Tree.prototype.getNodeByDataIndex = function (dataIndex) {
      var rawIndex = this.data.getRawIndex(dataIndex);
      return this._nodes[rawIndex];
    };

    Tree.prototype.getNodeById = function (name) {
      return this.root.getNodeById(name);
    };

    Tree.prototype.update = function () {
      var data = this.data;
      var nodes = this._nodes;

      for (var i = 0, len = nodes.length; i < len; i++) {
        nodes[i].dataIndex = -1;
      }

      for (var i = 0, len = data.count(); i < len; i++) {
        nodes[data.getRawIndex(i)].dataIndex = i;
      }
    };

    Tree.prototype.clearLayouts = function () {
      this.data.clearItemLayouts();
    };

    Tree.createTree = function (dataRoot, hostModel, beforeLink) {
      var tree = new Tree(hostModel);
      var listData = [];
      var dimMax = 1;
      buildHierarchy(dataRoot);

      function buildHierarchy(dataNode, parentNode) {
        var value = dataNode.value;
        dimMax = Math.max(dimMax, isArray(value) ? value.length : 1);
        listData.push(dataNode);
        var node = new TreeNode(convertOptionIdName(dataNode.name, ''), tree);
        parentNode ? addChild(node, parentNode) : tree.root = node;

        tree._nodes.push(node);

        var children = dataNode.children;

        if (children) {
          for (var i = 0; i < children.length; i++) {
            buildHierarchy(children[i], node);
          }
        }
      }

      tree.root.updateDepthAndHeight(0);
      var dimensionsInfo = createDimensions(listData, {
        coordDimensions: ['value'],
        dimensionsCount: dimMax
      });
      var list = new List(dimensionsInfo, hostModel);
      list.initData(listData);
      beforeLink && beforeLink(list);
      linkList({
        mainData: list,
        struct: tree,
        structAttr: 'tree'
      });
      tree.update();
      return tree;
    };

    return Tree;
  }();

  function addChild(child, node) {
    var children = node.children;

    if (child.parentNode === node) {
      return;
    }

    children.push(child);
    child.parentNode = node;
  }

  var TreeSeriesModel = function (_super) {
    __extends(TreeSeriesModel, _super);

    function TreeSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.hasSymbolVisual = true;
      _this.ignoreStyleOnData = true;
      return _this;
    }

    TreeSeriesModel.prototype.getInitialData = function (option) {
      var root = {
        name: option.name,
        children: option.data
      };
      var leaves = option.leaves || {};
      var leavesModel = new Model(leaves, this, this.ecModel);
      var tree = Tree.createTree(root, this, beforeLink);

      function beforeLink(nodeData) {
        nodeData.wrapMethod('getItemModel', function (model, idx) {
          var node = tree.getNodeByDataIndex(idx);

          if (!node.children.length || !node.isExpand) {
            model.parentModel = leavesModel;
          }

          return model;
        });
      }

      var treeDepth = 0;
      tree.eachNode('preorder', function (node) {
        if (node.depth > treeDepth) {
          treeDepth = node.depth;
        }
      });
      var expandAndCollapse = option.expandAndCollapse;
      var expandTreeDepth = expandAndCollapse && option.initialTreeDepth >= 0 ? option.initialTreeDepth : treeDepth;
      tree.root.eachNode('preorder', function (node) {
        var item = node.hostTree.data.getRawDataItem(node.dataIndex);
        node.isExpand = item && item.collapsed != null ? !item.collapsed : node.depth <= expandTreeDepth;
      });
      return tree.data;
    };

    TreeSeriesModel.prototype.getOrient = function () {
      var orient = this.get('orient');

      if (orient === 'horizontal') {
        orient = 'LR';
      } else if (orient === 'vertical') {
        orient = 'TB';
      }

      return orient;
    };

    TreeSeriesModel.prototype.setZoom = function (zoom) {
      this.option.zoom = zoom;
    };

    TreeSeriesModel.prototype.setCenter = function (center) {
      this.option.center = center;
    };

    TreeSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var tree = this.getData().tree;
      var realRoot = tree.root.children[0];
      var node = tree.getNodeByDataIndex(dataIndex);
      var value = node.getValue();
      var name = node.name;

      while (node && node !== realRoot) {
        name = node.parentNode.name + '.' + name;
        node = node.parentNode;
      }

      return createTooltipMarkup('nameValue', {
        name: name,
        value: value,
        noValue: isNaN(value) || value == null
      });
    };

    TreeSeriesModel.type = 'series.tree';
    TreeSeriesModel.layoutMode = 'box';
    TreeSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'view',
      left: '12%',
      top: '12%',
      right: '12%',
      bottom: '12%',
      layout: 'orthogonal',
      edgeShape: 'curve',
      edgeForkPosition: '50%',
      roam: false,
      nodeScaleRatio: 0.4,
      center: null,
      zoom: 1,
      orient: 'LR',
      symbol: 'emptyCircle',
      symbolSize: 7,
      expandAndCollapse: true,
      initialTreeDepth: 2,
      lineStyle: {
        color: '#ccc',
        width: 1.5,
        curveness: 0.5
      },
      itemStyle: {
        color: 'lightsteelblue',
        borderColor: '#c23531',
        borderWidth: 1.5
      },
      label: {
        show: true
      },
      animationEasing: 'linear',
      animationDuration: 700,
      animationDurationUpdate: 500
    };
    return TreeSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(TreeSeriesModel);

  function init$2(inRoot) {
    var root = inRoot;
    root.hierNode = {
      defaultAncestor: null,
      ancestor: root,
      prelim: 0,
      modifier: 0,
      change: 0,
      shift: 0,
      i: 0,
      thread: null
    };
    var nodes = [root];
    var node;
    var children;

    while (node = nodes.pop()) {
      children = node.children;

      if (node.isExpand && children.length) {
        var n = children.length;

        for (var i = n - 1; i >= 0; i--) {
          var child = children[i];
          child.hierNode = {
            defaultAncestor: null,
            ancestor: child,
            prelim: 0,
            modifier: 0,
            change: 0,
            shift: 0,
            i: i,
            thread: null
          };
          nodes.push(child);
        }
      }
    }
  }

  function firstWalk(node, separation) {
    var children = node.isExpand ? node.children : [];
    var siblings = node.parentNode.children;
    var subtreeW = node.hierNode.i ? siblings[node.hierNode.i - 1] : null;

    if (children.length) {
      executeShifts(node);
      var midPoint = (children[0].hierNode.prelim + children[children.length - 1].hierNode.prelim) / 2;

      if (subtreeW) {
        node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW);
        node.hierNode.modifier = node.hierNode.prelim - midPoint;
      } else {
        node.hierNode.prelim = midPoint;
      }
    } else if (subtreeW) {
      node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW);
    }

    node.parentNode.hierNode.defaultAncestor = apportion(node, subtreeW, node.parentNode.hierNode.defaultAncestor || siblings[0], separation);
  }

  function secondWalk(node) {
    var nodeX = node.hierNode.prelim + node.parentNode.hierNode.modifier;
    node.setLayout({
      x: nodeX
    }, true);
    node.hierNode.modifier += node.parentNode.hierNode.modifier;
  }

  function separation(cb) {
    return arguments.length ? cb : defaultSeparation;
  }

  function radialCoordinate(rad, r) {
    rad -= Math.PI / 2;
    return {
      x: r * Math.cos(rad),
      y: r * Math.sin(rad)
    };
  }

  function getViewRect$1(seriesModel, api) {
    return getLayoutRect(seriesModel.getBoxLayoutParams(), {
      width: api.getWidth(),
      height: api.getHeight()
    });
  }

  function executeShifts(node) {
    var children = node.children;
    var n = children.length;
    var shift = 0;
    var change = 0;

    while (--n >= 0) {
      var child = children[n];
      child.hierNode.prelim += shift;
      child.hierNode.modifier += shift;
      change += child.hierNode.change;
      shift += child.hierNode.shift + change;
    }
  }

  function apportion(subtreeV, subtreeW, ancestor, separation) {
    if (subtreeW) {
      var nodeOutRight = subtreeV;
      var nodeInRight = subtreeV;
      var nodeOutLeft = nodeInRight.parentNode.children[0];
      var nodeInLeft = subtreeW;
      var sumOutRight = nodeOutRight.hierNode.modifier;
      var sumInRight = nodeInRight.hierNode.modifier;
      var sumOutLeft = nodeOutLeft.hierNode.modifier;
      var sumInLeft = nodeInLeft.hierNode.modifier;

      while (nodeInLeft = nextRight(nodeInLeft), nodeInRight = nextLeft(nodeInRight), nodeInLeft && nodeInRight) {
        nodeOutRight = nextRight(nodeOutRight);
        nodeOutLeft = nextLeft(nodeOutLeft);
        nodeOutRight.hierNode.ancestor = subtreeV;
        var shift = nodeInLeft.hierNode.prelim + sumInLeft - nodeInRight.hierNode.prelim - sumInRight + separation(nodeInLeft, nodeInRight);

        if (shift > 0) {
          moveSubtree(nextAncestor(nodeInLeft, subtreeV, ancestor), subtreeV, shift);
          sumInRight += shift;
          sumOutRight += shift;
        }

        sumInLeft += nodeInLeft.hierNode.modifier;
        sumInRight += nodeInRight.hierNode.modifier;
        sumOutRight += nodeOutRight.hierNode.modifier;
        sumOutLeft += nodeOutLeft.hierNode.modifier;
      }

      if (nodeInLeft && !nextRight(nodeOutRight)) {
        nodeOutRight.hierNode.thread = nodeInLeft;
        nodeOutRight.hierNode.modifier += sumInLeft - sumOutRight;
      }

      if (nodeInRight && !nextLeft(nodeOutLeft)) {
        nodeOutLeft.hierNode.thread = nodeInRight;
        nodeOutLeft.hierNode.modifier += sumInRight - sumOutLeft;
        ancestor = subtreeV;
      }
    }

    return ancestor;
  }

  function nextRight(node) {
    var children = node.children;
    return children.length && node.isExpand ? children[children.length - 1] : node.hierNode.thread;
  }

  function nextLeft(node) {
    var children = node.children;
    return children.length && node.isExpand ? children[0] : node.hierNode.thread;
  }

  function nextAncestor(nodeInLeft, node, ancestor) {
    return nodeInLeft.hierNode.ancestor.parentNode === node.parentNode ? nodeInLeft.hierNode.ancestor : ancestor;
  }

  function moveSubtree(wl, wr, shift) {
    var change = shift / (wr.hierNode.i - wl.hierNode.i);
    wr.hierNode.change -= change;
    wr.hierNode.shift += shift;
    wr.hierNode.modifier += shift;
    wr.hierNode.prelim += shift;
    wl.hierNode.change += change;
  }

  function defaultSeparation(node1, node2) {
    return node1.parentNode === node2.parentNode ? 1 : 2;
  }

  var TreeEdgeShape = function () {
    function TreeEdgeShape() {
      this.parentPoint = [];
      this.childPoints = [];
    }

    return TreeEdgeShape;
  }();

  var TreePath = function (_super) {
    __extends(TreePath, _super);

    function TreePath(opts) {
      return _super.call(this, opts) || this;
    }

    TreePath.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    TreePath.prototype.getDefaultShape = function () {
      return new TreeEdgeShape();
    };

    TreePath.prototype.buildPath = function (ctx, shape) {
      var childPoints = shape.childPoints;
      var childLen = childPoints.length;
      var parentPoint = shape.parentPoint;
      var firstChildPos = childPoints[0];
      var lastChildPos = childPoints[childLen - 1];

      if (childLen === 1) {
        ctx.moveTo(parentPoint[0], parentPoint[1]);
        ctx.lineTo(firstChildPos[0], firstChildPos[1]);
        return;
      }

      var orient = shape.orient;
      var forkDim = orient === 'TB' || orient === 'BT' ? 0 : 1;
      var otherDim = 1 - forkDim;
      var forkPosition = parsePercent$2(shape.forkPosition, 1);
      var tmpPoint = [];
      tmpPoint[forkDim] = parentPoint[forkDim];
      tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition;
      ctx.moveTo(parentPoint[0], parentPoint[1]);
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      ctx.moveTo(firstChildPos[0], firstChildPos[1]);
      tmpPoint[forkDim] = firstChildPos[forkDim];
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      tmpPoint[forkDim] = lastChildPos[forkDim];
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      ctx.lineTo(lastChildPos[0], lastChildPos[1]);

      for (var i = 1; i < childLen - 1; i++) {
        var point = childPoints[i];
        ctx.moveTo(point[0], point[1]);
        tmpPoint[forkDim] = point[forkDim];
        ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      }
    };

    return TreePath;
  }(Path);

  var TreeView = function (_super) {
    __extends(TreeView, _super);

    function TreeView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TreeView.type;
      _this._mainGroup = new Group();
      return _this;
    }

    TreeView.prototype.init = function (ecModel, api) {
      this._controller = new RoamController(api.getZr());
      this._controllerHost = {
        target: this.group
      };
      this.group.add(this._mainGroup);
    };

    TreeView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var layoutInfo = seriesModel.layoutInfo;
      var group = this._mainGroup;
      var layout = seriesModel.get('layout');

      if (layout === 'radial') {
        group.x = layoutInfo.x + layoutInfo.width / 2;
        group.y = layoutInfo.y + layoutInfo.height / 2;
      } else {
        group.x = layoutInfo.x;
        group.y = layoutInfo.y;
      }

      this._updateViewCoordSys(seriesModel);

      this._updateController(seriesModel, ecModel, api);

      var oldData = this._data;
      data.diff(oldData).add(function (newIdx) {
        if (symbolNeedsDraw$1(data, newIdx)) {
          updateNode(data, newIdx, null, group, seriesModel);
        }
      }).update(function (newIdx, oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);

        if (!symbolNeedsDraw$1(data, newIdx)) {
          symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel);
          return;
        }

        updateNode(data, newIdx, symbolEl, group, seriesModel);
      }).remove(function (oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);

        if (symbolEl) {
          removeNode(oldData, oldIdx, symbolEl, group, seriesModel);
        }
      }).execute();
      this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');

      this._updateNodeAndLinkScale(seriesModel);

      if (seriesModel.get('expandAndCollapse') === true) {
        data.eachItemGraphicEl(function (el, dataIndex) {
          el.off('click').on('click', function () {
            api.dispatchAction({
              type: 'treeExpandAndCollapse',
              seriesId: seriesModel.id,
              dataIndex: dataIndex
            });
          });
        });
      }

      this._data = data;
    };

    TreeView.prototype._updateViewCoordSys = function (seriesModel) {
      var data = seriesModel.getData();
      var points = [];
      data.each(function (idx) {
        var layout = data.getItemLayout(idx);

        if (layout && !isNaN(layout.x) && !isNaN(layout.y)) {
          points.push([+layout.x, +layout.y]);
        }
      });
      var min = [];
      var max = [];
      fromPoints(points, min, max);
      var oldMin = this._min;
      var oldMax = this._max;

      if (max[0] - min[0] === 0) {
        min[0] = oldMin ? oldMin[0] : min[0] - 1;
        max[0] = oldMax ? oldMax[0] : max[0] + 1;
      }

      if (max[1] - min[1] === 0) {
        min[1] = oldMin ? oldMin[1] : min[1] - 1;
        max[1] = oldMax ? oldMax[1] : max[1] + 1;
      }

      var viewCoordSys = seriesModel.coordinateSystem = new View();
      viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
      viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);
      viewCoordSys.setCenter(seriesModel.get('center'));
      viewCoordSys.setZoom(seriesModel.get('zoom'));
      this.group.attr({
        x: viewCoordSys.x,
        y: viewCoordSys.y,
        scaleX: viewCoordSys.scaleX,
        scaleY: viewCoordSys.scaleY
      });
      this._min = min;
      this._max = max;
    };

    TreeView.prototype._updateController = function (seriesModel, ecModel, api) {
      var _this = this;

      var controller = this._controller;
      var controllerHost = this._controllerHost;
      var group = this.group;
      controller.setPointerChecker(function (e, x, y) {
        var rect = group.getBoundingRect();
        rect.applyTransform(group.transform);
        return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel);
      });
      controller.enable(seriesModel.get('roam'));
      controllerHost.zoomLimit = seriesModel.get('scaleLimit');
      controllerHost.zoom = seriesModel.coordinateSystem.getZoom();
      controller.off('pan').off('zoom').on('pan', function (e) {
        updateViewOnPan(controllerHost, e.dx, e.dy);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: 'treeRoam',
          dx: e.dx,
          dy: e.dy
        });
      }).on('zoom', function (e) {
        updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: 'treeRoam',
          zoom: e.scale,
          originX: e.originX,
          originY: e.originY
        });

        _this._updateNodeAndLinkScale(seriesModel);

        api.updateLabelLayout();
      });
    };

    TreeView.prototype._updateNodeAndLinkScale = function (seriesModel) {
      var data = seriesModel.getData();

      var nodeScale = this._getNodeGlobalScale(seriesModel);

      data.eachItemGraphicEl(function (el, idx) {
        el.setSymbolScale(nodeScale);
      });
    };

    TreeView.prototype._getNodeGlobalScale = function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys.type !== 'view') {
        return 1;
      }

      var nodeScaleRatio = this._nodeScaleRatio;
      var groupZoom = coordSys.scaleX || 1;
      var roamZoom = coordSys.getZoom();
      var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
      return nodeScale / groupZoom;
    };

    TreeView.prototype.dispose = function () {
      this._controller && this._controller.dispose();
      this._controllerHost = null;
    };

    TreeView.prototype.remove = function () {
      this._mainGroup.removeAll();

      this._data = null;
    };

    TreeView.type = 'tree';
    return TreeView;
  }(ChartView);

  function symbolNeedsDraw$1(data, dataIndex) {
    var layout = data.getItemLayout(dataIndex);
    return layout && !isNaN(layout.x) && !isNaN(layout.y);
  }

  function updateNode(data, dataIndex, symbolEl, group, seriesModel) {
    var isInit = !symbolEl;
    var node = data.tree.getNodeByDataIndex(dataIndex);
    var itemModel = node.getModel();
    var visualColor = node.getVisual('style').fill;
    var symbolInnerColor = node.isExpand === false && node.children.length !== 0 ? visualColor : '#fff';
    var virtualRoot = data.tree.root;
    var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
    var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
    var sourceLayout = source.getLayout();
    var sourceOldLayout = sourceSymbolEl ? {
      x: sourceSymbolEl.__oldX,
      y: sourceSymbolEl.__oldY,
      rawX: sourceSymbolEl.__radialOldRawX,
      rawY: sourceSymbolEl.__radialOldRawY
    } : sourceLayout;
    var targetLayout = node.getLayout();

    if (isInit) {
      symbolEl = new Symbol(data, dataIndex, null, {
        symbolInnerColor: symbolInnerColor,
        useNameLabel: true
      });
      symbolEl.x = sourceOldLayout.x;
      symbolEl.y = sourceOldLayout.y;
    } else {
      symbolEl.updateData(data, dataIndex, null, {
        symbolInnerColor: symbolInnerColor,
        useNameLabel: true
      });
    }

    symbolEl.__radialOldRawX = symbolEl.__radialRawX;
    symbolEl.__radialOldRawY = symbolEl.__radialRawY;
    symbolEl.__radialRawX = targetLayout.rawX;
    symbolEl.__radialRawY = targetLayout.rawY;
    group.add(symbolEl);
    data.setItemGraphicEl(dataIndex, symbolEl);
    symbolEl.__oldX = symbolEl.x;
    symbolEl.__oldY = symbolEl.y;
    updateProps(symbolEl, {
      x: targetLayout.x,
      y: targetLayout.y
    }, seriesModel);
    var symbolPath = symbolEl.getSymbolPath();

    if (seriesModel.get('layout') === 'radial') {
      var realRoot = virtualRoot.children[0];
      var rootLayout = realRoot.getLayout();
      var length_1 = realRoot.children.length;
      var rad = void 0;
      var isLeft = void 0;

      if (targetLayout.x === rootLayout.x && node.isExpand === true) {
        var center = {
          x: (realRoot.children[0].getLayout().x + realRoot.children[length_1 - 1].getLayout().x) / 2,
          y: (realRoot.children[0].getLayout().y + realRoot.children[length_1 - 1].getLayout().y) / 2
        };
        rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x);

        if (rad < 0) {
          rad = Math.PI * 2 + rad;
        }

        isLeft = center.x < rootLayout.x;

        if (isLeft) {
          rad = rad - Math.PI;
        }
      } else {
        rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x);

        if (rad < 0) {
          rad = Math.PI * 2 + rad;
        }

        if (node.children.length === 0 || node.children.length !== 0 && node.isExpand === false) {
          isLeft = targetLayout.x < rootLayout.x;

          if (isLeft) {
            rad = rad - Math.PI;
          }
        } else {
          isLeft = targetLayout.x > rootLayout.x;

          if (!isLeft) {
            rad = rad - Math.PI;
          }
        }
      }

      var textPosition = isLeft ? 'left' : 'right';
      var normalLabelModel = itemModel.getModel('label');
      var rotate = normalLabelModel.get('rotate');
      var labelRotateRadian = rotate * (Math.PI / 180);
      var textContent = symbolPath.getTextContent();

      if (textContent) {
        symbolPath.setTextConfig({
          position: normalLabelModel.get('position') || textPosition,
          rotation: rotate == null ? -rad : labelRotateRadian,
          origin: 'center'
        });
        textContent.setStyle('verticalAlign', 'middle');
      }
    }

    var focus = itemModel.get(['emphasis', 'focus']);
    var focusDataIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : null;

    if (focusDataIndices) {
      getECData(symbolEl).focus = focusDataIndices;
    }

    drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group);

    if (symbolEl.__edge) {
      symbolEl.onHoverStateChange = function (toState) {
        if (toState !== 'blur') {
          var parentEl = node.parentNode && data.getItemGraphicEl(node.parentNode.dataIndex);

          if (!(parentEl && parentEl.hoverState === HOVER_STATE_BLUR)) {
            setStatesFlag(symbolEl.__edge, toState);
          }
        }
      };
    }
  }

  function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group) {
    var itemModel = node.getModel();
    var edgeShape = seriesModel.get('edgeShape');
    var layout = seriesModel.get('layout');
    var orient = seriesModel.getOrient();
    var curvature = seriesModel.get(['lineStyle', 'curveness']);
    var edgeForkPosition = seriesModel.get('edgeForkPosition');
    var lineStyle = itemModel.getModel('lineStyle').getLineStyle();
    var edge = symbolEl.__edge;

    if (edgeShape === 'curve') {
      if (node.parentNode && node.parentNode !== virtualRoot) {
        if (!edge) {
          edge = symbolEl.__edge = new BezierCurve({
            shape: getEdgeShape(layout, orient, curvature, sourceOldLayout, sourceOldLayout)
          });
        }

        updateProps(edge, {
          shape: getEdgeShape(layout, orient, curvature, sourceLayout, targetLayout)
        }, seriesModel);
      }
    } else if (edgeShape === 'polyline') {
      if (layout === 'orthogonal') {
        if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) {
          var children = node.children;
          var childPoints = [];

          for (var i = 0; i < children.length; i++) {
            var childLayout = children[i].getLayout();
            childPoints.push([childLayout.x, childLayout.y]);
          }

          if (!edge) {
            edge = symbolEl.__edge = new TreePath({
              shape: {
                parentPoint: [targetLayout.x, targetLayout.y],
                childPoints: [[targetLayout.x, targetLayout.y]],
                orient: orient,
                forkPosition: edgeForkPosition
              }
            });
          }

          updateProps(edge, {
            shape: {
              parentPoint: [targetLayout.x, targetLayout.y],
              childPoints: childPoints
            }
          }, seriesModel);
        }
      } else {
        if (true) {
          throw new Error('The polyline edgeShape can only be used in orthogonal layout');
        }
      }
    }

    if (edge) {
      edge.useStyle(defaults({
        strokeNoScale: true,
        fill: null
      }, lineStyle));
      setStatesStylesFromModel(edge, itemModel, 'lineStyle');
      setDefaultStateProxy(edge);
      group.add(edge);
    }
  }

  function removeNode(data, dataIndex, symbolEl, group, seriesModel) {
    var node = data.tree.getNodeByDataIndex(dataIndex);
    var virtualRoot = data.tree.root;
    var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
    var sourceLayout;

    while (sourceLayout = source.getLayout(), sourceLayout == null) {
      source = source.parentNode === virtualRoot ? source : source.parentNode || source;
    }

    var removeAnimationOpt = {
      duration: seriesModel.get('animationDurationUpdate'),
      easing: seriesModel.get('animationEasingUpdate')
    };
    removeElement(symbolEl, {
      x: sourceLayout.x + 1,
      y: sourceLayout.y + 1
    }, seriesModel, {
      cb: function () {
        group.remove(symbolEl);
        data.setItemGraphicEl(dataIndex, null);
      },
      removeOpt: removeAnimationOpt
    });
    symbolEl.fadeOut(null, {
      fadeLabel: true,
      animation: removeAnimationOpt
    });
    var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
    var sourceEdge = sourceSymbolEl.__edge;
    var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : undefined);
    var edgeShape = seriesModel.get('edgeShape');
    var layoutOpt = seriesModel.get('layout');
    var orient = seriesModel.get('orient');
    var curvature = seriesModel.get(['lineStyle', 'curveness']);

    if (edge) {
      if (edgeShape === 'curve') {
        removeElement(edge, {
          shape: getEdgeShape(layoutOpt, orient, curvature, sourceLayout, sourceLayout),
          style: {
            opacity: 0
          }
        }, seriesModel, {
          cb: function () {
            group.remove(edge);
          },
          removeOpt: removeAnimationOpt
        });
      } else if (edgeShape === 'polyline' && seriesModel.get('layout') === 'orthogonal') {
        removeElement(edge, {
          shape: {
            parentPoint: [sourceLayout.x, sourceLayout.y],
            childPoints: [[sourceLayout.x, sourceLayout.y]]
          },
          style: {
            opacity: 0
          }
        }, seriesModel, {
          cb: function () {
            group.remove(edge);
          },
          removeOpt: removeAnimationOpt
        });
      }
    }
  }

  function getEdgeShape(layoutOpt, orient, curvature, sourceLayout, targetLayout) {
    var cpx1;
    var cpy1;
    var cpx2;
    var cpy2;
    var x1;
    var x2;
    var y1;
    var y2;

    if (layoutOpt === 'radial') {
      x1 = sourceLayout.rawX;
      y1 = sourceLayout.rawY;
      x2 = targetLayout.rawX;
      y2 = targetLayout.rawY;
      var radialCoor1 = radialCoordinate(x1, y1);
      var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * curvature);
      var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * curvature);
      var radialCoor4 = radialCoordinate(x2, y2);
      return {
        x1: radialCoor1.x || 0,
        y1: radialCoor1.y || 0,
        x2: radialCoor4.x || 0,
        y2: radialCoor4.y || 0,
        cpx1: radialCoor2.x || 0,
        cpy1: radialCoor2.y || 0,
        cpx2: radialCoor3.x || 0,
        cpy2: radialCoor3.y || 0
      };
    } else {
      x1 = sourceLayout.x;
      y1 = sourceLayout.y;
      x2 = targetLayout.x;
      y2 = targetLayout.y;

      if (orient === 'LR' || orient === 'RL') {
        cpx1 = x1 + (x2 - x1) * curvature;
        cpy1 = y1;
        cpx2 = x2 + (x1 - x2) * curvature;
        cpy2 = y2;
      }

      if (orient === 'TB' || orient === 'BT') {
        cpx1 = x1;
        cpy1 = y1 + (y2 - y1) * curvature;
        cpx2 = x2;
        cpy2 = y2 + (y1 - y2) * curvature;
      }
    }

    return {
      x1: x1,
      y1: y1,
      x2: x2,
      y2: y2,
      cpx1: cpx1,
      cpy1: cpy1,
      cpx2: cpx2,
      cpy2: cpy2
    };
  }

  ChartView.registerClass(TreeView);
  registerAction({
    type: 'treeExpandAndCollapse',
    event: 'treeExpandAndCollapse',
    update: 'update'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'tree',
      query: payload
    }, function (seriesModel) {
      var dataIndex = payload.dataIndex;
      var tree = seriesModel.getData().tree;
      var node = tree.getNodeByDataIndex(dataIndex);
      node.isExpand = !node.isExpand;
    });
  });
  registerAction({
    type: 'treeRoam',
    event: 'treeRoam',
    update: 'none'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'tree',
      query: payload
    }, function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var res = updateCenterAndZoom(coordSys, payload);
      seriesModel.setCenter && seriesModel.setCenter(res.center);
      seriesModel.setZoom && seriesModel.setZoom(res.zoom);
    });
  });

  function eachAfter(root, callback, separation) {
    var nodes = [root];
    var next = [];
    var node;

    while (node = nodes.pop()) {
      next.push(node);

      if (node.isExpand) {
        var children = node.children;

        if (children.length) {
          for (var i = 0; i < children.length; i++) {
            nodes.push(children[i]);
          }
        }
      }
    }

    while (node = next.pop()) {
      callback(node, separation);
    }
  }

  function eachBefore(root, callback) {
    var nodes = [root];
    var node;

    while (node = nodes.pop()) {
      callback(node);

      if (node.isExpand) {
        var children = node.children;

        if (children.length) {
          for (var i = children.length - 1; i >= 0; i--) {
            nodes.push(children[i]);
          }
        }
      }
    }
  }

  function treeLayout(ecModel, api) {
    ecModel.eachSeriesByType('tree', function (seriesModel) {
      commonLayout(seriesModel, api);
    });
  }

  function commonLayout(seriesModel, api) {
    var layoutInfo = getViewRect$1(seriesModel, api);
    seriesModel.layoutInfo = layoutInfo;
    var layout = seriesModel.get('layout');
    var width = 0;
    var height = 0;
    var separation$1 = null;

    if (layout === 'radial') {
      width = 2 * Math.PI;
      height = Math.min(layoutInfo.height, layoutInfo.width) / 2;
      separation$1 = separation(function (node1, node2) {
        return (node1.parentNode === node2.parentNode ? 1 : 2) / node1.depth;
      });
    } else {
      width = layoutInfo.width;
      height = layoutInfo.height;
      separation$1 = separation();
    }

    var virtualRoot = seriesModel.getData().tree.root;
    var realRoot = virtualRoot.children[0];

    if (realRoot) {
      init$2(virtualRoot);
      eachAfter(realRoot, firstWalk, separation$1);
      virtualRoot.hierNode.modifier = -realRoot.hierNode.prelim;
      eachBefore(realRoot, secondWalk);
      var left_1 = realRoot;
      var right_1 = realRoot;
      var bottom_1 = realRoot;
      eachBefore(realRoot, function (node) {
        var x = node.getLayout().x;

        if (x < left_1.getLayout().x) {
          left_1 = node;
        }

        if (x > right_1.getLayout().x) {
          right_1 = node;
        }

        if (node.depth > bottom_1.depth) {
          bottom_1 = node;
        }
      });
      var delta = left_1 === right_1 ? 1 : separation$1(left_1, right_1) / 2;
      var tx_1 = delta - left_1.getLayout().x;
      var kx_1 = 0;
      var ky_1 = 0;
      var coorX_1 = 0;
      var coorY_1 = 0;

      if (layout === 'radial') {
        kx_1 = width / (right_1.getLayout().x + delta + tx_1);
        ky_1 = height / (bottom_1.depth - 1 || 1);
        eachBefore(realRoot, function (node) {
          coorX_1 = (node.getLayout().x + tx_1) * kx_1;
          coorY_1 = (node.depth - 1) * ky_1;
          var finalCoor = radialCoordinate(coorX_1, coorY_1);
          node.setLayout({
            x: finalCoor.x,
            y: finalCoor.y,
            rawX: coorX_1,
            rawY: coorY_1
          }, true);
        });
      } else {
        var orient_1 = seriesModel.getOrient();

        if (orient_1 === 'RL' || orient_1 === 'LR') {
          ky_1 = height / (right_1.getLayout().x + delta + tx_1);
          kx_1 = width / (bottom_1.depth - 1 || 1);
          eachBefore(realRoot, function (node) {
            coorY_1 = (node.getLayout().x + tx_1) * ky_1;
            coorX_1 = orient_1 === 'LR' ? (node.depth - 1) * kx_1 : width - (node.depth - 1) * kx_1;
            node.setLayout({
              x: coorX_1,
              y: coorY_1
            }, true);
          });
        } else if (orient_1 === 'TB' || orient_1 === 'BT') {
          kx_1 = width / (right_1.getLayout().x + delta + tx_1);
          ky_1 = height / (bottom_1.depth - 1 || 1);
          eachBefore(realRoot, function (node) {
            coorX_1 = (node.getLayout().x + tx_1) * kx_1;
            coorY_1 = orient_1 === 'TB' ? (node.depth - 1) * ky_1 : height - (node.depth - 1) * ky_1;
            node.setLayout({
              x: coorX_1,
              y: coorY_1
            }, true);
          });
        }
      }
    }
  }

  function treeVisual(ecModel) {
    ecModel.eachSeriesByType('tree', function (seriesModel) {
      var data = seriesModel.getData();
      var tree = data.tree;
      tree.eachNode(function (node) {
        var model = node.getModel();
        var style = model.getModel('itemStyle').getItemStyle();
        var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style');
        extend(existsStyle, style);
      });
    });
  }

  registerLayout(treeLayout);
  registerVisual(treeVisual);

  function retrieveTargetInfo(payload, validPayloadTypes, seriesModel) {
    if (payload && indexOf(validPayloadTypes, payload.type) >= 0) {
      var root = seriesModel.getData().tree.root;
      var targetNode = payload.targetNode;

      if (typeof targetNode === 'string') {
        targetNode = root.getNodeById(targetNode);
      }

      if (targetNode && root.contains(targetNode)) {
        return {
          node: targetNode
        };
      }

      var targetNodeId = payload.targetNodeId;

      if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) {
        return {
          node: targetNode
        };
      }
    }
  }

  function getPathToRoot(node) {
    var path = [];

    while (node) {
      node = node.parentNode;
      node && path.push(node);
    }

    return path.reverse();
  }

  function aboveViewRoot(viewRoot, node) {
    var viewPath = getPathToRoot(viewRoot);
    return indexOf(viewPath, node) >= 0;
  }

  function wrapTreePathInfo(node, seriesModel) {
    var treePathInfo = [];

    while (node) {
      var nodeDataIndex = node.dataIndex;
      treePathInfo.push({
        name: node.name,
        dataIndex: nodeDataIndex,
        value: seriesModel.getRawValue(nodeDataIndex)
      });
      node = node.parentNode;
    }

    treePathInfo.reverse();
    return treePathInfo;
  }

  function enableAriaDecalForTree(seriesModel) {
    var data = seriesModel.getData();
    var tree = data.tree;
    var decalPaletteScope = {};
    tree.eachNode(function (node) {
      var current = node;

      while (current && current.depth > 1) {
        current = current.parentNode;
      }

      var decal = getDecalFromPalette(seriesModel.ecModel, current.name || current.dataIndex + '', decalPaletteScope);
      node.setVisual('decal', decal);
    });
  }

  var TreemapSeriesModel = function (_super) {
    __extends(TreemapSeriesModel, _super);

    function TreemapSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TreemapSeriesModel.type;
      _this.preventUsingHoverLayer = true;
      return _this;
    }

    TreemapSeriesModel.prototype.getInitialData = function (option, ecModel) {
      var root = {
        name: option.name,
        children: option.data
      };
      completeTreeValue(root);
      var levels = option.levels || [];
      var designatedVisualItemStyle = this.designatedVisualItemStyle = {};
      var designatedVisualModel = new Model({
        itemStyle: designatedVisualItemStyle
      }, this, ecModel);
      levels = option.levels = setDefault(levels, ecModel);
      var levelModels = map(levels || [], function (levelDefine) {
        return new Model(levelDefine, designatedVisualModel, ecModel);
      }, this);
      var tree = Tree.createTree(root, this, beforeLink);

      function beforeLink(nodeData) {
        nodeData.wrapMethod('getItemModel', function (model, idx) {
          var node = tree.getNodeByDataIndex(idx);
          var levelModel = levelModels[node.depth];
          model.parentModel = levelModel || designatedVisualModel;
          return model;
        });
      }

      return tree.data;
    };

    TreemapSeriesModel.prototype.optionUpdated = function () {
      this.resetViewRoot();
    };

    TreemapSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var value = this.getRawValue(dataIndex);
      var name = data.getName(dataIndex);
      return createTooltipMarkup('nameValue', {
        name: name,
        value: value
      });
    };

    TreemapSeriesModel.prototype.getDataParams = function (dataIndex) {
      var params = _super.prototype.getDataParams.apply(this, arguments);

      var node = this.getData().tree.getNodeByDataIndex(dataIndex);
      params.treePathInfo = wrapTreePathInfo(node, this);
      return params;
    };

    TreemapSeriesModel.prototype.setLayoutInfo = function (layoutInfo) {
      this.layoutInfo = this.layoutInfo || {};
      extend(this.layoutInfo, layoutInfo);
    };

    TreemapSeriesModel.prototype.mapIdToIndex = function (id) {
      var idIndexMap = this._idIndexMap;

      if (!idIndexMap) {
        idIndexMap = this._idIndexMap = createHashMap();
        this._idIndexMapCount = 0;
      }

      var index = idIndexMap.get(id);

      if (index == null) {
        idIndexMap.set(id, index = this._idIndexMapCount++);
      }

      return index;
    };

    TreemapSeriesModel.prototype.getViewRoot = function () {
      return this._viewRoot;
    };

    TreemapSeriesModel.prototype.resetViewRoot = function (viewRoot) {
      viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot;
      var root = this.getRawData().tree.root;

      if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) {
        this._viewRoot = root;
      }
    };

    TreemapSeriesModel.prototype.enableAriaDecal = function () {
      enableAriaDecalForTree(this);
    };

    TreemapSeriesModel.type = 'series.treemap';
    TreemapSeriesModel.layoutMode = 'box';
    TreemapSeriesModel.defaultOption = {
      progressive: 0,
      left: 'center',
      top: 'middle',
      width: '80%',
      height: '80%',
      sort: true,
      clipWindow: 'origin',
      squareRatio: 0.5 * (1 + Math.sqrt(5)),
      leafDepth: null,
      drillDownIcon: '▶',
      zoomToNodeRatio: 0.32 * 0.32,
      roam: true,
      nodeClick: 'zoomToNode',
      animation: true,
      animationDurationUpdate: 900,
      animationEasing: 'quinticInOut',
      breadcrumb: {
        show: true,
        height: 22,
        left: 'center',
        top: 'bottom',
        emptyItemWidth: 25,
        itemStyle: {
          color: 'rgba(0,0,0,0.7)',
          textStyle: {
            color: '#fff'
          }
        }
      },
      label: {
        show: true,
        distance: 0,
        padding: 5,
        position: 'inside',
        color: '#fff',
        overflow: 'truncate'
      },
      upperLabel: {
        show: false,
        position: [0, '50%'],
        height: 20,
        overflow: 'truncate',
        verticalAlign: 'middle'
      },
      itemStyle: {
        color: null,
        colorAlpha: null,
        colorSaturation: null,
        borderWidth: 0,
        gapWidth: 0,
        borderColor: '#fff',
        borderColorSaturation: null
      },
      emphasis: {
        upperLabel: {
          show: true,
          position: [0, '50%'],
          ellipsis: true,
          verticalAlign: 'middle'
        }
      },
      visualDimension: 0,
      visualMin: null,
      visualMax: null,
      color: [],
      colorAlpha: null,
      colorSaturation: null,
      colorMappingBy: 'index',
      visibleMin: 10,
      childrenVisibleMin: null,
      levels: []
    };
    return TreemapSeriesModel;
  }(SeriesModel);

  function completeTreeValue(dataNode) {
    var sum = 0;
    each(dataNode.children, function (child) {
      completeTreeValue(child);
      var childValue = child.value;
      isArray(childValue) && (childValue = childValue[0]);
      sum += childValue;
    });
    var thisValue = dataNode.value;

    if (isArray(thisValue)) {
      thisValue = thisValue[0];
    }

    if (thisValue == null || isNaN(thisValue)) {
      thisValue = sum;
    }

    if (thisValue < 0) {
      thisValue = 0;
    }

    isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue;
  }

  function setDefault(levels, ecModel) {
    var globalColorList = normalizeToArray(ecModel.get('color'));
    var globalDecalList = normalizeToArray(ecModel.get('decals'));

    if (!globalColorList) {
      return;
    }

    levels = levels || [];
    var hasColorDefine;
    var hasDecalDefine;
    each(levels, function (levelDefine) {
      var model = new Model(levelDefine);
      var modelColor = model.get('color');
      var modelDecal = model.get('decal');

      if (model.get(['itemStyle', 'color']) || modelColor && modelColor !== 'none') {
        hasColorDefine = true;
      }

      if (model.get(['itemStyle', 'decal']) || modelDecal && modelDecal !== 'none') {
        hasDecalDefine = true;
      }
    });
    var level0 = levels[0] || (levels[0] = {});

    if (!hasColorDefine) {
      level0.color = globalColorList.slice();
    }

    if (!hasDecalDefine && globalDecalList) {
      level0.decal = globalDecalList.slice();
    }

    return levels;
  }

  SeriesModel.registerClass(TreemapSeriesModel);
  var TEXT_PADDING = 8;
  var ITEM_GAP = 8;
  var ARRAY_LENGTH = 5;

  var Breadcrumb = function () {
    function Breadcrumb(containerGroup) {
      this.group = new Group();
      containerGroup.add(this.group);
    }

    Breadcrumb.prototype.render = function (seriesModel, api, targetNode, onSelect) {
      var model = seriesModel.getModel('breadcrumb');
      var thisGroup = this.group;
      thisGroup.removeAll();

      if (!model.get('show') || !targetNode) {
        return;
      }

      var normalStyleModel = model.getModel('itemStyle');
      var textStyleModel = normalStyleModel.getModel('textStyle');
      var layoutParam = {
        pos: {
          left: model.get('left'),
          right: model.get('right'),
          top: model.get('top'),
          bottom: model.get('bottom')
        },
        box: {
          width: api.getWidth(),
          height: api.getHeight()
        },
        emptyItemWidth: model.get('emptyItemWidth'),
        totalWidth: 0,
        renderList: []
      };

      this._prepare(targetNode, layoutParam, textStyleModel);

      this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect);

      positionElement(thisGroup, layoutParam.pos, layoutParam.box);
    };

    Breadcrumb.prototype._prepare = function (targetNode, layoutParam, textStyleModel) {
      for (var node = targetNode; node; node = node.parentNode) {
        var text = convertOptionIdName(node.getModel().get('name'), '');
        var textRect = textStyleModel.getTextRect(text);
        var itemWidth = Math.max(textRect.width + TEXT_PADDING * 2, layoutParam.emptyItemWidth);
        layoutParam.totalWidth += itemWidth + ITEM_GAP;
        layoutParam.renderList.push({
          node: node,
          text: text,
          width: itemWidth
        });
      }
    };

    Breadcrumb.prototype._renderContent = function (seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect) {
      var lastX = 0;
      var emptyItemWidth = layoutParam.emptyItemWidth;
      var height = seriesModel.get(['breadcrumb', 'height']);
      var availableSize = getAvailableSize(layoutParam.pos, layoutParam.box);
      var totalWidth = layoutParam.totalWidth;
      var renderList = layoutParam.renderList;

      for (var i = renderList.length - 1; i >= 0; i--) {
        var item = renderList[i];
        var itemNode = item.node;
        var itemWidth = item.width;
        var text = item.text;

        if (totalWidth > availableSize.width) {
          totalWidth -= itemWidth - emptyItemWidth;
          itemWidth = emptyItemWidth;
          text = null;
        }

        var el = new Polygon({
          shape: {
            points: makeItemPoints(lastX, 0, itemWidth, height, i === renderList.length - 1, i === 0)
          },
          style: defaults(normalStyleModel.getItemStyle(), {
            lineJoin: 'bevel'
          }),
          textContent: new ZRText({
            style: {
              text: text,
              fill: textStyleModel.getTextColor(),
              font: textStyleModel.getFont()
            }
          }),
          textConfig: {
            position: 'inside'
          },
          z: 10,
          onclick: curry(onSelect, itemNode)
        });
        el.disableLabelAnimation = true;
        this.group.add(el);
        packEventData(el, seriesModel, itemNode);
        lastX += itemWidth + ITEM_GAP;
      }
    };

    Breadcrumb.prototype.remove = function () {
      this.group.removeAll();
    };

    return Breadcrumb;
  }();

  function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) {
    var points = [[head ? x : x - ARRAY_LENGTH, y], [x + itemWidth, y], [x + itemWidth, y + itemHeight], [head ? x : x - ARRAY_LENGTH, y + itemHeight]];
    !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]);
    !head && points.push([x, y + itemHeight / 2]);
    return points;
  }

  function packEventData(el, seriesModel, itemNode) {
    getECData(el).eventData = {
      componentType: 'series',
      componentSubType: 'treemap',
      componentIndex: seriesModel.componentIndex,
      seriesIndex: seriesModel.componentIndex,
      seriesName: seriesModel.name,
      seriesType: 'treemap',
      selfType: 'breadcrumb',
      nodeData: {
        dataIndex: itemNode && itemNode.dataIndex,
        name: itemNode && itemNode.name
      },
      treePathInfo: itemNode && wrapTreePathInfo(itemNode, seriesModel)
    };
  }

  var AnimationWrap = function () {
    function AnimationWrap() {
      this._storage = [];
      this._elExistsMap = {};
    }

    AnimationWrap.prototype.add = function (el, target, duration, delay, easing) {
      if (this._elExistsMap[el.id]) {
        return false;
      }

      this._elExistsMap[el.id] = true;

      this._storage.push({
        el: el,
        target: target,
        duration: duration,
        delay: delay,
        easing: easing
      });

      return true;
    };

    AnimationWrap.prototype.finished = function (callback) {
      this._finishedCallback = callback;
      return this;
    };

    AnimationWrap.prototype.start = function () {
      var _this = this;

      var count = this._storage.length;

      var checkTerminate = function () {
        count--;

        if (count <= 0) {
          _this._storage.length = 0;
          _this._elExistsMap = {};
          _this._finishedCallback && _this._finishedCallback();
        }
      };

      for (var i = 0, len = this._storage.length; i < len; i++) {
        var item = this._storage[i];
        item.el.animateTo(item.target, {
          duration: item.duration,
          delay: item.delay,
          easing: item.easing,
          setToFinal: true,
          done: checkTerminate,
          aborted: checkTerminate
        });
      }

      return this;
    };

    return AnimationWrap;
  }();

  function createWrap() {
    return new AnimationWrap();
  }

  var Group$1 = Group;
  var Rect$1 = Rect;
  var DRAG_THRESHOLD = 3;
  var PATH_LABEL_NOAMAL = 'label';
  var PATH_UPPERLABEL_NORMAL = 'upperLabel';
  var Z_BASE = 10;
  var Z_BG = 1;
  var Z_CONTENT = 2;
  var getStateItemStyle = makeStyleMapper([['fill', 'color'], ['stroke', 'strokeColor'], ['lineWidth', 'strokeWidth'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor']]);

  var getItemStyleNormal = function (model) {
    var itemStyle = getStateItemStyle(model);
    itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null;
    return itemStyle;
  };

  var inner$9 = makeInner();

  var TreemapView = function (_super) {
    __extends(TreemapView, _super);

    function TreemapView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TreemapView.type;
      _this._state = 'ready';
      _this._storage = createStorage();
      return _this;
    }

    TreemapView.prototype.render = function (seriesModel, ecModel, api, payload) {
      var models = ecModel.findComponents({
        mainType: 'series',
        subType: 'treemap',
        query: payload
      });

      if (indexOf(models, seriesModel) < 0) {
        return;
      }

      this.seriesModel = seriesModel;
      this.api = api;
      this.ecModel = ecModel;
      var types = ['treemapZoomToNode', 'treemapRootToNode'];
      var targetInfo = retrieveTargetInfo(payload, types, seriesModel);
      var payloadType = payload && payload.type;
      var layoutInfo = seriesModel.layoutInfo;
      var isInit = !this._oldTree;
      var thisStorage = this._storage;
      var reRoot = payloadType === 'treemapRootToNode' && targetInfo && thisStorage ? {
        rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()],
        direction: payload.direction
      } : null;

      var containerGroup = this._giveContainerGroup(layoutInfo);

      var renderResult = this._doRender(containerGroup, seriesModel, reRoot);

      !isInit && (!payloadType || payloadType === 'treemapZoomToNode' || payloadType === 'treemapRootToNode') ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) : renderResult.renderFinally();

      this._resetController(api);

      this._renderBreadcrumb(seriesModel, api, targetInfo);
    };

    TreemapView.prototype._giveContainerGroup = function (layoutInfo) {
      var containerGroup = this._containerGroup;

      if (!containerGroup) {
        containerGroup = this._containerGroup = new Group$1();

        this._initEvents(containerGroup);

        this.group.add(containerGroup);
      }

      containerGroup.x = layoutInfo.x;
      containerGroup.y = layoutInfo.y;
      return containerGroup;
    };

    TreemapView.prototype._doRender = function (containerGroup, seriesModel, reRoot) {
      var thisTree = seriesModel.getData().tree;
      var oldTree = this._oldTree;
      var lastsForAnimation = createStorage();
      var thisStorage = createStorage();
      var oldStorage = this._storage;
      var willInvisibleEls = [];

      function doRenderNode(thisNode, oldNode, parentGroup, depth) {
        return renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth);
      }

      dualTravel(thisTree.root ? [thisTree.root] : [], oldTree && oldTree.root ? [oldTree.root] : [], containerGroup, thisTree === oldTree || !oldTree, 0);
      var willDeleteEls = clearStorage(oldStorage);
      this._oldTree = thisTree;
      this._storage = thisStorage;
      return {
        lastsForAnimation: lastsForAnimation,
        willDeleteEls: willDeleteEls,
        renderFinally: renderFinally
      };

      function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) {
        if (sameTree) {
          oldViewChildren = thisViewChildren;
          each(thisViewChildren, function (child, index) {
            !child.isRemoved() && processNode(index, index);
          });
        } else {
          new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute();
        }

        function getKey(node) {
          return node.getId();
        }

        function processNode(newIndex, oldIndex) {
          var thisNode = newIndex != null ? thisViewChildren[newIndex] : null;
          var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null;
          var group = doRenderNode(thisNode, oldNode, parentGroup, depth);
          group && dualTravel(thisNode && thisNode.viewChildren || [], oldNode && oldNode.viewChildren || [], group, sameTree, depth + 1);
        }
      }

      function clearStorage(storage) {
        var willDeleteEls = createStorage();
        storage && each(storage, function (store, storageName) {
          var delEls = willDeleteEls[storageName];
          each(store, function (el) {
            el && (delEls.push(el), inner$9(el).willDelete = true);
          });
        });
        return willDeleteEls;
      }

      function renderFinally() {
        each(willDeleteEls, function (els) {
          each(els, function (el) {
            el.parent && el.parent.remove(el);
          });
        });
        each(willInvisibleEls, function (el) {
          el.invisible = true;
          el.dirty();
        });
      }
    };

    TreemapView.prototype._doAnimation = function (containerGroup, renderResult, seriesModel, reRoot) {
      if (!seriesModel.get('animation')) {
        return;
      }

      var durationOption = seriesModel.get('animationDurationUpdate');
      var easingOption = seriesModel.get('animationEasing');
      var duration = (isFunction(durationOption) ? 0 : durationOption) || 0;
      var easing = (isFunction(easingOption) ? null : easingOption) || 'cubicOut';
      var animationWrap = createWrap();
      each(renderResult.willDeleteEls, function (store, storageName) {
        each(store, function (el, rawIndex) {
          if (el.invisible) {
            return;
          }

          var parent = el.parent;
          var target;
          var innerStore = inner$9(parent);

          if (reRoot && reRoot.direction === 'drillDown') {
            target = parent === reRoot.rootNodeGroup ? {
              shape: {
                x: 0,
                y: 0,
                width: innerStore.nodeWidth,
                height: innerStore.nodeHeight
              },
              style: {
                opacity: 0
              }
            } : {
              style: {
                opacity: 0
              }
            };
          } else {
            var targetX = 0;
            var targetY = 0;

            if (!innerStore.willDelete) {
              targetX = innerStore.nodeWidth / 2;
              targetY = innerStore.nodeHeight / 2;
            }

            target = storageName === 'nodeGroup' ? {
              x: targetX,
              y: targetY,
              style: {
                opacity: 0
              }
            } : {
              shape: {
                x: targetX,
                y: targetY,
                width: 0,
                height: 0
              },
              style: {
                opacity: 0
              }
            };
          }

          target && animationWrap.add(el, target, duration, 0, easing);
        });
      });
      each(this._storage, function (store, storageName) {
        each(store, function (el, rawIndex) {
          var last = renderResult.lastsForAnimation[storageName][rawIndex];
          var target = {};

          if (!last) {
            return;
          }

          if (el instanceof Group) {
            if (last.oldX != null) {
              target.x = el.x;
              target.y = el.y;
              el.x = last.oldX;
              el.y = last.oldY;
            }
          } else {
            if (last.oldShape) {
              target.shape = extend({}, el.shape);
              el.setShape(last.oldShape);
            }

            if (last.fadein) {
              el.setStyle('opacity', 0);
              target.style = {
                opacity: 1
              };
            } else if (el.style.opacity !== 1) {
              target.style = {
                opacity: 1
              };
            }
          }

          animationWrap.add(el, target, duration, 0, easing);
        });
      }, this);
      this._state = 'animating';
      animationWrap.finished(bind(function () {
        this._state = 'ready';
        renderResult.renderFinally();
      }, this)).start();
    };

    TreemapView.prototype._resetController = function (api) {
      var controller = this._controller;

      if (!controller) {
        controller = this._controller = new RoamController(api.getZr());
        controller.enable(this.seriesModel.get('roam'));
        controller.on('pan', bind(this._onPan, this));
        controller.on('zoom', bind(this._onZoom, this));
      }

      var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight());
      controller.setPointerChecker(function (e, x, y) {
        return rect.contain(x, y);
      });
    };

    TreemapView.prototype._clearController = function () {
      var controller = this._controller;

      if (controller) {
        controller.dispose();
        controller = null;
      }
    };

    TreemapView.prototype._onPan = function (e) {
      if (this._state !== 'animating' && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)) {
        var root = this.seriesModel.getData().tree.root;

        if (!root) {
          return;
        }

        var rootLayout = root.getLayout();

        if (!rootLayout) {
          return;
        }

        this.api.dispatchAction({
          type: 'treemapMove',
          from: this.uid,
          seriesId: this.seriesModel.id,
          rootRect: {
            x: rootLayout.x + e.dx,
            y: rootLayout.y + e.dy,
            width: rootLayout.width,
            height: rootLayout.height
          }
        });
      }
    };

    TreemapView.prototype._onZoom = function (e) {
      var mouseX = e.originX;
      var mouseY = e.originY;

      if (this._state !== 'animating') {
        var root = this.seriesModel.getData().tree.root;

        if (!root) {
          return;
        }

        var rootLayout = root.getLayout();

        if (!rootLayout) {
          return;
        }

        var rect = new BoundingRect(rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height);
        var layoutInfo = this.seriesModel.layoutInfo;
        mouseX -= layoutInfo.x;
        mouseY -= layoutInfo.y;
        var m = create$1();
        translate(m, m, [-mouseX, -mouseY]);
        scale$1(m, m, [e.scale, e.scale]);
        translate(m, m, [mouseX, mouseY]);
        rect.applyTransform(m);
        this.api.dispatchAction({
          type: 'treemapRender',
          from: this.uid,
          seriesId: this.seriesModel.id,
          rootRect: {
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
          }
        });
      }
    };

    TreemapView.prototype._initEvents = function (containerGroup) {
      var _this = this;

      containerGroup.on('click', function (e) {
        if (_this._state !== 'ready') {
          return;
        }

        var nodeClick = _this.seriesModel.get('nodeClick', true);

        if (!nodeClick) {
          return;
        }

        var targetInfo = _this.findTarget(e.offsetX, e.offsetY);

        if (!targetInfo) {
          return;
        }

        var node = targetInfo.node;

        if (node.getLayout().isLeafRoot) {
          _this._rootToNode(targetInfo);
        } else {
          if (nodeClick === 'zoomToNode') {
            _this._zoomToNode(targetInfo);
          } else if (nodeClick === 'link') {
            var itemModel = node.hostTree.data.getItemModel(node.dataIndex);
            var link = itemModel.get('link', true);
            var linkTarget = itemModel.get('target', true) || 'blank';
            link && windowOpen(link, linkTarget);
          }
        }
      }, this);
    };

    TreemapView.prototype._renderBreadcrumb = function (seriesModel, api, targetInfo) {
      var _this = this;

      if (!targetInfo) {
        targetInfo = seriesModel.get('leafDepth', true) != null ? {
          node: seriesModel.getViewRoot()
        } : this.findTarget(api.getWidth() / 2, api.getHeight() / 2);

        if (!targetInfo) {
          targetInfo = {
            node: seriesModel.getData().tree.root
          };
        }
      }

      (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))).render(seriesModel, api, targetInfo.node, function (node) {
        if (_this._state !== 'animating') {
          aboveViewRoot(seriesModel.getViewRoot(), node) ? _this._rootToNode({
            node: node
          }) : _this._zoomToNode({
            node: node
          });
        }
      });
    };

    TreemapView.prototype.remove = function () {
      this._clearController();

      this._containerGroup && this._containerGroup.removeAll();
      this._storage = createStorage();
      this._state = 'ready';
      this._breadcrumb && this._breadcrumb.remove();
    };

    TreemapView.prototype.dispose = function () {
      this._clearController();
    };

    TreemapView.prototype._zoomToNode = function (targetInfo) {
      this.api.dispatchAction({
        type: 'treemapZoomToNode',
        from: this.uid,
        seriesId: this.seriesModel.id,
        targetNode: targetInfo.node
      });
    };

    TreemapView.prototype._rootToNode = function (targetInfo) {
      this.api.dispatchAction({
        type: 'treemapRootToNode',
        from: this.uid,
        seriesId: this.seriesModel.id,
        targetNode: targetInfo.node
      });
    };

    TreemapView.prototype.findTarget = function (x, y) {
      var targetInfo;
      var viewRoot = this.seriesModel.getViewRoot();
      viewRoot.eachNode({
        attr: 'viewChildren',
        order: 'preorder'
      }, function (node) {
        var bgEl = this._storage.background[node.getRawIndex()];

        if (bgEl) {
          var point = bgEl.transformCoordToLocal(x, y);
          var shape = bgEl.shape;

          if (shape.x <= point[0] && point[0] <= shape.x + shape.width && shape.y <= point[1] && point[1] <= shape.y + shape.height) {
            targetInfo = {
              node: node,
              offsetX: point[0],
              offsetY: point[1]
            };
          } else {
            return false;
          }
        }
      }, this);
      return targetInfo;
    };

    TreemapView.type = 'treemap';
    return TreemapView;
  }(ChartView);

  function createStorage() {
    return {
      nodeGroup: [],
      background: [],
      content: []
    };
  }

  function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth) {
    if (!thisNode) {
      return;
    }

    var thisLayout = thisNode.getLayout();
    var data = seriesModel.getData();
    var nodeModel = thisNode.getModel();
    data.setItemGraphicEl(thisNode.dataIndex, null);

    if (!thisLayout || !thisLayout.isInView) {
      return;
    }

    var thisWidth = thisLayout.width;
    var thisHeight = thisLayout.height;
    var borderWidth = thisLayout.borderWidth;
    var thisInvisible = thisLayout.invisible;
    var thisRawIndex = thisNode.getRawIndex();
    var oldRawIndex = oldNode && oldNode.getRawIndex();
    var thisViewChildren = thisNode.viewChildren;
    var upperHeight = thisLayout.upperHeight;
    var isParent = thisViewChildren && thisViewChildren.length;
    var itemStyleNormalModel = nodeModel.getModel('itemStyle');
    var itemStyleEmphasisModel = nodeModel.getModel(['emphasis', 'itemStyle']);
    var itemStyleBlurModel = nodeModel.getModel(['blur', 'itemStyle']);
    var itemStyleSelectModel = nodeModel.getModel(['select', 'itemStyle']);
    var borderRadius = itemStyleNormalModel.get('borderRadius') || 0;
    var group = giveGraphic('nodeGroup', Group$1);

    if (!group) {
      return;
    }

    parentGroup.add(group);
    group.x = thisLayout.x || 0;
    group.y = thisLayout.y || 0;
    group.markRedraw();
    inner$9(group).nodeWidth = thisWidth;
    inner$9(group).nodeHeight = thisHeight;

    if (thisLayout.isAboveViewRoot) {
      return group;
    }

    var bg = giveGraphic('background', Rect$1, depth, Z_BG);
    bg && renderBackground(group, bg, isParent && thisLayout.upperLabelHeight);
    var focus = nodeModel.get(['emphasis', 'focus']);
    var blurScope = nodeModel.get(['emphasis', 'blurScope']);
    var focusDataIndices = focus === 'ancestor' ? thisNode.getAncestorsIndices() : focus === 'descendant' ? thisNode.getDescendantIndices() : null;

    if (isParent) {
      if (isHighDownDispatcher(group)) {
        setAsHighDownDispatcher(group, false);
      }

      if (bg) {
        setAsHighDownDispatcher(bg, true);
        data.setItemGraphicEl(thisNode.dataIndex, bg);
        enableHoverFocus(bg, focusDataIndices || focus, blurScope);
      }
    } else {
      var content = giveGraphic('content', Rect$1, depth, Z_CONTENT);
      content && renderContent(group, content);

      if (bg && isHighDownDispatcher(bg)) {
        setAsHighDownDispatcher(bg, false);
      }

      setAsHighDownDispatcher(group, true);
      data.setItemGraphicEl(thisNode.dataIndex, group);
      enableHoverFocus(group, focusDataIndices || focus, blurScope);
    }

    return group;

    function renderBackground(group, bg, useUpperLabel) {
      var ecData = getECData(bg);
      ecData.dataIndex = thisNode.dataIndex;
      ecData.seriesIndex = seriesModel.seriesIndex;
      bg.setShape({
        x: 0,
        y: 0,
        width: thisWidth,
        height: thisHeight,
        r: borderRadius
      });

      if (thisInvisible) {
        processInvisible(bg);
      } else {
        bg.invisible = false;
        var style = thisNode.getVisual('style');
        var visualBorderColor = style.stroke;
        var normalStyle = getItemStyleNormal(itemStyleNormalModel);
        normalStyle.fill = visualBorderColor;
        var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
        emphasisStyle.fill = itemStyleEmphasisModel.get('borderColor');
        var blurStyle = getStateItemStyle(itemStyleBlurModel);
        blurStyle.fill = itemStyleBlurModel.get('borderColor');
        var selectStyle = getStateItemStyle(itemStyleSelectModel);
        selectStyle.fill = itemStyleSelectModel.get('borderColor');

        if (useUpperLabel) {
          var upperLabelWidth = thisWidth - 2 * borderWidth;
          prepareText(bg, visualBorderColor, upperLabelWidth, upperHeight, style.opacity, {
            x: borderWidth,
            y: 0,
            width: upperLabelWidth,
            height: upperHeight
          });
        } else {
          bg.removeTextContent();
        }

        bg.setStyle(normalStyle);
        bg.ensureState('emphasis').style = emphasisStyle;
        bg.ensureState('blur').style = blurStyle;
        bg.ensureState('select').style = selectStyle;
        setDefaultStateProxy(bg);
      }

      group.add(bg);
    }

    function renderContent(group, content) {
      var ecData = getECData(content);
      ecData.dataIndex = thisNode.dataIndex;
      ecData.seriesIndex = seriesModel.seriesIndex;
      var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0);
      var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0);
      content.culling = true;
      content.setShape({
        x: borderWidth,
        y: borderWidth,
        width: contentWidth,
        height: contentHeight,
        r: borderRadius
      });

      if (thisInvisible) {
        processInvisible(content);
      } else {
        content.invisible = false;
        var nodeStyle = thisNode.getVisual('style');
        var visualColor = nodeStyle.fill;
        var normalStyle = getItemStyleNormal(itemStyleNormalModel);
        normalStyle.fill = visualColor;
        normalStyle.decal = nodeStyle.decal;
        var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
        var blurStyle = getStateItemStyle(itemStyleBlurModel);
        var selectStyle = getStateItemStyle(itemStyleSelectModel);
        prepareText(content, visualColor, contentWidth, nodeStyle.opacity);
        content.setStyle(normalStyle);
        content.ensureState('emphasis').style = emphasisStyle;
        content.ensureState('blur').style = blurStyle;
        content.ensureState('select').style = selectStyle;
        setDefaultStateProxy(content);
      }

      group.add(content);
    }

    function processInvisible(element) {
      !element.invisible && willInvisibleEls.push(element);
    }

    function prepareText(rectEl, visualColor, visualOpacity, width, height, upperLabelRect) {
      var normalLabelModel = nodeModel.getModel(upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL);
      var text = retrieve(seriesModel.getFormattedLabel(thisNode.dataIndex, 'normal', null, null, normalLabelModel.get('formatter')), convertOptionIdName(nodeModel.get('name'), null));

      if (!upperLabelRect && thisLayout.isLeafRoot) {
        var iconChar = seriesModel.get('drillDownIcon', true);
        text = iconChar ? iconChar + ' ' + text : text;
      }

      var isShow = normalLabelModel.getShallow('show');
      setLabelStyle(rectEl, getLabelStatesModels(nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL), {
        defaultText: isShow ? text : null,
        inheritColor: visualColor,
        defaultOpacity: visualOpacity,
        labelFetcher: seriesModel,
        labelDataIndex: thisNode.dataIndex
      });
      var textEl = rectEl.getTextContent();
      var textStyle = textEl.style;
      var textPadding = normalizeCssArray(textStyle.padding || 0);

      if (upperLabelRect) {
        rectEl.setTextConfig({
          layoutRect: upperLabelRect
        });
        textEl.disableLabelLayout = true;
      }

      textEl.beforeUpdate = function () {
        var width = Math.max((upperLabelRect ? upperLabelRect.width : rectEl.shape.width) - textPadding[1] - textPadding[3], 0);
        var height = Math.max((upperLabelRect ? upperLabelRect.height : rectEl.shape.height) - textPadding[0] - textPadding[2], 0);

        if (textStyle.width !== width || textStyle.height !== height) {
          textEl.setStyle({
            width: width,
            height: height
          });
        }
      };

      textStyle.truncateMinChar = 2;
      textStyle.lineOverflow = 'truncate';
      addDrillDownIcon(textStyle, upperLabelRect, thisLayout);
      var textEmphasisState = textEl.getState('emphasis');
      addDrillDownIcon(textEmphasisState ? textEmphasisState.style : null, upperLabelRect, thisLayout);
    }

    function addDrillDownIcon(style, upperLabelRect, thisLayout) {
      var text = style ? style.text : null;

      if (!upperLabelRect && thisLayout.isLeafRoot && text != null) {
        var iconChar = seriesModel.get('drillDownIcon', true);
        style.text = iconChar ? iconChar + ' ' + text : text;
      }
    }

    function giveGraphic(storageName, Ctor, depth, z) {
      var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex];
      var lasts = lastsForAnimation[storageName];

      if (element) {
        oldStorage[storageName][oldRawIndex] = null;
        prepareAnimationWhenHasOld(lasts, element);
      } else if (!thisInvisible) {
        element = new Ctor();

        if (element instanceof Displayable) {
          element.z = calculateZ(depth, z);
        }

        prepareAnimationWhenNoOld(lasts, element);
      }

      return thisStorage[storageName][thisRawIndex] = element;
    }

    function prepareAnimationWhenHasOld(lasts, element) {
      var lastCfg = lasts[thisRawIndex] = {};

      if (element instanceof Group$1) {
        lastCfg.oldX = element.x;
        lastCfg.oldY = element.y;
      } else {
        lastCfg.oldShape = extend({}, element.shape);
      }
    }

    function prepareAnimationWhenNoOld(lasts, element) {
      var lastCfg = lasts[thisRawIndex] = {};
      var parentNode = thisNode.parentNode;
      var isGroup = element instanceof Group;

      if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) {
        var parentOldX = 0;
        var parentOldY = 0;
        var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()];

        if (!reRoot && parentOldBg && parentOldBg.oldShape) {
          parentOldX = parentOldBg.oldShape.width;
          parentOldY = parentOldBg.oldShape.height;
        }

        if (isGroup) {
          lastCfg.oldX = 0;
          lastCfg.oldY = parentOldY;
        } else {
          lastCfg.oldShape = {
            x: parentOldX,
            y: parentOldY,
            width: 0,
            height: 0
          };
        }
      }

      lastCfg.fadein = !isGroup;
    }
  }

  function calculateZ(depth, zInLevel) {
    var zb = depth * Z_BASE + zInLevel;
    return (zb - 1) / zb;
  }

  ChartView.registerClass(TreemapView);

  var noop$1 = function () {};

  var actionTypes = ['treemapZoomToNode', 'treemapRender', 'treemapMove'];

  for (var i$1 = 0; i$1 < actionTypes.length; i$1++) {
    registerAction({
      type: actionTypes[i$1],
      update: 'updateView'
    }, noop$1);
  }

  registerAction({
    type: 'treemapRootToNode',
    update: 'updateView'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'treemap',
      query: payload
    }, handleRootToNode);

    function handleRootToNode(model, index) {
      var types = ['treemapZoomToNode', 'treemapRootToNode'];
      var targetInfo = retrieveTargetInfo(payload, types, model);

      if (targetInfo) {
        var originViewRoot = model.getViewRoot();

        if (originViewRoot) {
          payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown';
        }

        model.resetViewRoot(targetInfo.node);
      }
    }
  });
  var each$4 = each;
  var isObject$4 = isObject;
  var CATEGORY_DEFAULT_VISUAL_INDEX = -1;

  var VisualMapping = function () {
    function VisualMapping(option) {
      var mappingMethod = option.mappingMethod;
      var visualType = option.type;
      var thisOption = this.option = clone(option);
      this.type = visualType;
      this.mappingMethod = mappingMethod;
      this._normalizeData = normalizers[mappingMethod];
      var visualHandler = VisualMapping.visualHandlers[visualType];
      this.applyVisual = visualHandler.applyVisual;
      this.getColorMapper = visualHandler.getColorMapper;
      this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod];

      if (mappingMethod === 'piecewise') {
        normalizeVisualRange(thisOption);
        preprocessForPiecewise(thisOption);
      } else if (mappingMethod === 'category') {
        thisOption.categories ? preprocessForSpecifiedCategory(thisOption) : normalizeVisualRange(thisOption, true);
      } else {
        assert(mappingMethod !== 'linear' || thisOption.dataExtent);
        normalizeVisualRange(thisOption);
      }
    }

    VisualMapping.prototype.mapValueToVisual = function (value) {
      var normalized = this._normalizeData(value);

      return this._normalizedToVisual(normalized, value);
    };

    VisualMapping.prototype.getNormalizer = function () {
      return bind(this._normalizeData, this);
    };

    VisualMapping.listVisualTypes = function () {
      return keys(VisualMapping.visualHandlers);
    };

    VisualMapping.isValidType = function (visualType) {
      return VisualMapping.visualHandlers.hasOwnProperty(visualType);
    };

    VisualMapping.eachVisual = function (visual, callback, context) {
      if (isObject(visual)) {
        each(visual, callback, context);
      } else {
        callback.call(context, visual);
      }
    };

    VisualMapping.mapVisual = function (visual, callback, context) {
      var isPrimary;
      var newVisual = isArray(visual) ? [] : isObject(visual) ? {} : (isPrimary = true, null);
      VisualMapping.eachVisual(visual, function (v, key) {
        var newVal = callback.call(context, v, key);
        isPrimary ? newVisual = newVal : newVisual[key] = newVal;
      });
      return newVisual;
    };

    VisualMapping.retrieveVisuals = function (obj) {
      var ret = {};
      var hasVisual;
      obj && each$4(VisualMapping.visualHandlers, function (h, visualType) {
        if (obj.hasOwnProperty(visualType)) {
          ret[visualType] = obj[visualType];
          hasVisual = true;
        }
      });
      return hasVisual ? ret : null;
    };

    VisualMapping.prepareVisualTypes = function (visualTypes) {
      if (isArray(visualTypes)) {
        visualTypes = visualTypes.slice();
      } else if (isObject$4(visualTypes)) {
        var types_1 = [];
        each$4(visualTypes, function (item, type) {
          types_1.push(type);
        });
        visualTypes = types_1;
      } else {
        return [];
      }

      visualTypes.sort(function (type1, type2) {
        return type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0 ? 1 : -1;
      });
      return visualTypes;
    };

    VisualMapping.dependsOn = function (visualType1, visualType2) {
      return visualType2 === 'color' ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) : visualType1 === visualType2;
    };

    VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) {
      var possibleI;
      var abs = Infinity;

      for (var i = 0, len = pieceList.length; i < len; i++) {
        var pieceValue = pieceList[i].value;

        if (pieceValue != null) {
          if (pieceValue === value || typeof pieceValue === 'string' && pieceValue === value + '') {
            return i;
          }

          findClosestWhenOutside && updatePossible(pieceValue, i);
        }
      }

      for (var i = 0, len = pieceList.length; i < len; i++) {
        var piece = pieceList[i];
        var interval = piece.interval;
        var close_1 = piece.close;

        if (interval) {
          if (interval[0] === -Infinity) {
            if (littleThan(close_1[1], value, interval[1])) {
              return i;
            }
          } else if (interval[1] === Infinity) {
            if (littleThan(close_1[0], interval[0], value)) {
              return i;
            }
          } else if (littleThan(close_1[0], interval[0], value) && littleThan(close_1[1], value, interval[1])) {
            return i;
          }

          findClosestWhenOutside && updatePossible(interval[0], i);
          findClosestWhenOutside && updatePossible(interval[1], i);
        }
      }

      if (findClosestWhenOutside) {
        return value === Infinity ? pieceList.length - 1 : value === -Infinity ? 0 : possibleI;
      }

      function updatePossible(val, index) {
        var newAbs = Math.abs(val - value);

        if (newAbs < abs) {
          abs = newAbs;
          possibleI = index;
        }
      }
    };

    VisualMapping.visualHandlers = {
      color: {
        applyVisual: makeApplyVisual('color'),
        getColorMapper: function () {
          var thisOption = this.option;
          return bind(thisOption.mappingMethod === 'category' ? function (value, isNormalized) {
            !isNormalized && (value = this._normalizeData(value));
            return doMapCategory.call(this, value);
          } : function (value, isNormalized, out) {
            var returnRGBArray = !!out;
            !isNormalized && (value = this._normalizeData(value));
            out = fastLerp(value, thisOption.parsedVisual, out);
            return returnRGBArray ? out : stringify(out, 'rgba');
          }, this);
        },
        _normalizedToVisual: {
          linear: function (normalized) {
            return stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba');
          },
          category: doMapCategory,
          piecewise: function (normalized, value) {
            var result = getSpecifiedVisual.call(this, value);

            if (result == null) {
              result = stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba');
            }

            return result;
          },
          fixed: doMapFixed
        }
      },
      colorHue: makePartialColorVisualHandler(function (color$1, value) {
        return modifyHSL(color$1, value);
      }),
      colorSaturation: makePartialColorVisualHandler(function (color$1, value) {
        return modifyHSL(color$1, null, value);
      }),
      colorLightness: makePartialColorVisualHandler(function (color$1, value) {
        return modifyHSL(color$1, null, null, value);
      }),
      colorAlpha: makePartialColorVisualHandler(function (color$1, value) {
        return modifyAlpha(color$1, value);
      }),
      decal: {
        applyVisual: makeApplyVisual('decal'),
        _normalizedToVisual: {
          linear: null,
          category: doMapCategory,
          piecewise: null,
          fixed: null
        }
      },
      opacity: {
        applyVisual: makeApplyVisual('opacity'),
        _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
      },
      liftZ: {
        applyVisual: makeApplyVisual('liftZ'),
        _normalizedToVisual: {
          linear: doMapFixed,
          category: doMapFixed,
          piecewise: doMapFixed,
          fixed: doMapFixed
        }
      },
      symbol: {
        applyVisual: function (value, getter, setter) {
          var symbolCfg = this.mapValueToVisual(value);
          setter('symbol', symbolCfg);
        },
        _normalizedToVisual: {
          linear: doMapToArray,
          category: doMapCategory,
          piecewise: function (normalized, value) {
            var result = getSpecifiedVisual.call(this, value);

            if (result == null) {
              result = doMapToArray.call(this, normalized);
            }

            return result;
          },
          fixed: doMapFixed
        }
      },
      symbolSize: {
        applyVisual: makeApplyVisual('symbolSize'),
        _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
      }
    };
    return VisualMapping;
  }();

  function preprocessForPiecewise(thisOption) {
    var pieceList = thisOption.pieceList;
    thisOption.hasSpecialVisual = false;
    each(pieceList, function (piece, index) {
      piece.originIndex = index;

      if (piece.visual != null) {
        thisOption.hasSpecialVisual = true;
      }
    });
  }

  function preprocessForSpecifiedCategory(thisOption) {
    var categories = thisOption.categories;
    var categoryMap = thisOption.categoryMap = {};
    var visual = thisOption.visual;
    each$4(categories, function (cate, index) {
      categoryMap[cate] = index;
    });

    if (!isArray(visual)) {
      var visualArr_1 = [];

      if (isObject(visual)) {
        each$4(visual, function (v, cate) {
          var index = categoryMap[cate];
          visualArr_1[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
        });
      } else {
        visualArr_1[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
      }

      visual = setVisualToOption(thisOption, visualArr_1);
    }

    for (var i = categories.length - 1; i >= 0; i--) {
      if (visual[i] == null) {
        delete categoryMap[categories[i]];
        categories.pop();
      }
    }
  }

  function normalizeVisualRange(thisOption, isCategory) {
    var visual = thisOption.visual;
    var visualArr = [];

    if (isObject(visual)) {
      each$4(visual, function (v) {
        visualArr.push(v);
      });
    } else if (visual != null) {
      visualArr.push(visual);
    }

    var doNotNeedPair = {
      color: 1,
      symbol: 1
    };

    if (!isCategory && visualArr.length === 1 && !doNotNeedPair.hasOwnProperty(thisOption.type)) {
      visualArr[1] = visualArr[0];
    }

    setVisualToOption(thisOption, visualArr);
  }

  function makePartialColorVisualHandler(applyValue) {
    return {
      applyVisual: function (value, getter, setter) {
        var colorChannel = this.mapValueToVisual(value);
        setter('color', applyValue(getter('color'), colorChannel));
      },
      _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
    };
  }

  function doMapToArray(normalized) {
    var visual = this.option.visual;
    return visual[Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))] || {};
  }

  function makeApplyVisual(visualType) {
    return function (value, getter, setter) {
      setter(visualType, this.mapValueToVisual(value));
    };
  }

  function doMapCategory(normalized) {
    var visual = this.option.visual;
    return visual[this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX ? normalized % visual.length : normalized];
  }

  function doMapFixed() {
    return this.option.visual[0];
  }

  function createNormalizedToNumericVisual(sourceExtent) {
    return {
      linear: function (normalized) {
        return linearMap(normalized, sourceExtent, this.option.visual, true);
      },
      category: doMapCategory,
      piecewise: function (normalized, value) {
        var result = getSpecifiedVisual.call(this, value);

        if (result == null) {
          result = linearMap(normalized, sourceExtent, this.option.visual, true);
        }

        return result;
      },
      fixed: doMapFixed
    };
  }

  function getSpecifiedVisual(value) {
    var thisOption = this.option;
    var pieceList = thisOption.pieceList;

    if (thisOption.hasSpecialVisual) {
      var pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
      var piece = pieceList[pieceIndex];

      if (piece && piece.visual) {
        return piece.visual[this.type];
      }
    }
  }

  function setVisualToOption(thisOption, visualArr) {
    thisOption.visual = visualArr;

    if (thisOption.type === 'color') {
      thisOption.parsedVisual = map(visualArr, function (item) {
        return parse(item);
      });
    }

    return visualArr;
  }

  var normalizers = {
    linear: function (value) {
      return linearMap(value, this.option.dataExtent, [0, 1], true);
    },
    piecewise: function (value) {
      var pieceList = this.option.pieceList;
      var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true);

      if (pieceIndex != null) {
        return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
      }
    },
    category: function (value) {
      var index = this.option.categories ? this.option.categoryMap[value] : value;
      return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
    },
    fixed: noop
  };

  function littleThan(close, a, b) {
    return close ? a <= b : a < b;
  }

  var ITEM_STYLE_NORMAL = 'itemStyle';
  var inner$a = makeInner();
  var treemapVisual = {
    seriesType: 'treemap',
    reset: function (seriesModel) {
      var tree = seriesModel.getData().tree;
      var root = tree.root;

      if (root.isRemoved()) {
        return;
      }

      travelTree(root, {}, seriesModel.getViewRoot().getAncestors(), seriesModel);
    }
  };

  function travelTree(node, designatedVisual, viewRootAncestors, seriesModel) {
    var nodeModel = node.getModel();
    var nodeLayout = node.getLayout();
    var data = node.hostTree.data;

    if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) {
      return;
    }

    var nodeItemStyleModel = nodeModel.getModel(ITEM_STYLE_NORMAL);
    var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel);
    var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style');
    var borderColor = nodeItemStyleModel.get('borderColor');
    var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation');
    var thisNodeColor;

    if (borderColorSaturation != null) {
      thisNodeColor = calculateColor(visuals);
      borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor);
    }

    existsStyle.stroke = borderColor;
    var viewChildren = node.viewChildren;

    if (!viewChildren || !viewChildren.length) {
      thisNodeColor = calculateColor(visuals);
      existsStyle.fill = thisNodeColor;
    } else {
      var mapping_1 = buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren);
      each(viewChildren, function (child, index) {
        if (child.depth >= viewRootAncestors.length || child === viewRootAncestors[child.depth]) {
          var childVisual = mapVisual(nodeModel, visuals, child, index, mapping_1, seriesModel);
          travelTree(child, childVisual, viewRootAncestors, seriesModel);
        }
      });
    }
  }

  function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) {
    var visuals = extend({}, designatedVisual);
    var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle;
    each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
      designatedVisualItemStyle[visualName] = designatedVisual[visualName];
      var val = nodeItemStyleModel.get(visualName);
      designatedVisualItemStyle[visualName] = null;
      val != null && (visuals[visualName] = val);
    });
    return visuals;
  }

  function calculateColor(visuals) {
    var color = getValueVisualDefine(visuals, 'color');

    if (color) {
      var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha');
      var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation');

      if (colorSaturation) {
        color = modifyHSL(color, null, null, colorSaturation);
      }

      if (colorAlpha) {
        color = modifyAlpha(color, colorAlpha);
      }

      return color;
    }
  }

  function calculateBorderColor(borderColorSaturation, thisNodeColor) {
    return thisNodeColor != null ? modifyHSL(thisNodeColor, null, null, borderColorSaturation) : null;
  }

  function getValueVisualDefine(visuals, name) {
    var value = visuals[name];

    if (value != null && value !== 'none') {
      return value;
    }
  }

  function buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren) {
    if (!viewChildren || !viewChildren.length) {
      return;
    }

    var rangeVisual = getRangeVisual(nodeModel, 'color') || visuals.color != null && visuals.color !== 'none' && (getRangeVisual(nodeModel, 'colorAlpha') || getRangeVisual(nodeModel, 'colorSaturation'));

    if (!rangeVisual) {
      return;
    }

    var visualMin = nodeModel.get('visualMin');
    var visualMax = nodeModel.get('visualMax');
    var dataExtent = nodeLayout.dataExtent.slice();
    visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin);
    visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax);
    var colorMappingBy = nodeModel.get('colorMappingBy');
    var opt = {
      type: rangeVisual.name,
      dataExtent: dataExtent,
      visual: rangeVisual.range
    };

    if (opt.type === 'color' && (colorMappingBy === 'index' || colorMappingBy === 'id')) {
      opt.mappingMethod = 'category';
      opt.loop = true;
    } else {
      opt.mappingMethod = 'linear';
    }

    var mapping = new VisualMapping(opt);
    inner$a(mapping).drColorMappingBy = colorMappingBy;
    return mapping;
  }

  function getRangeVisual(nodeModel, name) {
    var range = nodeModel.get(name);
    return isArray(range) && range.length ? {
      name: name,
      range: range
    } : null;
  }

  function mapVisual(nodeModel, visuals, child, index, mapping, seriesModel) {
    var childVisuals = extend({}, visuals);

    if (mapping) {
      var mappingType = mapping.type;
      var colorMappingBy = mappingType === 'color' && inner$a(mapping).drColorMappingBy;
      var value = colorMappingBy === 'index' ? index : colorMappingBy === 'id' ? seriesModel.mapIdToIndex(child.getId()) : child.getValue(nodeModel.get('visualDimension'));
      childVisuals[mappingType] = mapping.mapValueToVisual(value);
    }

    return childVisuals;
  }

  var mathMax$7 = Math.max;
  var mathMin$7 = Math.min;
  var retrieveValue = retrieve;
  var each$5 = each;
  var PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth'];
  var PATH_GAP_WIDTH = ['itemStyle', 'gapWidth'];
  var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'show'];
  var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'height'];
  var treemapLayout = {
    seriesType: 'treemap',
    reset: function (seriesModel, ecModel, api, payload) {
      var ecWidth = api.getWidth();
      var ecHeight = api.getHeight();
      var seriesOption = seriesModel.option;
      var layoutInfo = getLayoutRect(seriesModel.getBoxLayoutParams(), {
        width: api.getWidth(),
        height: api.getHeight()
      });
      var size = seriesOption.size || [];
      var containerWidth = parsePercent$2(retrieveValue(layoutInfo.width, size[0]), ecWidth);
      var containerHeight = parsePercent$2(retrieveValue(layoutInfo.height, size[1]), ecHeight);
      var payloadType = payload && payload.type;
      var types = ['treemapZoomToNode', 'treemapRootToNode'];
      var targetInfo = retrieveTargetInfo(payload, types, seriesModel);
      var rootRect = payloadType === 'treemapRender' || payloadType === 'treemapMove' ? payload.rootRect : null;
      var viewRoot = seriesModel.getViewRoot();
      var viewAbovePath = getPathToRoot(viewRoot);

      if (payloadType !== 'treemapMove') {
        var rootSize = payloadType === 'treemapZoomToNode' ? estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) : rootRect ? [rootRect.width, rootRect.height] : [containerWidth, containerHeight];
        var sort_1 = seriesOption.sort;

        if (sort_1 && sort_1 !== 'asc' && sort_1 !== 'desc') {
          sort_1 = 'desc';
        }

        var options = {
          squareRatio: seriesOption.squareRatio,
          sort: sort_1,
          leafDepth: seriesOption.leafDepth
        };
        viewRoot.hostTree.clearLayouts();
        var viewRootLayout_1 = {
          x: 0,
          y: 0,
          width: rootSize[0],
          height: rootSize[1],
          area: rootSize[0] * rootSize[1]
        };
        viewRoot.setLayout(viewRootLayout_1);
        squarify(viewRoot, options, false, 0);
        viewRootLayout_1 = viewRoot.getLayout();
        each$5(viewAbovePath, function (node, index) {
          var childValue = (viewAbovePath[index + 1] || viewRoot).getValue();
          node.setLayout(extend({
            dataExtent: [childValue, childValue],
            borderWidth: 0,
            upperHeight: 0
          }, viewRootLayout_1));
        });
      }

      var treeRoot = seriesModel.getData().tree.root;
      treeRoot.setLayout(calculateRootPosition(layoutInfo, rootRect, targetInfo), true);
      seriesModel.setLayoutInfo(layoutInfo);
      prunning(treeRoot, new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight), viewAbovePath, viewRoot, 0);
    }
  };

  function squarify(node, options, hideChildren, depth) {
    var width;
    var height;

    if (node.isRemoved()) {
      return;
    }

    var thisLayout = node.getLayout();
    width = thisLayout.width;
    height = thisLayout.height;
    var nodeModel = node.getModel();
    var borderWidth = nodeModel.get(PATH_BORDER_WIDTH);
    var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2;
    var upperLabelHeight = getUpperLabelHeight(nodeModel);
    var upperHeight = Math.max(borderWidth, upperLabelHeight);
    var layoutOffset = borderWidth - halfGapWidth;
    var layoutOffsetUpper = upperHeight - halfGapWidth;
    node.setLayout({
      borderWidth: borderWidth,
      upperHeight: upperHeight,
      upperLabelHeight: upperLabelHeight
    }, true);
    width = mathMax$7(width - 2 * layoutOffset, 0);
    height = mathMax$7(height - layoutOffset - layoutOffsetUpper, 0);
    var totalArea = width * height;
    var viewChildren = initChildren(node, nodeModel, totalArea, options, hideChildren, depth);

    if (!viewChildren.length) {
      return;
    }

    var rect = {
      x: layoutOffset,
      y: layoutOffsetUpper,
      width: width,
      height: height
    };
    var rowFixedLength = mathMin$7(width, height);
    var best = Infinity;
    var row = [];
    row.area = 0;

    for (var i = 0, len = viewChildren.length; i < len;) {
      var child = viewChildren[i];
      row.push(child);
      row.area += child.getLayout().area;
      var score = worst(row, rowFixedLength, options.squareRatio);

      if (score <= best) {
        i++;
        best = score;
      } else {
        row.area -= row.pop().getLayout().area;
        position(row, rowFixedLength, rect, halfGapWidth, false);
        rowFixedLength = mathMin$7(rect.width, rect.height);
        row.length = row.area = 0;
        best = Infinity;
      }
    }

    if (row.length) {
      position(row, rowFixedLength, rect, halfGapWidth, true);
    }

    if (!hideChildren) {
      var childrenVisibleMin = nodeModel.get('childrenVisibleMin');

      if (childrenVisibleMin != null && totalArea < childrenVisibleMin) {
        hideChildren = true;
      }
    }

    for (var i = 0, len = viewChildren.length; i < len; i++) {
      squarify(viewChildren[i], options, hideChildren, depth + 1);
    }
  }

  function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) {
    var viewChildren = node.children || [];
    var orderBy = options.sort;
    orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null);
    var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth;

    if (hideChildren && !overLeafDepth) {
      return node.viewChildren = [];
    }

    viewChildren = filter(viewChildren, function (child) {
      return !child.isRemoved();
    });
    sort$1(viewChildren, orderBy);
    var info = statistic(nodeModel, viewChildren, orderBy);

    if (info.sum === 0) {
      return node.viewChildren = [];
    }

    info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren);

    if (info.sum === 0) {
      return node.viewChildren = [];
    }

    for (var i = 0, len = viewChildren.length; i < len; i++) {
      var area = viewChildren[i].getValue() / info.sum * totalArea;
      viewChildren[i].setLayout({
        area: area
      });
    }

    if (overLeafDepth) {
      viewChildren.length && node.setLayout({
        isLeafRoot: true
      }, true);
      viewChildren.length = 0;
    }

    node.viewChildren = viewChildren;
    node.setLayout({
      dataExtent: info.dataExtent
    }, true);
    return viewChildren;
  }

  function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) {
    if (!orderBy) {
      return sum;
    }

    var visibleMin = nodeModel.get('visibleMin');
    var len = orderedChildren.length;
    var deletePoint = len;

    for (var i = len - 1; i >= 0; i--) {
      var value = orderedChildren[orderBy === 'asc' ? len - i - 1 : i].getValue();

      if (value / sum * totalArea < visibleMin) {
        deletePoint = i;
        sum -= value;
      }
    }

    orderBy === 'asc' ? orderedChildren.splice(0, len - deletePoint) : orderedChildren.splice(deletePoint, len - deletePoint);
    return sum;
  }

  function sort$1(viewChildren, orderBy) {
    if (orderBy) {
      viewChildren.sort(function (a, b) {
        var diff = orderBy === 'asc' ? a.getValue() - b.getValue() : b.getValue() - a.getValue();
        return diff === 0 ? orderBy === 'asc' ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex : diff;
      });
    }

    return viewChildren;
  }

  function statistic(nodeModel, children, orderBy) {
    var sum = 0;

    for (var i = 0, len = children.length; i < len; i++) {
      sum += children[i].getValue();
    }

    var dimension = nodeModel.get('visualDimension');
    var dataExtent;

    if (!children || !children.length) {
      dataExtent = [NaN, NaN];
    } else if (dimension === 'value' && orderBy) {
      dataExtent = [children[children.length - 1].getValue(), children[0].getValue()];
      orderBy === 'asc' && dataExtent.reverse();
    } else {
      dataExtent = [Infinity, -Infinity];
      each$5(children, function (child) {
        var value = child.getValue(dimension);
        value < dataExtent[0] && (dataExtent[0] = value);
        value > dataExtent[1] && (dataExtent[1] = value);
      });
    }

    return {
      sum: sum,
      dataExtent: dataExtent
    };
  }

  function worst(row, rowFixedLength, ratio) {
    var areaMax = 0;
    var areaMin = Infinity;

    for (var i = 0, area = void 0, len = row.length; i < len; i++) {
      area = row[i].getLayout().area;

      if (area) {
        area < areaMin && (areaMin = area);
        area > areaMax && (areaMax = area);
      }
    }

    var squareArea = row.area * row.area;
    var f = rowFixedLength * rowFixedLength * ratio;
    return squareArea ? mathMax$7(f * areaMax / squareArea, squareArea / (f * areaMin)) : Infinity;
  }

  function position(row, rowFixedLength, rect, halfGapWidth, flush) {
    var idx0WhenH = rowFixedLength === rect.width ? 0 : 1;
    var idx1WhenH = 1 - idx0WhenH;
    var xy = ['x', 'y'];
    var wh = ['width', 'height'];
    var last = rect[xy[idx0WhenH]];
    var rowOtherLength = rowFixedLength ? row.area / rowFixedLength : 0;

    if (flush || rowOtherLength > rect[wh[idx1WhenH]]) {
      rowOtherLength = rect[wh[idx1WhenH]];
    }

    for (var i = 0, rowLen = row.length; i < rowLen; i++) {
      var node = row[i];
      var nodeLayout = {};
      var step = rowOtherLength ? node.getLayout().area / rowOtherLength : 0;
      var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax$7(rowOtherLength - 2 * halfGapWidth, 0);
      var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last;
      var modWH = i === rowLen - 1 || remain < step ? remain : step;
      var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax$7(modWH - 2 * halfGapWidth, 0);
      nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin$7(halfGapWidth, wh1 / 2);
      nodeLayout[xy[idx0WhenH]] = last + mathMin$7(halfGapWidth, wh0 / 2);
      last += modWH;
      node.setLayout(nodeLayout, true);
    }

    rect[xy[idx1WhenH]] += rowOtherLength;
    rect[wh[idx1WhenH]] -= rowOtherLength;
  }

  function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
    var currNode = (targetInfo || {}).node;
    var defaultSize = [containerWidth, containerHeight];

    if (!currNode || currNode === viewRoot) {
      return defaultSize;
    }

    var parent;
    var viewArea = containerWidth * containerHeight;
    var area = viewArea * seriesModel.option.zoomToNodeRatio;

    while (parent = currNode.parentNode) {
      var sum = 0;
      var siblings = parent.children;

      for (var i = 0, len = siblings.length; i < len; i++) {
        sum += siblings[i].getValue();
      }

      var currNodeValue = currNode.getValue();

      if (currNodeValue === 0) {
        return defaultSize;
      }

      area *= sum / currNodeValue;
      var parentModel = parent.getModel();
      var borderWidth = parentModel.get(PATH_BORDER_WIDTH);
      var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel));
      area += 4 * borderWidth * borderWidth + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5);
      area > MAX_SAFE_INTEGER && (area = MAX_SAFE_INTEGER);
      currNode = parent;
    }

    area < viewArea && (area = viewArea);
    var scale = Math.pow(area / viewArea, 0.5);
    return [containerWidth * scale, containerHeight * scale];
  }

  function calculateRootPosition(layoutInfo, rootRect, targetInfo) {
    if (rootRect) {
      return {
        x: rootRect.x,
        y: rootRect.y
      };
    }

    var defaultPosition = {
      x: 0,
      y: 0
    };

    if (!targetInfo) {
      return defaultPosition;
    }

    var targetNode = targetInfo.node;
    var layout = targetNode.getLayout();

    if (!layout) {
      return defaultPosition;
    }

    var targetCenter = [layout.width / 2, layout.height / 2];
    var node = targetNode;

    while (node) {
      var nodeLayout = node.getLayout();
      targetCenter[0] += nodeLayout.x;
      targetCenter[1] += nodeLayout.y;
      node = node.parentNode;
    }

    return {
      x: layoutInfo.width / 2 - targetCenter[0],
      y: layoutInfo.height / 2 - targetCenter[1]
    };
  }

  function prunning(node, clipRect, viewAbovePath, viewRoot, depth) {
    var nodeLayout = node.getLayout();
    var nodeInViewAbovePath = viewAbovePath[depth];
    var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node;

    if (nodeInViewAbovePath && !isAboveViewRoot || depth === viewAbovePath.length && node !== viewRoot) {
      return;
    }

    node.setLayout({
      isInView: true,
      invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout),
      isAboveViewRoot: isAboveViewRoot
    }, true);
    var childClipRect = new BoundingRect(clipRect.x - nodeLayout.x, clipRect.y - nodeLayout.y, clipRect.width, clipRect.height);
    each$5(node.viewChildren || [], function (child) {
      prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1);
    });
  }

  function getUpperLabelHeight(model) {
    return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0;
  }

  registerVisual(treemapVisual);
  registerLayout(treemapLayout);

  function generateNodeKey(id) {
    return '_EC_' + id;
  }

  var Graph = function () {
    function Graph(directed) {
      this.type = 'graph';
      this.nodes = [];
      this.edges = [];
      this._nodesMap = {};
      this._edgesMap = {};
      this._directed = directed || false;
    }

    Graph.prototype.isDirected = function () {
      return this._directed;
    };

    Graph.prototype.addNode = function (id, dataIndex) {
      id = id == null ? '' + dataIndex : '' + id;
      var nodesMap = this._nodesMap;

      if (nodesMap[generateNodeKey(id)]) {
        if (true) {
          console.error('Graph nodes have duplicate name or id');
        }

        return;
      }

      var node = new GraphNode(id, dataIndex);
      node.hostGraph = this;
      this.nodes.push(node);
      nodesMap[generateNodeKey(id)] = node;
      return node;
    };

    Graph.prototype.getNodeByIndex = function (dataIndex) {
      var rawIdx = this.data.getRawIndex(dataIndex);
      return this.nodes[rawIdx];
    };

    Graph.prototype.getNodeById = function (id) {
      return this._nodesMap[generateNodeKey(id)];
    };

    Graph.prototype.addEdge = function (n1, n2, dataIndex) {
      var nodesMap = this._nodesMap;
      var edgesMap = this._edgesMap;

      if (typeof n1 === 'number') {
        n1 = this.nodes[n1];
      }

      if (typeof n2 === 'number') {
        n2 = this.nodes[n2];
      }

      if (!(n1 instanceof GraphNode)) {
        n1 = nodesMap[generateNodeKey(n1)];
      }

      if (!(n2 instanceof GraphNode)) {
        n2 = nodesMap[generateNodeKey(n2)];
      }

      if (!n1 || !n2) {
        return;
      }

      var key = n1.id + '-' + n2.id;
      var edge = new GraphEdge(n1, n2, dataIndex);
      edge.hostGraph = this;

      if (this._directed) {
        n1.outEdges.push(edge);
        n2.inEdges.push(edge);
      }

      n1.edges.push(edge);

      if (n1 !== n2) {
        n2.edges.push(edge);
      }

      this.edges.push(edge);
      edgesMap[key] = edge;
      return edge;
    };

    Graph.prototype.getEdgeByIndex = function (dataIndex) {
      var rawIdx = this.edgeData.getRawIndex(dataIndex);
      return this.edges[rawIdx];
    };

    Graph.prototype.getEdge = function (n1, n2) {
      if (n1 instanceof GraphNode) {
        n1 = n1.id;
      }

      if (n2 instanceof GraphNode) {
        n2 = n2.id;
      }

      var edgesMap = this._edgesMap;

      if (this._directed) {
        return edgesMap[n1 + '-' + n2];
      } else {
        return edgesMap[n1 + '-' + n2] || edgesMap[n2 + '-' + n1];
      }
    };

    Graph.prototype.eachNode = function (cb, context) {
      var nodes = this.nodes;
      var len = nodes.length;

      for (var i = 0; i < len; i++) {
        if (nodes[i].dataIndex >= 0) {
          cb.call(context, nodes[i], i);
        }
      }
    };

    Graph.prototype.eachEdge = function (cb, context) {
      var edges = this.edges;
      var len = edges.length;

      for (var i = 0; i < len; i++) {
        if (edges[i].dataIndex >= 0 && edges[i].node1.dataIndex >= 0 && edges[i].node2.dataIndex >= 0) {
          cb.call(context, edges[i], i);
        }
      }
    };

    Graph.prototype.breadthFirstTraverse = function (cb, startNode, direction, context) {
      if (!(startNode instanceof GraphNode)) {
        startNode = this._nodesMap[generateNodeKey(startNode)];
      }

      if (!startNode) {
        return;
      }

      var edgeType = direction === 'out' ? 'outEdges' : direction === 'in' ? 'inEdges' : 'edges';

      for (var i = 0; i < this.nodes.length; i++) {
        this.nodes[i].__visited = false;
      }

      if (cb.call(context, startNode, null)) {
        return;
      }

      var queue = [startNode];

      while (queue.length) {
        var currentNode = queue.shift();
        var edges = currentNode[edgeType];

        for (var i = 0; i < edges.length; i++) {
          var e = edges[i];
          var otherNode = e.node1 === currentNode ? e.node2 : e.node1;

          if (!otherNode.__visited) {
            if (cb.call(context, otherNode, currentNode)) {
              return;
            }

            queue.push(otherNode);
            otherNode.__visited = true;
          }
        }
      }
    };

    Graph.prototype.update = function () {
      var data = this.data;
      var edgeData = this.edgeData;
      var nodes = this.nodes;
      var edges = this.edges;

      for (var i = 0, len = nodes.length; i < len; i++) {
        nodes[i].dataIndex = -1;
      }

      for (var i = 0, len = data.count(); i < len; i++) {
        nodes[data.getRawIndex(i)].dataIndex = i;
      }

      edgeData.filterSelf(function (idx) {
        var edge = edges[edgeData.getRawIndex(idx)];
        return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0;
      });

      for (var i = 0, len = edges.length; i < len; i++) {
        edges[i].dataIndex = -1;
      }

      for (var i = 0, len = edgeData.count(); i < len; i++) {
        edges[edgeData.getRawIndex(i)].dataIndex = i;
      }
    };

    Graph.prototype.clone = function () {
      var graph = new Graph(this._directed);
      var nodes = this.nodes;
      var edges = this.edges;

      for (var i = 0; i < nodes.length; i++) {
        graph.addNode(nodes[i].id, nodes[i].dataIndex);
      }

      for (var i = 0; i < edges.length; i++) {
        var e = edges[i];
        graph.addEdge(e.node1.id, e.node2.id, e.dataIndex);
      }

      return graph;
    };

    return Graph;
  }();

  var GraphNode = function () {
    function GraphNode(id, dataIndex) {
      this.inEdges = [];
      this.outEdges = [];
      this.edges = [];
      this.dataIndex = -1;
      this.id = id == null ? '' : id;
      this.dataIndex = dataIndex == null ? -1 : dataIndex;
    }

    GraphNode.prototype.degree = function () {
      return this.edges.length;
    };

    GraphNode.prototype.inDegree = function () {
      return this.inEdges.length;
    };

    GraphNode.prototype.outDegree = function () {
      return this.outEdges.length;
    };

    GraphNode.prototype.getModel = function (path) {
      if (this.dataIndex < 0) {
        return;
      }

      var graph = this.hostGraph;
      var itemModel = graph.data.getItemModel(this.dataIndex);
      return itemModel.getModel(path);
    };

    GraphNode.prototype.getAdjacentDataIndices = function () {
      var dataIndices = {
        edge: [],
        node: []
      };

      for (var i = 0; i < this.edges.length; i++) {
        var adjacentEdge = this.edges[i];

        if (adjacentEdge.dataIndex < 0) {
          continue;
        }

        dataIndices.edge.push(adjacentEdge.dataIndex);
        dataIndices.node.push(adjacentEdge.node1.dataIndex, adjacentEdge.node2.dataIndex);
      }

      return dataIndices;
    };

    return GraphNode;
  }();

  var GraphEdge = function () {
    function GraphEdge(n1, n2, dataIndex) {
      this.dataIndex = -1;
      this.node1 = n1;
      this.node2 = n2;
      this.dataIndex = dataIndex == null ? -1 : dataIndex;
    }

    GraphEdge.prototype.getModel = function (path) {
      if (this.dataIndex < 0) {
        return;
      }

      var graph = this.hostGraph;
      var itemModel = graph.edgeData.getItemModel(this.dataIndex);
      return itemModel.getModel(path);
    };

    GraphEdge.prototype.getAdjacentDataIndices = function () {
      return {
        edge: [this.dataIndex],
        node: [this.node1.dataIndex, this.node2.dataIndex]
      };
    };

    return GraphEdge;
  }();

  function createGraphDataProxyMixin(hostName, dataName) {
    return {
      getValue: function (dimension) {
        var data = this[hostName][dataName];
        return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
      },
      setVisual: function (key, value) {
        this.dataIndex >= 0 && this[hostName][dataName].setItemVisual(this.dataIndex, key, value);
      },
      getVisual: function (key) {
        return this[hostName][dataName].getItemVisual(this.dataIndex, key);
      },
      setLayout: function (layout, merge) {
        this.dataIndex >= 0 && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge);
      },
      getLayout: function () {
        return this[hostName][dataName].getItemLayout(this.dataIndex);
      },
      getGraphicEl: function () {
        return this[hostName][dataName].getItemGraphicEl(this.dataIndex);
      },
      getRawIndex: function () {
        return this[hostName][dataName].getRawIndex(this.dataIndex);
      }
    };
  }

  mixin(GraphNode, createGraphDataProxyMixin('hostGraph', 'data'));
  mixin(GraphEdge, createGraphDataProxyMixin('hostGraph', 'edgeData'));

  function createGraphFromNodeEdge(nodes, edges, seriesModel, directed, beforeLink) {
    var graph = new Graph(directed);

    for (var i = 0; i < nodes.length; i++) {
      graph.addNode(retrieve(nodes[i].id, nodes[i].name, i), i);
    }

    var linkNameList = [];
    var validEdges = [];
    var linkCount = 0;

    for (var i = 0; i < edges.length; i++) {
      var link = edges[i];
      var source = link.source;
      var target = link.target;

      if (graph.addEdge(source, target, linkCount)) {
        validEdges.push(link);
        linkNameList.push(retrieve(convertOptionIdName(link.id, null), source + ' > ' + target));
        linkCount++;
      }
    }

    var coordSys = seriesModel.get('coordinateSystem');
    var nodeData;

    if (coordSys === 'cartesian2d' || coordSys === 'polar') {
      nodeData = createListFromArray(nodes, seriesModel);
    } else {
      var coordSysCtor = CoordinateSystemManager.get(coordSys);
      var coordDimensions = coordSysCtor ? coordSysCtor.dimensions || [] : [];

      if (indexOf(coordDimensions, 'value') < 0) {
        coordDimensions.concat(['value']);
      }

      var dimensionNames = createDimensions(nodes, {
        coordDimensions: coordDimensions
      });
      nodeData = new List(dimensionNames, seriesModel);
      nodeData.initData(nodes);
    }

    var edgeData = new List(['value'], seriesModel);
    edgeData.initData(validEdges, linkNameList);
    beforeLink && beforeLink(nodeData, edgeData);
    linkList({
      mainData: nodeData,
      struct: graph,
      structAttr: 'graph',
      datas: {
        node: nodeData,
        edge: edgeData
      },
      datasAttr: {
        node: 'data',
        edge: 'edgeData'
      }
    });
    graph.update();
    return graph;
  }

  var KEY_DELIMITER = '-->';

  var getAutoCurvenessParams = function (seriesModel) {
    return seriesModel.get('autoCurveness') || null;
  };

  var createCurveness = function (seriesModel, appendLength) {
    var autoCurvenessParmas = getAutoCurvenessParams(seriesModel);
    var length = 20;
    var curvenessList = [];

    if (typeof autoCurvenessParmas === 'number') {
      length = autoCurvenessParmas;
    } else if (isArray(autoCurvenessParmas)) {
      seriesModel.__curvenessList = autoCurvenessParmas;
      return;
    }

    if (appendLength > length) {
      length = appendLength;
    }

    var len = length % 2 ? length + 2 : length + 3;
    curvenessList = [];

    for (var i = 0; i < len; i++) {
      curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1));
    }

    seriesModel.__curvenessList = curvenessList;
  };

  var getKeyOfEdges = function (n1, n2, seriesModel) {
    var source = [n1.id, n1.dataIndex].join('.');
    var target = [n2.id, n2.dataIndex].join('.');
    return [seriesModel.uid, source, target].join(KEY_DELIMITER);
  };

  var getOppositeKey = function (key) {
    var keys = key.split(KEY_DELIMITER);
    return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER);
  };

  var getEdgeFromMap = function (edge, seriesModel) {
    var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
    return seriesModel.__edgeMap[key];
  };

  var getTotalLengthBetweenNodes = function (edge, seriesModel) {
    var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel);
    var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel);
    return len + lenV;
  };

  var getEdgeMapLengthWithKey = function (key, seriesModel) {
    var edgeMap = seriesModel.__edgeMap;
    return edgeMap[key] ? edgeMap[key].length : 0;
  };

  function initCurvenessList(seriesModel) {
    if (!getAutoCurvenessParams(seriesModel)) {
      return;
    }

    seriesModel.__curvenessList = [];
    seriesModel.__edgeMap = {};
    createCurveness(seriesModel);
  }

  function createEdgeMapForCurveness(n1, n2, seriesModel, index) {
    if (!getAutoCurvenessParams(seriesModel)) {
      return;
    }

    var key = getKeyOfEdges(n1, n2, seriesModel);
    var edgeMap = seriesModel.__edgeMap;
    var oppositeEdges = edgeMap[getOppositeKey(key)];

    if (edgeMap[key] && !oppositeEdges) {
      edgeMap[key].isForward = true;
    } else if (oppositeEdges && edgeMap[key]) {
      oppositeEdges.isForward = true;
      edgeMap[key].isForward = false;
    }

    edgeMap[key] = edgeMap[key] || [];
    edgeMap[key].push(index);
  }

  function getCurvenessForEdge(edge, seriesModel, index, needReverse) {
    var autoCurvenessParams = getAutoCurvenessParams(seriesModel);
    var isArrayParam = isArray(autoCurvenessParams);

    if (!autoCurvenessParams) {
      return null;
    }

    var edgeArray = getEdgeFromMap(edge, seriesModel);

    if (!edgeArray) {
      return null;
    }

    var edgeIndex = -1;

    for (var i = 0; i < edgeArray.length; i++) {
      if (edgeArray[i] === index) {
        edgeIndex = i;
        break;
      }
    }

    var totalLen = getTotalLengthBetweenNodes(edge, seriesModel);
    createCurveness(seriesModel, totalLen);
    edge.lineStyle = edge.lineStyle || {};
    var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel);
    var curvenessList = seriesModel.__curvenessList;
    var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1;

    if (!edgeArray.isForward) {
      var oppositeKey = getOppositeKey(curKey);
      var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel);
      var resValue = curvenessList[edgeIndex + len + parityCorrection];

      if (needReverse) {
        if (isArrayParam) {
          if (autoCurvenessParams && autoCurvenessParams[0] === 0) {
            return (len + parityCorrection) % 2 ? resValue : -resValue;
          } else {
            return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue;
          }
        } else {
          return (len + parityCorrection) % 2 ? resValue : -resValue;
        }
      } else {
        return curvenessList[edgeIndex + len + parityCorrection];
      }
    } else {
      return curvenessList[parityCorrection + edgeIndex];
    }
  }

  var GraphSeriesModel = function (_super) {
    __extends(GraphSeriesModel, _super);

    function GraphSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GraphSeriesModel.type;
      _this.hasSymbolVisual = true;
      return _this;
    }

    GraphSeriesModel.prototype.init = function (option) {
      _super.prototype.init.apply(this, arguments);

      var self = this;

      function getCategoriesData() {
        return self._categoriesData;
      }

      this.legendVisualProvider = new LegendVisualProvider(getCategoriesData, getCategoriesData);
      this.fillDataTextStyle(option.edges || option.links);

      this._updateCategoriesData();
    };

    GraphSeriesModel.prototype.mergeOption = function (option) {
      _super.prototype.mergeOption.apply(this, arguments);

      this.fillDataTextStyle(option.edges || option.links);

      this._updateCategoriesData();
    };

    GraphSeriesModel.prototype.mergeDefaultAndTheme = function (option) {
      _super.prototype.mergeDefaultAndTheme.apply(this, arguments);

      defaultEmphasis(option, 'edgeLabel', ['show']);
    };

    GraphSeriesModel.prototype.getInitialData = function (option, ecModel) {
      var edges = option.edges || option.links || [];
      var nodes = option.data || option.nodes || [];
      var self = this;

      if (nodes && edges) {
        initCurvenessList(this);
        var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink);
        each(graph.edges, function (edge) {
          createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex);
        }, this);
        return graph.data;
      }

      function beforeLink(nodeData, edgeData) {
        nodeData.wrapMethod('getItemModel', function (model) {
          var categoriesModels = self._categoriesModels;
          var categoryIdx = model.getShallow('category');
          var categoryModel = categoriesModels[categoryIdx];

          if (categoryModel) {
            categoryModel.parentModel = model.parentModel;
            model.parentModel = categoryModel;
          }

          return model;
        });
        var oldGetModel = Model.prototype.getModel;

        function newGetModel(path, parentModel) {
          var model = oldGetModel.call(this, path, parentModel);
          model.resolveParentPath = resolveParentPath;
          return model;
        }

        edgeData.wrapMethod('getItemModel', function (model) {
          model.resolveParentPath = resolveParentPath;
          model.getModel = newGetModel;
          return model;
        });

        function resolveParentPath(pathArr) {
          if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) {
            var newPathArr = pathArr.slice();

            if (pathArr[0] === 'label') {
              newPathArr[0] = 'edgeLabel';
            } else if (pathArr[1] === 'label') {
              newPathArr[1] = 'edgeLabel';
            }

            return newPathArr;
          }

          return pathArr;
        }
      }
    };

    GraphSeriesModel.prototype.getGraph = function () {
      return this.getData().graph;
    };

    GraphSeriesModel.prototype.getEdgeData = function () {
      return this.getGraph().edgeData;
    };

    GraphSeriesModel.prototype.getCategoriesData = function () {
      return this._categoriesData;
    };

    GraphSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      if (dataType === 'edge') {
        var nodeData = this.getData();
        var params = this.getDataParams(dataIndex, dataType);
        var edge = nodeData.graph.getEdgeByIndex(dataIndex);
        var sourceName = nodeData.getName(edge.node1.dataIndex);
        var targetName = nodeData.getName(edge.node2.dataIndex);
        var nameArr = [];
        sourceName != null && nameArr.push(sourceName);
        targetName != null && nameArr.push(targetName);
        return createTooltipMarkup('nameValue', {
          name: nameArr.join(' > '),
          value: params.value,
          noValue: params.value == null
        });
      }

      var nodeMarkup = defaultSeriesFormatTooltip({
        series: this,
        dataIndex: dataIndex,
        multipleSeries: multipleSeries
      });
      return nodeMarkup;
    };

    GraphSeriesModel.prototype._updateCategoriesData = function () {
      var categories = map(this.option.categories || [], function (category) {
        return category.value != null ? category : extend({
          value: 0
        }, category);
      });
      var categoriesData = new List(['value'], this);
      categoriesData.initData(categories);
      this._categoriesData = categoriesData;
      this._categoriesModels = categoriesData.mapArray(function (idx) {
        return categoriesData.getItemModel(idx);
      });
    };

    GraphSeriesModel.prototype.setZoom = function (zoom) {
      this.option.zoom = zoom;
    };

    GraphSeriesModel.prototype.setCenter = function (center) {
      this.option.center = center;
    };

    GraphSeriesModel.prototype.isAnimationEnabled = function () {
      return _super.prototype.isAnimationEnabled.call(this) && !(this.get('layout') === 'force' && this.get(['force', 'layoutAnimation']));
    };

    GraphSeriesModel.type = 'series.graph';
    GraphSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'view',
      legendHoverLink: true,
      layout: null,
      focusNodeAdjacency: false,
      circular: {
        rotateLabel: false
      },
      force: {
        initLayout: null,
        repulsion: [0, 50],
        gravity: 0.1,
        friction: 0.6,
        edgeLength: 30,
        layoutAnimation: true
      },
      left: 'center',
      top: 'center',
      symbol: 'circle',
      symbolSize: 10,
      edgeSymbol: ['none', 'none'],
      edgeSymbolSize: 10,
      edgeLabel: {
        position: 'middle',
        distance: 5
      },
      draggable: false,
      roam: false,
      center: null,
      zoom: 1,
      nodeScaleRatio: 0.6,
      label: {
        show: false,
        formatter: '{b}'
      },
      itemStyle: {},
      lineStyle: {
        color: '#aaa',
        width: 1,
        opacity: 0.5
      },
      emphasis: {
        scale: true,
        label: {
          show: true
        }
      },
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      }
    };
    return GraphSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(GraphSeriesModel);
  var straightLineProto = Line.prototype;
  var bezierCurveProto = BezierCurve.prototype;

  var StraightLineShape = function () {
    function StraightLineShape() {
      this.x1 = 0;
      this.y1 = 0;
      this.x2 = 0;
      this.y2 = 0;
      this.percent = 1;
    }

    return StraightLineShape;
  }();

  var CurveShape = function (_super) {
    __extends(CurveShape, _super);

    function CurveShape() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    return CurveShape;
  }(StraightLineShape);

  function isStraightLine(shape) {
    return isNaN(+shape.cpx1) || isNaN(+shape.cpy1);
  }

  var ECLinePath = function (_super) {
    __extends(ECLinePath, _super);

    function ECLinePath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'ec-line';
      return _this;
    }

    ECLinePath.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    ECLinePath.prototype.getDefaultShape = function () {
      return new StraightLineShape();
    };

    ECLinePath.prototype.buildPath = function (ctx, shape) {
      if (isStraightLine(shape)) {
        straightLineProto.buildPath.call(this, ctx, shape);
      } else {
        bezierCurveProto.buildPath.call(this, ctx, shape);
      }
    };

    ECLinePath.prototype.pointAt = function (t) {
      if (isStraightLine(this.shape)) {
        return straightLineProto.pointAt.call(this, t);
      } else {
        return bezierCurveProto.pointAt.call(this, t);
      }
    };

    ECLinePath.prototype.tangentAt = function (t) {
      var shape = this.shape;
      var p = isStraightLine(shape) ? [shape.x2 - shape.x1, shape.y2 - shape.y1] : bezierCurveProto.tangentAt.call(this, t);
      return normalize(p, p);
    };

    return ECLinePath;
  }(Path);

  var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol'];

  function makeSymbolTypeKey(symbolCategory) {
    return '_' + symbolCategory + 'Type';
  }

  function createSymbol$1(name, lineData, idx) {
    var symbolType = lineData.getItemVisual(idx, name);

    if (!symbolType || symbolType === 'none') {
      return;
    }

    var symbolSize = lineData.getItemVisual(idx, name + 'Size');
    var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate');
    var symbolSizeArr = isArray(symbolSize) ? symbolSize : [symbolSize, symbolSize];
    var symbolPath = createSymbol(symbolType, -symbolSizeArr[0] / 2, -symbolSizeArr[1] / 2, symbolSizeArr[0], symbolSizeArr[1]);
    symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) ? void 0 : +symbolRotate * Math.PI / 180 || 0;
    symbolPath.name = name;
    return symbolPath;
  }

  function createLine(points) {
    var line = new ECLinePath({
      name: 'line',
      subPixelOptimize: true
    });
    setLinePoints(line.shape, points);
    return line;
  }

  function setLinePoints(targetShape, points) {
    targetShape.x1 = points[0][0];
    targetShape.y1 = points[0][1];
    targetShape.x2 = points[1][0];
    targetShape.y2 = points[1][1];
    targetShape.percent = 1;
    var cp1 = points[2];

    if (cp1) {
      targetShape.cpx1 = cp1[0];
      targetShape.cpy1 = cp1[1];
    } else {
      targetShape.cpx1 = NaN;
      targetShape.cpy1 = NaN;
    }
  }

  var Line$1 = function (_super) {
    __extends(Line, _super);

    function Line(lineData, idx, seriesScope) {
      var _this = _super.call(this) || this;

      _this._createLine(lineData, idx, seriesScope);

      return _this;
    }

    Line.prototype._createLine = function (lineData, idx, seriesScope) {
      var seriesModel = lineData.hostModel;
      var linePoints = lineData.getItemLayout(idx);
      var line = createLine(linePoints);
      line.shape.percent = 0;
      initProps(line, {
        shape: {
          percent: 1
        }
      }, seriesModel, idx);
      this.add(line);
      each(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbol = createSymbol$1(symbolCategory, lineData, idx);
        this.add(symbol);
        this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory);
      }, this);

      this._updateCommonStl(lineData, idx, seriesScope);
    };

    Line.prototype.updateData = function (lineData, idx, seriesScope) {
      var seriesModel = lineData.hostModel;
      var line = this.childOfName('line');
      var linePoints = lineData.getItemLayout(idx);
      var target = {
        shape: {}
      };
      setLinePoints(target.shape, linePoints);
      updateProps(line, target, seriesModel, idx);
      each(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbolType = lineData.getItemVisual(idx, symbolCategory);
        var key = makeSymbolTypeKey(symbolCategory);

        if (this[key] !== symbolType) {
          this.remove(this.childOfName(symbolCategory));
          var symbol = createSymbol$1(symbolCategory, lineData, idx);
          this.add(symbol);
        }

        this[key] = symbolType;
      }, this);

      this._updateCommonStl(lineData, idx, seriesScope);
    };

    Line.prototype.getLinePath = function () {
      return this.childAt(0);
    };

    Line.prototype._updateCommonStl = function (lineData, idx, seriesScope) {
      var seriesModel = lineData.hostModel;
      var line = this.childOfName('line');
      var emphasisLineStyle = seriesScope && seriesScope.emphasisLineStyle;
      var blurLineStyle = seriesScope && seriesScope.blurLineStyle;
      var selectLineStyle = seriesScope && seriesScope.selectLineStyle;
      var labelStatesModels = seriesScope && seriesScope.labelStatesModels;

      if (!seriesScope || lineData.hasItemOption) {
        var itemModel = lineData.getItemModel(idx);
        emphasisLineStyle = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle();
        blurLineStyle = itemModel.getModel(['blur', 'lineStyle']).getLineStyle();
        selectLineStyle = itemModel.getModel(['select', 'lineStyle']).getLineStyle();
        labelStatesModels = getLabelStatesModels(itemModel);
      }

      var lineStyle = lineData.getItemVisual(idx, 'style');
      var visualColor = lineStyle.stroke;
      line.useStyle(lineStyle);
      line.style.fill = null;
      line.style.strokeNoScale = true;
      line.ensureState('emphasis').style = emphasisLineStyle;
      line.ensureState('blur').style = blurLineStyle;
      line.ensureState('select').style = selectLineStyle;
      each(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbol = this.childOfName(symbolCategory);

        if (symbol) {
          symbol.setColor(visualColor);
          symbol.style.opacity = lineStyle.opacity;

          for (var i = 0; i < SPECIAL_STATES.length; i++) {
            var stateName = SPECIAL_STATES[i];
            var lineState = line.getState(stateName);

            if (lineState) {
              var lineStateStyle = lineState.style || {};
              var state = symbol.ensureState(stateName);
              var stateStyle = state.style || (state.style = {});

              if (lineStateStyle.stroke != null) {
                stateStyle[symbol.__isEmptyBrush ? 'stroke' : 'fill'] = lineStateStyle.stroke;
              }

              if (lineStateStyle.opacity != null) {
                stateStyle.opacity = lineStateStyle.opacity;
              }
            }
          }

          symbol.markRedraw();
        }
      }, this);
      var rawVal = seriesModel.getRawValue(idx);
      setLabelStyle(this, labelStatesModels, {
        labelDataIndex: idx,
        labelFetcher: {
          getFormattedLabel: function (dataIndex, stateName) {
            return seriesModel.getFormattedLabel(dataIndex, stateName, lineData.dataType);
          }
        },
        inheritColor: visualColor || '#000',
        defaultOpacity: lineStyle.opacity,
        defaultText: (rawVal == null ? lineData.getName(idx) : isFinite(rawVal) ? round$1(rawVal) : rawVal) + ''
      });
      var label = this.getTextContent();

      if (label) {
        var labelNormalModel = labelStatesModels.normal;
        label.__align = label.style.align;
        label.__verticalAlign = label.style.verticalAlign;
        label.__position = labelNormalModel.get('position') || 'middle';
        var distance = labelNormalModel.get('distance');

        if (!isArray(distance)) {
          distance = [distance, distance];
        }

        label.__labelDistance = distance;
      }

      this.setTextConfig({
        position: null,
        local: true,
        inside: false
      });
      enableHoverEmphasis(this);
    };

    Line.prototype.highlight = function () {
      enterEmphasis(this);
    };

    Line.prototype.downplay = function () {
      leaveEmphasis(this);
    };

    Line.prototype.updateLayout = function (lineData, idx) {
      this.setLinePoints(lineData.getItemLayout(idx));
    };

    Line.prototype.setLinePoints = function (points) {
      var linePath = this.childOfName('line');
      setLinePoints(linePath.shape, points);
      linePath.dirty();
    };

    Line.prototype.beforeUpdate = function () {
      var lineGroup = this;
      var symbolFrom = lineGroup.childOfName('fromSymbol');
      var symbolTo = lineGroup.childOfName('toSymbol');
      var label = lineGroup.getTextContent();

      if (!symbolFrom && !symbolTo && (!label || label.ignore)) {
        return;
      }

      var invScale = 1;
      var parentNode = this.parent;

      while (parentNode) {
        if (parentNode.scaleX) {
          invScale /= parentNode.scaleX;
        }

        parentNode = parentNode.parent;
      }

      var line = lineGroup.childOfName('line');

      if (!this.__dirty && !line.__dirty) {
        return;
      }

      var percent = line.shape.percent;
      var fromPos = line.pointAt(0);
      var toPos = line.pointAt(percent);
      var d = sub([], toPos, fromPos);
      normalize(d, d);

      function setSymbolRotation(symbol, percent) {
        var specifiedRotation = symbol.__specifiedRotation;

        if (specifiedRotation == null) {
          var tangent = line.tangentAt(percent);
          symbol.attr('rotation', (percent === 1 ? -1 : 1) * Math.PI / 2 - Math.atan2(tangent[1], tangent[0]));
        } else {
          symbol.attr('rotation', specifiedRotation);
        }
      }

      if (symbolFrom) {
        symbolFrom.setPosition(fromPos);
        setSymbolRotation(symbolFrom, 0);
        symbolFrom.scaleX = symbolFrom.scaleY = invScale * percent;
        symbolFrom.markRedraw();
      }

      if (symbolTo) {
        symbolTo.setPosition(toPos);
        setSymbolRotation(symbolTo, 1);
        symbolTo.scaleX = symbolTo.scaleY = invScale * percent;
        symbolTo.markRedraw();
      }

      if (label && !label.ignore) {
        label.x = label.y = 0;
        label.originX = label.originY = 0;
        var textAlign = void 0;
        var textVerticalAlign = void 0;
        var distance = label.__labelDistance;
        var distanceX = distance[0] * invScale;
        var distanceY = distance[1] * invScale;
        var halfPercent = percent / 2;
        var tangent = line.tangentAt(halfPercent);
        var n = [tangent[1], -tangent[0]];
        var cp = line.pointAt(halfPercent);

        if (n[1] > 0) {
          n[0] = -n[0];
          n[1] = -n[1];
        }

        var dir = tangent[0] < 0 ? -1 : 1;

        if (label.__position !== 'start' && label.__position !== 'end') {
          var rotation = -Math.atan2(tangent[1], tangent[0]);

          if (toPos[0] < fromPos[0]) {
            rotation = Math.PI + rotation;
          }

          label.rotation = rotation;
        }

        var dy = void 0;

        switch (label.__position) {
          case 'insideStartTop':
          case 'insideMiddleTop':
          case 'insideEndTop':
          case 'middle':
            dy = -distanceY;
            textVerticalAlign = 'bottom';
            break;

          case 'insideStartBottom':
          case 'insideMiddleBottom':
          case 'insideEndBottom':
            dy = distanceY;
            textVerticalAlign = 'top';
            break;

          default:
            dy = 0;
            textVerticalAlign = 'middle';
        }

        switch (label.__position) {
          case 'end':
            label.x = d[0] * distanceX + toPos[0];
            label.y = d[1] * distanceY + toPos[1];
            textAlign = d[0] > 0.8 ? 'left' : d[0] < -0.8 ? 'right' : 'center';
            textVerticalAlign = d[1] > 0.8 ? 'top' : d[1] < -0.8 ? 'bottom' : 'middle';
            break;

          case 'start':
            label.x = -d[0] * distanceX + fromPos[0];
            label.y = -d[1] * distanceY + fromPos[1];
            textAlign = d[0] > 0.8 ? 'right' : d[0] < -0.8 ? 'left' : 'center';
            textVerticalAlign = d[1] > 0.8 ? 'bottom' : d[1] < -0.8 ? 'top' : 'middle';
            break;

          case 'insideStartTop':
          case 'insideStart':
          case 'insideStartBottom':
            label.x = distanceX * dir + fromPos[0];
            label.y = fromPos[1] + dy;
            textAlign = tangent[0] < 0 ? 'right' : 'left';
            label.originX = -distanceX * dir;
            label.originY = -dy;
            break;

          case 'insideMiddleTop':
          case 'insideMiddle':
          case 'insideMiddleBottom':
          case 'middle':
            label.x = cp[0];
            label.y = cp[1] + dy;
            textAlign = 'center';
            label.originY = -dy;
            break;

          case 'insideEndTop':
          case 'insideEnd':
          case 'insideEndBottom':
            label.x = -distanceX * dir + toPos[0];
            label.y = toPos[1] + dy;
            textAlign = tangent[0] >= 0 ? 'right' : 'left';
            label.originX = distanceX * dir;
            label.originY = -dy;
            break;
        }

        label.scaleX = label.scaleY = invScale;
        label.setStyle({
          verticalAlign: label.__verticalAlign || textVerticalAlign,
          align: label.__align || textAlign
        });
      }
    };

    return Line;
  }(Group);

  var LineDraw = function () {
    function LineDraw(LineCtor) {
      this.group = new Group();
      this._LineCtor = LineCtor || Line$1;
    }

    LineDraw.prototype.isPersistent = function () {
      return true;
    };

    LineDraw.prototype.updateData = function (lineData) {
      var _this = this;

      var lineDraw = this;
      var group = lineDraw.group;
      var oldLineData = lineDraw._lineData;
      lineDraw._lineData = lineData;

      if (!oldLineData) {
        group.removeAll();
      }

      var seriesScope = makeSeriesScope$1(lineData);
      lineData.diff(oldLineData).add(function (idx) {
        _this._doAdd(lineData, idx, seriesScope);
      }).update(function (newIdx, oldIdx) {
        _this._doUpdate(oldLineData, lineData, oldIdx, newIdx, seriesScope);
      }).remove(function (idx) {
        group.remove(oldLineData.getItemGraphicEl(idx));
      }).execute();
    };

    LineDraw.prototype.updateLayout = function () {
      var lineData = this._lineData;

      if (!lineData) {
        return;
      }

      lineData.eachItemGraphicEl(function (el, idx) {
        el.updateLayout(lineData, idx);
      }, this);
    };

    LineDraw.prototype.incrementalPrepareUpdate = function (lineData) {
      this._seriesScope = makeSeriesScope$1(lineData);
      this._lineData = null;
      this.group.removeAll();
    };

    LineDraw.prototype.incrementalUpdate = function (taskParams, lineData) {
      function updateIncrementalAndHover(el) {
        if (!el.isGroup && !isEffectObject(el)) {
          el.incremental = true;
          el.ensureState('emphasis').hoverLayer = true;
        }
      }

      for (var idx = taskParams.start; idx < taskParams.end; idx++) {
        var itemLayout = lineData.getItemLayout(idx);

        if (lineNeedsDraw(itemLayout)) {
          var el = new this._LineCtor(lineData, idx, this._seriesScope);
          el.traverse(updateIncrementalAndHover);
          this.group.add(el);
          lineData.setItemGraphicEl(idx, el);
        }
      }
    };

    LineDraw.prototype.remove = function () {
      this.group.removeAll();
    };

    LineDraw.prototype._doAdd = function (lineData, idx, seriesScope) {
      var itemLayout = lineData.getItemLayout(idx);

      if (!lineNeedsDraw(itemLayout)) {
        return;
      }

      var el = new this._LineCtor(lineData, idx, seriesScope);
      lineData.setItemGraphicEl(idx, el);
      this.group.add(el);
    };

    LineDraw.prototype._doUpdate = function (oldLineData, newLineData, oldIdx, newIdx, seriesScope) {
      var itemEl = oldLineData.getItemGraphicEl(oldIdx);

      if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) {
        this.group.remove(itemEl);
        return;
      }

      if (!itemEl) {
        itemEl = new this._LineCtor(newLineData, newIdx, seriesScope);
      } else {
        itemEl.updateData(newLineData, newIdx, seriesScope);
      }

      newLineData.setItemGraphicEl(newIdx, itemEl);
      this.group.add(itemEl);
    };

    return LineDraw;
  }();

  function isEffectObject(el) {
    return el.animators && el.animators.length > 0;
  }

  function makeSeriesScope$1(lineData) {
    var hostModel = lineData.hostModel;
    return {
      lineStyle: hostModel.getModel('lineStyle').getLineStyle(),
      emphasisLineStyle: hostModel.getModel(['emphasis', 'lineStyle']).getLineStyle(),
      blurLineStyle: hostModel.getModel(['blur', 'lineStyle']).getLineStyle(),
      selectLineStyle: hostModel.getModel(['select', 'lineStyle']).getLineStyle(),
      labelStatesModels: getLabelStatesModels(hostModel)
    };
  }

  function isPointNaN(pt) {
    return isNaN(pt[0]) || isNaN(pt[1]);
  }

  function lineNeedsDraw(pts) {
    return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
  }

  function getNodeGlobalScale(seriesModel) {
    var coordSys = seriesModel.coordinateSystem;

    if (coordSys.type !== 'view') {
      return 1;
    }

    var nodeScaleRatio = seriesModel.option.nodeScaleRatio;
    var groupZoom = coordSys.scaleX;
    var roamZoom = coordSys.getZoom();
    var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
    return nodeScale / groupZoom;
  }

  function getSymbolSize(node) {
    var symbolSize = node.getVisual('symbolSize');

    if (symbolSize instanceof Array) {
      symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
    }

    return +symbolSize;
  }

  var v1 = [];
  var v2 = [];
  var v3 = [];
  var quadraticAt$1 = quadraticAt;
  var v2DistSquare = distSquare;
  var mathAbs$2 = Math.abs;

  function intersectCurveCircle(curvePoints, center, radius) {
    var p0 = curvePoints[0];
    var p1 = curvePoints[1];
    var p2 = curvePoints[2];
    var d = Infinity;
    var t;
    var radiusSquare = radius * radius;
    var interval = 0.1;

    for (var _t = 0.1; _t <= 0.9; _t += 0.1) {
      v1[0] = quadraticAt$1(p0[0], p1[0], p2[0], _t);
      v1[1] = quadraticAt$1(p0[1], p1[1], p2[1], _t);
      var diff = mathAbs$2(v2DistSquare(v1, center) - radiusSquare);

      if (diff < d) {
        d = diff;
        t = _t;
      }
    }

    for (var i = 0; i < 32; i++) {
      var next = t + interval;
      v2[0] = quadraticAt$1(p0[0], p1[0], p2[0], t);
      v2[1] = quadraticAt$1(p0[1], p1[1], p2[1], t);
      v3[0] = quadraticAt$1(p0[0], p1[0], p2[0], next);
      v3[1] = quadraticAt$1(p0[1], p1[1], p2[1], next);
      var diff = v2DistSquare(v2, center) - radiusSquare;

      if (mathAbs$2(diff) < 1e-2) {
        break;
      }

      var nextDiff = v2DistSquare(v3, center) - radiusSquare;
      interval /= 2;

      if (diff < 0) {
        if (nextDiff >= 0) {
          t = t + interval;
        } else {
          t = t - interval;
        }
      } else {
        if (nextDiff >= 0) {
          t = t - interval;
        } else {
          t = t + interval;
        }
      }
    }

    return t;
  }

  function adjustEdge(graph, scale) {
    var tmp0 = [];
    var quadraticSubdivide$1 = quadraticSubdivide;
    var pts = [[], [], []];
    var pts2 = [[], []];
    var v = [];
    scale /= 2;
    graph.eachEdge(function (edge, idx) {
      var linePoints = edge.getLayout();
      var fromSymbol = edge.getVisual('fromSymbol');
      var toSymbol = edge.getVisual('toSymbol');

      if (!linePoints.__original) {
        linePoints.__original = [clone$1(linePoints[0]), clone$1(linePoints[1])];

        if (linePoints[2]) {
          linePoints.__original.push(clone$1(linePoints[2]));
        }
      }

      var originalPoints = linePoints.__original;

      if (linePoints[2] != null) {
        copy(pts[0], originalPoints[0]);
        copy(pts[1], originalPoints[2]);
        copy(pts[2], originalPoints[1]);

        if (fromSymbol && fromSymbol !== 'none') {
          var symbolSize = getSymbolSize(edge.node1);
          var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale);
          quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
          pts[0][0] = tmp0[3];
          pts[1][0] = tmp0[4];
          quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
          pts[0][1] = tmp0[3];
          pts[1][1] = tmp0[4];
        }

        if (toSymbol && toSymbol !== 'none') {
          var symbolSize = getSymbolSize(edge.node2);
          var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale);
          quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
          pts[1][0] = tmp0[1];
          pts[2][0] = tmp0[2];
          quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
          pts[1][1] = tmp0[1];
          pts[2][1] = tmp0[2];
        }

        copy(linePoints[0], pts[0]);
        copy(linePoints[1], pts[2]);
        copy(linePoints[2], pts[1]);
      } else {
        copy(pts2[0], originalPoints[0]);
        copy(pts2[1], originalPoints[1]);
        sub(v, pts2[1], pts2[0]);
        normalize(v, v);

        if (fromSymbol && fromSymbol !== 'none') {
          var symbolSize = getSymbolSize(edge.node1);
          scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale);
        }

        if (toSymbol && toSymbol !== 'none') {
          var symbolSize = getSymbolSize(edge.node2);
          scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale);
        }

        copy(linePoints[0], pts2[0]);
        copy(linePoints[1], pts2[1]);
      }
    });
  }

  function isViewCoordSys(coordSys) {
    return coordSys.type === 'view';
  }

  var GraphView = function (_super) {
    __extends(GraphView, _super);

    function GraphView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GraphView.type;
      return _this;
    }

    GraphView.prototype.init = function (ecModel, api) {
      var symbolDraw = new SymbolDraw();
      var lineDraw = new LineDraw();
      var group = this.group;
      this._controller = new RoamController(api.getZr());
      this._controllerHost = {
        target: group
      };
      group.add(symbolDraw.group);
      group.add(lineDraw.group);
      this._symbolDraw = symbolDraw;
      this._lineDraw = lineDraw;
      this._firstRender = true;
    };

    GraphView.prototype.render = function (seriesModel, ecModel, api) {
      var _this = this;

      var coordSys = seriesModel.coordinateSystem;
      this._model = seriesModel;
      var symbolDraw = this._symbolDraw;
      var lineDraw = this._lineDraw;
      var group = this.group;

      if (isViewCoordSys(coordSys)) {
        var groupNewProp = {
          x: coordSys.x,
          y: coordSys.y,
          scaleX: coordSys.scaleX,
          scaleY: coordSys.scaleY
        };

        if (this._firstRender) {
          group.attr(groupNewProp);
        } else {
          updateProps(group, groupNewProp, seriesModel);
        }
      }

      adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));
      var data = seriesModel.getData();
      symbolDraw.updateData(data);
      var edgeData = seriesModel.getEdgeData();
      lineDraw.updateData(edgeData);

      this._updateNodeAndLinkScale();

      this._updateController(seriesModel, ecModel, api);

      clearTimeout(this._layoutTimeout);
      var forceLayout = seriesModel.forceLayout;
      var layoutAnimation = seriesModel.get(['force', 'layoutAnimation']);

      if (forceLayout) {
        this._startForceLayoutIteration(forceLayout, layoutAnimation);
      }

      data.graph.eachNode(function (node) {
        var idx = node.dataIndex;
        var el = node.getGraphicEl();
        var itemModel = node.getModel();
        el.off('drag').off('dragend');
        var draggable = itemModel.get('draggable');

        if (draggable) {
          el.on('drag', function () {
            if (forceLayout) {
              forceLayout.warmUp();
              !_this._layouting && _this._startForceLayoutIteration(forceLayout, layoutAnimation);
              forceLayout.setFixed(idx);
              data.setItemLayout(idx, [el.x, el.y]);
            }
          }).on('dragend', function () {
            if (forceLayout) {
              forceLayout.setUnfixed(idx);
            }
          });
        }

        el.setDraggable(draggable && !!forceLayout);
        var focus = itemModel.get(['emphasis', 'focus']);

        if (focus === 'adjacency') {
          getECData(el).focus = node.getAdjacentDataIndices();
        }
      });
      data.graph.eachEdge(function (edge) {
        var el = edge.getGraphicEl();
        var focus = edge.getModel().get(['emphasis', 'focus']);

        if (focus === 'adjacency') {
          getECData(el).focus = {
            edge: [edge.dataIndex],
            node: [edge.node1.dataIndex, edge.node2.dataIndex]
          };
        }
      });
      var circularRotateLabel = seriesModel.get('layout') === 'circular' && seriesModel.get(['circular', 'rotateLabel']);
      var cx = data.getLayout('cx');
      var cy = data.getLayout('cy');
      data.eachItemGraphicEl(function (el, idx) {
        var itemModel = data.getItemModel(idx);
        var labelRotate = itemModel.get(['label', 'rotate']) || 0;
        var symbolPath = el.getSymbolPath();

        if (circularRotateLabel) {
          var pos = data.getItemLayout(idx);
          var rad = Math.atan2(pos[1] - cy, pos[0] - cx);

          if (rad < 0) {
            rad = Math.PI * 2 + rad;
          }

          var isLeft = pos[0] < cx;

          if (isLeft) {
            rad = rad - Math.PI;
          }

          var textPosition = isLeft ? 'left' : 'right';
          symbolPath.setTextConfig({
            rotation: -rad,
            position: textPosition,
            origin: 'center'
          });
          var emphasisState = symbolPath.ensureState('emphasis');
          extend(emphasisState.textConfig || (emphasisState.textConfig = {}), {
            position: textPosition
          });
        } else {
          symbolPath.setTextConfig({
            rotation: labelRotate *= Math.PI / 180
          });
        }
      });
      this._firstRender = false;
    };

    GraphView.prototype.dispose = function () {
      this._controller && this._controller.dispose();
      this._controllerHost = null;
    };

    GraphView.prototype._startForceLayoutIteration = function (forceLayout, layoutAnimation) {
      var self = this;

      (function step() {
        forceLayout.step(function (stopped) {
          self.updateLayout(self._model);
          (self._layouting = !stopped) && (layoutAnimation ? self._layoutTimeout = setTimeout(step, 16) : step());
        });
      })();
    };

    GraphView.prototype._updateController = function (seriesModel, ecModel, api) {
      var _this = this;

      var controller = this._controller;
      var controllerHost = this._controllerHost;
      var group = this.group;
      controller.setPointerChecker(function (e, x, y) {
        var rect = group.getBoundingRect();
        rect.applyTransform(group.transform);
        return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel);
      });

      if (!isViewCoordSys(seriesModel.coordinateSystem)) {
        controller.disable();
        return;
      }

      controller.enable(seriesModel.get('roam'));
      controllerHost.zoomLimit = seriesModel.get('scaleLimit');
      controllerHost.zoom = seriesModel.coordinateSystem.getZoom();
      controller.off('pan').off('zoom').on('pan', function (e) {
        updateViewOnPan(controllerHost, e.dx, e.dy);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: 'graphRoam',
          dx: e.dx,
          dy: e.dy
        });
      }).on('zoom', function (e) {
        updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: 'graphRoam',
          zoom: e.scale,
          originX: e.originX,
          originY: e.originY
        });

        _this._updateNodeAndLinkScale();

        adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));

        _this._lineDraw.updateLayout();

        api.updateLabelLayout();
      });
    };

    GraphView.prototype._updateNodeAndLinkScale = function () {
      var seriesModel = this._model;
      var data = seriesModel.getData();
      var nodeScale = getNodeGlobalScale(seriesModel);
      data.eachItemGraphicEl(function (el, idx) {
        el.setSymbolScale(nodeScale);
      });
    };

    GraphView.prototype.updateLayout = function (seriesModel) {
      adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));

      this._symbolDraw.updateLayout();

      this._lineDraw.updateLayout();
    };

    GraphView.prototype.remove = function (ecModel, api) {
      this._symbolDraw && this._symbolDraw.remove();
      this._lineDraw && this._lineDraw.remove();
    };

    GraphView.type = 'graph';
    return GraphView;
  }(ChartView);

  ChartView.registerClass(GraphView);
  registerAction({
    type: 'focusNodeAdjacency',
    event: 'focusNodeAdjacency',
    update: 'series:focusNodeAdjacency'
  }, function () {});
  registerAction({
    type: 'unfocusNodeAdjacency',
    event: 'unfocusNodeAdjacency',
    update: 'series:unfocusNodeAdjacency'
  }, function () {});
  var actionInfo = {
    type: 'graphRoam',
    event: 'graphRoam',
    update: 'none'
  };
  registerAction(actionInfo, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      query: payload
    }, function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var res = updateCenterAndZoom(coordSys, payload);
      seriesModel.setCenter && seriesModel.setCenter(res.center);
      seriesModel.setZoom && seriesModel.setZoom(res.zoom);
    });
  });

  function categoryFilter(ecModel) {
    var legendModels = ecModel.findComponents({
      mainType: 'legend'
    });

    if (!legendModels || !legendModels.length) {
      return;
    }

    ecModel.eachSeriesByType('graph', function (graphSeries) {
      var categoriesData = graphSeries.getCategoriesData();
      var graph = graphSeries.getGraph();
      var data = graph.data;
      var categoryNames = categoriesData.mapArray(categoriesData.getName);
      data.filterSelf(function (idx) {
        var model = data.getItemModel(idx);
        var category = model.getShallow('category');

        if (category != null) {
          if (typeof category === 'number') {
            category = categoryNames[category];
          }

          for (var i = 0; i < legendModels.length; i++) {
            if (!legendModels[i].isSelected(category)) {
              return false;
            }
          }
        }

        return true;
      });
    });
  }

  function categoryVisual(ecModel) {
    var paletteScope = {};
    ecModel.eachSeriesByType('graph', function (seriesModel) {
      var categoriesData = seriesModel.getCategoriesData();
      var data = seriesModel.getData();
      var categoryNameIdxMap = {};
      categoriesData.each(function (idx) {
        var name = categoriesData.getName(idx);
        categoryNameIdxMap['ec-' + name] = idx;
        var itemModel = categoriesData.getItemModel(idx);
        var style = itemModel.getModel('itemStyle').getItemStyle();

        if (!style.fill) {
          style.fill = seriesModel.getColorFromPalette(name, paletteScope);
        }

        categoriesData.setItemVisual(idx, 'style', style);
        var symbolVisualList = ['symbol', 'symbolSize', 'symbolKeepAspect'];

        for (var i = 0; i < symbolVisualList.length; i++) {
          var symbolVisual = itemModel.getShallow(symbolVisualList[i], true);

          if (symbolVisual != null) {
            categoriesData.setItemVisual(idx, symbolVisualList[i], symbolVisual);
          }
        }
      });

      if (categoriesData.count()) {
        data.each(function (idx) {
          var model = data.getItemModel(idx);
          var categoryIdx = model.getShallow('category');

          if (categoryIdx != null) {
            if (typeof categoryIdx === 'string') {
              categoryIdx = categoryNameIdxMap['ec-' + categoryIdx];
            }

            var categoryStyle = categoriesData.getItemVisual(categoryIdx, 'style');
            var style = data.ensureUniqueItemVisual(idx, 'style');
            extend(style, categoryStyle);
            var visualList = ['symbol', 'symbolSize', 'symbolKeepAspect'];

            for (var i = 0; i < visualList.length; i++) {
              data.setItemVisual(idx, visualList[i], categoriesData.getItemVisual(categoryIdx, visualList[i]));
            }
          }
        });
      }
    });
  }

  function normalize$2(a) {
    if (!(a instanceof Array)) {
      a = [a, a];
    }

    return a;
  }

  function graphEdgeVisual(ecModel) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
      var graph = seriesModel.getGraph();
      var edgeData = seriesModel.getEdgeData();
      var symbolType = normalize$2(seriesModel.get('edgeSymbol'));
      var symbolSize = normalize$2(seriesModel.get('edgeSymbolSize'));
      edgeData.setVisual('fromSymbol', symbolType && symbolType[0]);
      edgeData.setVisual('toSymbol', symbolType && symbolType[1]);
      edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
      edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
      edgeData.setVisual('style', seriesModel.getModel('lineStyle').getLineStyle());
      edgeData.each(function (idx) {
        var itemModel = edgeData.getItemModel(idx);
        var edge = graph.getEdgeByIndex(idx);
        var symbolType = normalize$2(itemModel.getShallow('symbol', true));
        var symbolSize = normalize$2(itemModel.getShallow('symbolSize', true));
        var style = itemModel.getModel('lineStyle').getLineStyle();
        var existsStyle = edgeData.ensureUniqueItemVisual(idx, 'style');
        extend(existsStyle, style);

        switch (existsStyle.stroke) {
          case 'source':
            {
              var nodeStyle = edge.node1.getVisual('style');
              existsStyle.stroke = nodeStyle && nodeStyle.fill;
              break;
            }

          case 'target':
            {
              var nodeStyle = edge.node2.getVisual('style');
              existsStyle.stroke = nodeStyle && nodeStyle.fill;
              break;
            }
        }

        symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]);
        symbolType[1] && edge.setVisual('toSymbol', symbolType[1]);
        symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]);
        symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]);
      });
    });
  }

  function simpleLayout(seriesModel) {
    var coordSys = seriesModel.coordinateSystem;

    if (coordSys && coordSys.type !== 'view') {
      return;
    }

    var graph = seriesModel.getGraph();
    graph.eachNode(function (node) {
      var model = node.getModel();
      node.setLayout([+model.get('x'), +model.get('y')]);
    });
    simpleLayoutEdge(graph, seriesModel);
  }

  function simpleLayoutEdge(graph, seriesModel) {
    graph.eachEdge(function (edge, index) {
      var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, seriesModel, index, true), 0);
      var p1 = clone$1(edge.node1.getLayout());
      var p2 = clone$1(edge.node2.getLayout());
      var points = [p1, p2];

      if (+curveness) {
        points.push([(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness]);
      }

      edge.setLayout(points);
    });
  }

  function graphSimpleLayout(ecModel, api) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
      var layout = seriesModel.get('layout');
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys && coordSys.type !== 'view') {
        var data_1 = seriesModel.getData();
        var dimensions_1 = [];
        each(coordSys.dimensions, function (coordDim) {
          dimensions_1 = dimensions_1.concat(data_1.mapDimensionsAll(coordDim));
        });

        for (var dataIndex = 0; dataIndex < data_1.count(); dataIndex++) {
          var value = [];
          var hasValue = false;

          for (var i = 0; i < dimensions_1.length; i++) {
            var val = data_1.get(dimensions_1[i], dataIndex);

            if (!isNaN(val)) {
              hasValue = true;
            }

            value.push(val);
          }

          if (hasValue) {
            data_1.setItemLayout(dataIndex, coordSys.dataToPoint(value));
          } else {
            data_1.setItemLayout(dataIndex, [NaN, NaN]);
          }
        }

        simpleLayoutEdge(data_1.graph, seriesModel);
      } else if (!layout || layout === 'none') {
        simpleLayout(seriesModel);
      }
    });
  }

  var PI$7 = Math.PI;
  var _symbolRadiansHalf = [];

  function circularLayout(seriesModel, basedOn) {
    var coordSys = seriesModel.coordinateSystem;

    if (coordSys && coordSys.type !== 'view') {
      return;
    }

    var rect = coordSys.getBoundingRect();
    var nodeData = seriesModel.getData();
    var graph = nodeData.graph;
    var cx = rect.width / 2 + rect.x;
    var cy = rect.height / 2 + rect.y;
    var r = Math.min(rect.width, rect.height) / 2;
    var count = nodeData.count();
    nodeData.setLayout({
      cx: cx,
      cy: cy
    });

    if (!count) {
      return;
    }

    _layoutNodesBasedOn[basedOn](seriesModel, graph, nodeData, r, cx, cy, count);

    graph.eachEdge(function (edge, index) {
      var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), getCurvenessForEdge(edge, seriesModel, index), 0);
      var p1 = clone$1(edge.node1.getLayout());
      var p2 = clone$1(edge.node2.getLayout());
      var cp1;
      var x12 = (p1[0] + p2[0]) / 2;
      var y12 = (p1[1] + p2[1]) / 2;

      if (+curveness) {
        curveness *= 3;
        cp1 = [cx * curveness + x12 * (1 - curveness), cy * curveness + y12 * (1 - curveness)];
      }

      edge.setLayout([p1, p2, cp1]);
    });
  }

  var _layoutNodesBasedOn = {
    value: function (seriesModel, graph, nodeData, r, cx, cy, count) {
      var angle = 0;
      var sum = nodeData.getSum('value');
      var unitAngle = Math.PI * 2 / (sum || count);
      graph.eachNode(function (node) {
        var value = node.getValue('value');
        var radianHalf = unitAngle * (sum ? value : 1) / 2;
        angle += radianHalf;
        node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]);
        angle += radianHalf;
      });
    },
    symbolSize: function (seriesModel, graph, nodeData, r, cx, cy, count) {
      var sumRadian = 0;
      _symbolRadiansHalf.length = count;
      var nodeScale = getNodeGlobalScale(seriesModel);
      graph.eachNode(function (node) {
        var symbolSize = getSymbolSize(node);
        isNaN(symbolSize) && (symbolSize = 2);
        symbolSize < 0 && (symbolSize = 0);
        symbolSize *= nodeScale;
        var symbolRadianHalf = Math.asin(symbolSize / 2 / r);
        isNaN(symbolRadianHalf) && (symbolRadianHalf = PI$7 / 2);
        _symbolRadiansHalf[node.dataIndex] = symbolRadianHalf;
        sumRadian += symbolRadianHalf * 2;
      });
      var halfRemainRadian = (2 * PI$7 - sumRadian) / count / 2;
      var angle = 0;
      graph.eachNode(function (node) {
        var radianHalf = halfRemainRadian + _symbolRadiansHalf[node.dataIndex];
        angle += radianHalf;
        node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]);
        angle += radianHalf;
      });
    }
  };

  function graphCircularLayout(ecModel) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
      if (seriesModel.get('layout') === 'circular') {
        circularLayout(seriesModel, 'symbolSize');
      }
    });
  }

  var scaleAndAdd$1 = scaleAndAdd;

  function forceLayout(inNodes, inEdges, opts) {
    var nodes = inNodes;
    var edges = inEdges;
    var rect = opts.rect;
    var width = rect.width;
    var height = rect.height;
    var center = [rect.x + width / 2, rect.y + height / 2];
    var gravity = opts.gravity == null ? 0.1 : opts.gravity;

    for (var i = 0; i < nodes.length; i++) {
      var n = nodes[i];

      if (!n.p) {
        n.p = create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]);
      }

      n.pp = clone$1(n.p);
      n.edges = null;
    }

    var initialFriction = opts.friction == null ? 0.6 : opts.friction;
    var friction = initialFriction;
    var beforeStepCallback;
    var afterStepCallback;
    return {
      warmUp: function () {
        friction = initialFriction * 0.8;
      },
      setFixed: function (idx) {
        nodes[idx].fixed = true;
      },
      setUnfixed: function (idx) {
        nodes[idx].fixed = false;
      },
      beforeStep: function (cb) {
        beforeStepCallback = cb;
      },
      afterStep: function (cb) {
        afterStepCallback = cb;
      },
      step: function (cb) {
        beforeStepCallback && beforeStepCallback(nodes, edges);
        var v12 = [];
        var nLen = nodes.length;

        for (var i = 0; i < edges.length; i++) {
          var e = edges[i];

          if (e.ignoreForceLayout) {
            continue;
          }

          var n1 = e.n1;
          var n2 = e.n2;
          sub(v12, n2.p, n1.p);
          var d = len(v12) - e.d;
          var w = n2.w / (n1.w + n2.w);

          if (isNaN(w)) {
            w = 0;
          }

          normalize(v12, v12);
          !n1.fixed && scaleAndAdd$1(n1.p, n1.p, v12, w * d * friction);
          !n2.fixed && scaleAndAdd$1(n2.p, n2.p, v12, -(1 - w) * d * friction);
        }

        for (var i = 0; i < nLen; i++) {
          var n = nodes[i];

          if (!n.fixed) {
            sub(v12, center, n.p);
            scaleAndAdd$1(n.p, n.p, v12, gravity * friction);
          }
        }

        for (var i = 0; i < nLen; i++) {
          var n1 = nodes[i];

          for (var j = i + 1; j < nLen; j++) {
            var n2 = nodes[j];
            sub(v12, n2.p, n1.p);
            var d = len(v12);

            if (d === 0) {
              set(v12, Math.random() - 0.5, Math.random() - 0.5);
              d = 1;
            }

            var repFact = (n1.rep + n2.rep) / d / d;
            !n1.fixed && scaleAndAdd$1(n1.pp, n1.pp, v12, repFact);
            !n2.fixed && scaleAndAdd$1(n2.pp, n2.pp, v12, -repFact);
          }
        }

        var v = [];

        for (var i = 0; i < nLen; i++) {
          var n = nodes[i];

          if (!n.fixed) {
            sub(v, n.p, n.pp);
            scaleAndAdd$1(n.p, n.p, v, friction);
            copy(n.pp, n.p);
          }
        }

        friction = friction * 0.992;
        var finished = friction < 0.01;
        afterStepCallback && afterStepCallback(nodes, edges, finished);
        cb && cb(finished);
      }
    };
  }

  function graphForceLayout(ecModel) {
    ecModel.eachSeriesByType('graph', function (graphSeries) {
      var coordSys = graphSeries.coordinateSystem;

      if (coordSys && coordSys.type !== 'view') {
        return;
      }

      if (graphSeries.get('layout') === 'force') {
        var preservedPoints_1 = graphSeries.preservedPoints || {};
        var graph_1 = graphSeries.getGraph();
        var nodeData_1 = graph_1.data;
        var edgeData = graph_1.edgeData;
        var forceModel = graphSeries.getModel('force');
        var initLayout = forceModel.get('initLayout');

        if (graphSeries.preservedPoints) {
          nodeData_1.each(function (idx) {
            var id = nodeData_1.getId(idx);
            nodeData_1.setItemLayout(idx, preservedPoints_1[id] || [NaN, NaN]);
          });
        } else if (!initLayout || initLayout === 'none') {
          simpleLayout(graphSeries);
        } else if (initLayout === 'circular') {
          circularLayout(graphSeries, 'value');
        }

        var nodeDataExtent_1 = nodeData_1.getDataExtent('value');
        var edgeDataExtent_1 = edgeData.getDataExtent('value');
        var repulsion = forceModel.get('repulsion');
        var edgeLength = forceModel.get('edgeLength');
        var repulsionArr_1 = isArray(repulsion) ? repulsion : [repulsion, repulsion];
        var edgeLengthArr_1 = isArray(edgeLength) ? edgeLength : [edgeLength, edgeLength];
        edgeLengthArr_1 = [edgeLengthArr_1[1], edgeLengthArr_1[0]];
        var nodes_1 = nodeData_1.mapArray('value', function (value, idx) {
          var point = nodeData_1.getItemLayout(idx);
          var rep = linearMap(value, nodeDataExtent_1, repulsionArr_1);

          if (isNaN(rep)) {
            rep = (repulsionArr_1[0] + repulsionArr_1[1]) / 2;
          }

          return {
            w: rep,
            rep: rep,
            fixed: nodeData_1.getItemModel(idx).get('fixed'),
            p: !point || isNaN(point[0]) || isNaN(point[1]) ? null : point
          };
        });
        var edges = edgeData.mapArray('value', function (value, idx) {
          var edge = graph_1.getEdgeByIndex(idx);
          var d = linearMap(value, edgeDataExtent_1, edgeLengthArr_1);

          if (isNaN(d)) {
            d = (edgeLengthArr_1[0] + edgeLengthArr_1[1]) / 2;
          }

          var edgeModel = edge.getModel();
          var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, graphSeries, idx, true), 0);
          return {
            n1: nodes_1[edge.node1.dataIndex],
            n2: nodes_1[edge.node2.dataIndex],
            d: d,
            curveness: curveness,
            ignoreForceLayout: edgeModel.get('ignoreForceLayout')
          };
        });
        var rect = coordSys.getBoundingRect();
        var forceInstance = forceLayout(nodes_1, edges, {
          rect: rect,
          gravity: forceModel.get('gravity'),
          friction: forceModel.get('friction')
        });
        forceInstance.beforeStep(function (nodes, edges) {
          for (var i = 0, l = nodes.length; i < l; i++) {
            if (nodes[i].fixed) {
              copy(nodes[i].p, graph_1.getNodeByIndex(i).getLayout());
            }
          }
        });
        forceInstance.afterStep(function (nodes, edges, stopped) {
          for (var i = 0, l = nodes.length; i < l; i++) {
            if (!nodes[i].fixed) {
              graph_1.getNodeByIndex(i).setLayout(nodes[i].p);
            }

            preservedPoints_1[nodeData_1.getId(i)] = nodes[i].p;
          }

          for (var i = 0, l = edges.length; i < l; i++) {
            var e = edges[i];
            var edge = graph_1.getEdgeByIndex(i);
            var p1 = e.n1.p;
            var p2 = e.n2.p;
            var points = edge.getLayout();
            points = points ? points.slice() : [];
            points[0] = points[0] || [];
            points[1] = points[1] || [];
            copy(points[0], p1);
            copy(points[1], p2);

            if (+e.curveness) {
              points[2] = [(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness];
            }

            edge.setLayout(points);
          }
        });
        graphSeries.forceLayout = forceInstance;
        graphSeries.preservedPoints = preservedPoints_1;
        forceInstance.step();
      } else {
        graphSeries.forceLayout = null;
      }
    });
  }

  function getViewRect$2(seriesModel, api, aspect) {
    var option = extend(seriesModel.getBoxLayoutParams(), {
      aspect: aspect
    });
    return getLayoutRect(option, {
      width: api.getWidth(),
      height: api.getHeight()
    });
  }

  function createViewCoordSys(ecModel, api) {
    var viewList = [];
    ecModel.eachSeriesByType('graph', function (seriesModel) {
      var coordSysType = seriesModel.get('coordinateSystem');

      if (!coordSysType || coordSysType === 'view') {
        var data_1 = seriesModel.getData();
        var positions = data_1.mapArray(function (idx) {
          var itemModel = data_1.getItemModel(idx);
          return [+itemModel.get('x'), +itemModel.get('y')];
        });
        var min = [];
        var max = [];
        fromPoints(positions, min, max);

        if (max[0] - min[0] === 0) {
          max[0] += 1;
          min[0] -= 1;
        }

        if (max[1] - min[1] === 0) {
          max[1] += 1;
          min[1] -= 1;
        }

        var aspect = (max[0] - min[0]) / (max[1] - min[1]);
        var viewRect = getViewRect$2(seriesModel, api, aspect);

        if (isNaN(aspect)) {
          min = [viewRect.x, viewRect.y];
          max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height];
        }

        var bbWidth = max[0] - min[0];
        var bbHeight = max[1] - min[1];
        var viewWidth = viewRect.width;
        var viewHeight = viewRect.height;
        var viewCoordSys = seriesModel.coordinateSystem = new View();
        viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
        viewCoordSys.setBoundingRect(min[0], min[1], bbWidth, bbHeight);
        viewCoordSys.setViewRect(viewRect.x, viewRect.y, viewWidth, viewHeight);
        viewCoordSys.setCenter(seriesModel.get('center'));
        viewCoordSys.setZoom(seriesModel.get('zoom'));
        viewList.push(viewCoordSys);
      }
    });
    return viewList;
  }

  registerProcessor(categoryFilter);
  registerVisual(categoryVisual);
  registerVisual(graphEdgeVisual);
  registerLayout(graphSimpleLayout);
  registerLayout(PRIORITY.VISUAL.POST_CHART_LAYOUT, graphCircularLayout);
  registerLayout(graphForceLayout);
  registerCoordinateSystem('graphView', {
    dimensions: View.dimensions,
    create: createViewCoordSys
  });

  var GaugeSeriesModel = function (_super) {
    __extends(GaugeSeriesModel, _super);

    function GaugeSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GaugeSeriesModel.type;
      _this.visualStyleAccessPath = 'itemStyle';
      _this.useColorPaletteOnData = true;
      return _this;
    }

    GaugeSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListSimply(this, ['value']);
    };

    GaugeSeriesModel.type = 'series.gauge';
    GaugeSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      center: ['50%', '50%'],
      legendHoverLink: true,
      radius: '75%',
      startAngle: 225,
      endAngle: -45,
      clockwise: true,
      min: 0,
      max: 100,
      splitNumber: 10,
      axisLine: {
        show: true,
        roundCap: false,
        lineStyle: {
          color: [[1, '#E6EBF8']],
          width: 10
        }
      },
      progress: {
        show: false,
        overlap: true,
        width: 10,
        roundCap: false,
        clip: true
      },
      splitLine: {
        show: true,
        length: 10,
        distance: 10,
        lineStyle: {
          color: '#63677A',
          width: 3,
          type: 'solid'
        }
      },
      axisTick: {
        show: true,
        splitNumber: 5,
        length: 6,
        distance: 10,
        lineStyle: {
          color: '#63677A',
          width: 1,
          type: 'solid'
        }
      },
      axisLabel: {
        show: true,
        distance: 15,
        color: '#464646',
        fontSize: 12
      },
      pointer: {
        icon: null,
        offsetCenter: [0, 0],
        show: true,
        length: '60%',
        width: 6,
        keepAspect: false
      },
      anchor: {
        show: false,
        showAbove: false,
        size: 6,
        icon: 'circle',
        offsetCenter: [0, 0],
        keepAspect: false,
        itemStyle: {
          color: '#fff',
          borderWidth: 0,
          borderColor: '#5470c6'
        }
      },
      title: {
        show: true,
        offsetCenter: [0, '20%'],
        color: '#464646',
        fontSize: 16,
        valueAnimation: false
      },
      detail: {
        show: true,
        backgroundColor: 'rgba(0,0,0,0)',
        borderWidth: 0,
        borderColor: '#ccc',
        width: 100,
        height: null,
        padding: [5, 10],
        offsetCenter: [0, '40%'],
        color: '#464646',
        fontSize: 30,
        fontWeight: 'bold',
        lineHeight: 30,
        valueAnimation: false
      }
    };
    return GaugeSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(GaugeSeriesModel);

  var PointerShape = function () {
    function PointerShape() {
      this.angle = 0;
      this.width = 10;
      this.r = 10;
      this.x = 0;
      this.y = 0;
    }

    return PointerShape;
  }();

  var PointerPath = function (_super) {
    __extends(PointerPath, _super);

    function PointerPath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'pointer';
      return _this;
    }

    PointerPath.prototype.getDefaultShape = function () {
      return new PointerShape();
    };

    PointerPath.prototype.buildPath = function (ctx, shape) {
      var mathCos = Math.cos;
      var mathSin = Math.sin;
      var r = shape.r;
      var width = shape.width;
      var angle = shape.angle;
      var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2);
      var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2);
      angle = shape.angle - Math.PI / 2;
      ctx.moveTo(x, y);
      ctx.lineTo(shape.x + mathCos(angle) * width, shape.y + mathSin(angle) * width);
      ctx.lineTo(shape.x + mathCos(shape.angle) * r, shape.y + mathSin(shape.angle) * r);
      ctx.lineTo(shape.x - mathCos(angle) * width, shape.y - mathSin(angle) * width);
      ctx.lineTo(x, y);
    };

    return PointerPath;
  }(Path);

  function parsePosition(seriesModel, api) {
    var center = seriesModel.get('center');
    var width = api.getWidth();
    var height = api.getHeight();
    var size = Math.min(width, height);
    var cx = parsePercent$2(center[0], api.getWidth());
    var cy = parsePercent$2(center[1], api.getHeight());
    var r = parsePercent$2(seriesModel.get('radius'), size / 2);
    return {
      cx: cx,
      cy: cy,
      r: r
    };
  }

  function formatLabel(value, labelFormatter) {
    var label = value == null ? '' : value + '';

    if (labelFormatter) {
      if (typeof labelFormatter === 'string') {
        label = labelFormatter.replace('{value}', label);
      } else if (typeof labelFormatter === 'function') {
        label = labelFormatter(value);
      }
    }

    return label;
  }

  var PI2$9 = Math.PI * 2;

  var GaugeView = function (_super) {
    __extends(GaugeView, _super);

    function GaugeView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GaugeView.type;
      return _this;
    }

    GaugeView.prototype.render = function (seriesModel, ecModel, api) {
      this.group.removeAll();
      var colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']);
      var posInfo = parsePosition(seriesModel, api);

      this._renderMain(seriesModel, ecModel, api, colorList, posInfo);

      this._data = seriesModel.getData();
    };

    GaugeView.prototype.dispose = function () {};

    GaugeView.prototype._renderMain = function (seriesModel, ecModel, api, colorList, posInfo) {
      var group = this.group;
      var clockwise = seriesModel.get('clockwise');
      var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
      var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;
      var axisLineModel = seriesModel.getModel('axisLine');
      var roundCap = axisLineModel.get('roundCap');
      var MainPath = roundCap ? SausagePath : Sector;
      var showAxis = axisLineModel.get('show');
      var lineStyleModel = axisLineModel.getModel('lineStyle');
      var axisLineWidth = lineStyleModel.get('width');
      var angleRangeSpan = !((endAngle - startAngle) % PI2$9) && endAngle !== startAngle ? PI2$9 : (endAngle - startAngle) % PI2$9;
      var prevEndAngle = startAngle;

      for (var i = 0; showAxis && i < colorList.length; i++) {
        var percent = Math.min(Math.max(colorList[i][0], 0), 1);
        endAngle = startAngle + angleRangeSpan * percent;
        var sector = new MainPath({
          shape: {
            startAngle: prevEndAngle,
            endAngle: endAngle,
            cx: posInfo.cx,
            cy: posInfo.cy,
            clockwise: clockwise,
            r0: posInfo.r - axisLineWidth,
            r: posInfo.r
          },
          silent: true
        });
        sector.setStyle({
          fill: colorList[i][1]
        });
        sector.setStyle(lineStyleModel.getLineStyle(['color', 'width']));
        group.add(sector);
        prevEndAngle = endAngle;
      }

      var getColor = function (percent) {
        if (percent <= 0) {
          return colorList[0][1];
        }

        var i;

        for (i = 0; i < colorList.length; i++) {
          if (colorList[i][0] >= percent && (i === 0 ? 0 : colorList[i - 1][0]) < percent) {
            return colorList[i][1];
          }
        }

        return colorList[i - 1][1];
      };

      if (!clockwise) {
        var tmp = startAngle;
        startAngle = endAngle;
        endAngle = tmp;
      }

      this._renderTicks(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth);

      this._renderTitleAndDetail(seriesModel, ecModel, api, getColor, posInfo);

      this._renderAnchor(seriesModel, posInfo);

      this._renderPointer(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth);
    };

    GaugeView.prototype._renderTicks = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) {
      var group = this.group;
      var cx = posInfo.cx;
      var cy = posInfo.cy;
      var r = posInfo.r;
      var minVal = +seriesModel.get('min');
      var maxVal = +seriesModel.get('max');
      var splitLineModel = seriesModel.getModel('splitLine');
      var tickModel = seriesModel.getModel('axisTick');
      var labelModel = seriesModel.getModel('axisLabel');
      var splitNumber = seriesModel.get('splitNumber');
      var subSplitNumber = tickModel.get('splitNumber');
      var splitLineLen = parsePercent$2(splitLineModel.get('length'), r);
      var tickLen = parsePercent$2(tickModel.get('length'), r);
      var angle = startAngle;
      var step = (endAngle - startAngle) / splitNumber;
      var subStep = step / subSplitNumber;
      var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
      var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();
      var splitLineDistance = splitLineModel.get('distance');
      var unitX;
      var unitY;

      for (var i = 0; i <= splitNumber; i++) {
        unitX = Math.cos(angle);
        unitY = Math.sin(angle);

        if (splitLineModel.get('show')) {
          var distance = splitLineDistance ? splitLineDistance + axisLineWidth : axisLineWidth;
          var splitLine = new Line({
            shape: {
              x1: unitX * (r - distance) + cx,
              y1: unitY * (r - distance) + cy,
              x2: unitX * (r - splitLineLen - distance) + cx,
              y2: unitY * (r - splitLineLen - distance) + cy
            },
            style: splitLineStyle,
            silent: true
          });

          if (splitLineStyle.stroke === 'auto') {
            splitLine.setStyle({
              stroke: getColor(i / splitNumber)
            });
          }

          group.add(splitLine);
        }

        if (labelModel.get('show')) {
          var distance = labelModel.get('distance') + splitLineDistance;
          var label = formatLabel(round$1(i / splitNumber * (maxVal - minVal) + minVal), labelModel.get('formatter'));
          var autoColor = getColor(i / splitNumber);
          group.add(new ZRText({
            style: createTextStyle(labelModel, {
              text: label,
              x: unitX * (r - splitLineLen - distance) + cx,
              y: unitY * (r - splitLineLen - distance) + cy,
              verticalAlign: unitY < -0.8 ? 'top' : unitY > 0.8 ? 'bottom' : 'middle',
              align: unitX < -0.4 ? 'left' : unitX > 0.4 ? 'right' : 'center'
            }, {
              inheritColor: autoColor
            }),
            silent: true
          }));
        }

        if (tickModel.get('show') && i !== splitNumber) {
          var distance = tickModel.get('distance');
          distance = distance ? distance + axisLineWidth : axisLineWidth;

          for (var j = 0; j <= subSplitNumber; j++) {
            unitX = Math.cos(angle);
            unitY = Math.sin(angle);
            var tickLine = new Line({
              shape: {
                x1: unitX * (r - distance) + cx,
                y1: unitY * (r - distance) + cy,
                x2: unitX * (r - tickLen - distance) + cx,
                y2: unitY * (r - tickLen - distance) + cy
              },
              silent: true,
              style: tickLineStyle
            });

            if (tickLineStyle.stroke === 'auto') {
              tickLine.setStyle({
                stroke: getColor((i + j / subSplitNumber) / splitNumber)
              });
            }

            group.add(tickLine);
            angle += subStep;
          }

          angle -= subStep;
        } else {
          angle += step;
        }
      }
    };

    GaugeView.prototype._renderPointer = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) {
      var group = this.group;
      var oldData = this._data;
      var oldProgressData = this._progressEls;
      var progressList = [];
      var showPointer = seriesModel.get(['pointer', 'show']);
      var progressModel = seriesModel.getModel('progress');
      var showProgress = progressModel.get('show');
      var data = seriesModel.getData();
      var valueDim = data.mapDimension('value');
      var minVal = +seriesModel.get('min');
      var maxVal = +seriesModel.get('max');
      var valueExtent = [minVal, maxVal];
      var angleExtent = [startAngle, endAngle];

      function createPointer(idx, angle) {
        var itemModel = data.getItemModel(idx);
        var pointerModel = itemModel.getModel('pointer');
        var pointerWidth = parsePercent$2(pointerModel.get('width'), posInfo.r);
        var pointerLength = parsePercent$2(pointerModel.get('length'), posInfo.r);
        var pointerStr = seriesModel.get(['pointer', 'icon']);
        var pointerOffset = pointerModel.get('offsetCenter');
        var pointerKeepAspect = pointerModel.get('keepAspect');
        var pointer;

        if (pointerStr) {
          pointer = createSymbol(pointerStr, parsePercent$2(pointerOffset[0], posInfo.r) - pointerWidth / 2, parsePercent$2(pointerOffset[1], posInfo.r) - pointerLength, pointerWidth, pointerLength, null, pointerKeepAspect);
        } else {
          pointer = new PointerPath({
            shape: {
              angle: -Math.PI / 2,
              width: parsePercent$2(pointerModel.get('width'), posInfo.r),
              r: parsePercent$2(pointerModel.get('length'), posInfo.r)
            }
          });
        }

        pointer.rotation = -(angle + Math.PI / 2);
        pointer.x = posInfo.cx;
        pointer.y = posInfo.cy;
        return pointer;
      }

      function createProgress(idx, endAngle) {
        var roundCap = progressModel.get('roundCap');
        var ProgressPath = roundCap ? SausagePath : Sector;
        var isOverlap = progressModel.get('overlap');
        var progressWidth = isOverlap ? progressModel.get('width') : axisLineWidth / data.count();
        var r0 = isOverlap ? posInfo.r - progressWidth : posInfo.r - (idx + 1) * progressWidth;
        var r = isOverlap ? posInfo.r : posInfo.r - idx * progressWidth;
        var progress = new ProgressPath({
          shape: {
            startAngle: startAngle,
            endAngle: endAngle,
            cx: posInfo.cx,
            cy: posInfo.cy,
            clockwise: clockwise,
            r0: r0,
            r: r
          }
        });
        isOverlap && (progress.z2 = maxVal - data.get(valueDim, idx) % maxVal);
        return progress;
      }

      if (showProgress || showPointer) {
        data.diff(oldData).add(function (idx) {
          if (showPointer) {
            var pointer = createPointer(idx, startAngle);
            initProps(pointer, {
              rotation: -(linearMap(data.get(valueDim, idx), valueExtent, angleExtent, true) + Math.PI / 2)
            }, seriesModel);
            group.add(pointer);
            data.setItemGraphicEl(idx, pointer);
          }

          if (showProgress) {
            var progress = createProgress(idx, startAngle);
            var isClip = progressModel.get('clip');
            initProps(progress, {
              shape: {
                endAngle: linearMap(data.get(valueDim, idx), valueExtent, angleExtent, isClip)
              }
            }, seriesModel);
            group.add(progress);
            progressList[idx] = progress;
          }
        }).update(function (newIdx, oldIdx) {
          if (showPointer) {
            var previousPointer = oldData.getItemGraphicEl(oldIdx);
            var previousRotate = previousPointer ? previousPointer.rotation : startAngle;
            var pointer = createPointer(newIdx, previousRotate);
            pointer.rotation = previousRotate;
            updateProps(pointer, {
              rotation: -(linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, true) + Math.PI / 2)
            }, seriesModel);
            group.add(pointer);
            data.setItemGraphicEl(newIdx, pointer);
          }

          if (showProgress) {
            var previousProgress = oldProgressData[oldIdx];
            var previousEndAngle = previousProgress ? previousProgress.shape.endAngle : startAngle;
            var progress = createProgress(newIdx, previousEndAngle);
            var isClip = progressModel.get('clip');
            updateProps(progress, {
              shape: {
                endAngle: linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, isClip)
              }
            }, seriesModel);
            group.add(progress);
            progressList[newIdx] = progress;
          }
        }).execute();
        data.each(function (idx) {
          var itemModel = data.getItemModel(idx);
          var emphasisModel = itemModel.getModel('emphasis');

          if (showPointer) {
            var pointer = data.getItemGraphicEl(idx);
            pointer.useStyle(data.getItemVisual(idx, 'style'));
            pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle());

            if (pointer.style.fill === 'auto') {
              pointer.setStyle('fill', getColor(linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true)));
            }

            pointer.z2EmphasisLift = 0;
            setStatesStylesFromModel(pointer, itemModel);
            enableHoverEmphasis(pointer, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
          }

          if (showProgress) {
            var progress = progressList[idx];
            progress.useStyle(data.getItemVisual(idx, 'style'));
            progress.setStyle(itemModel.getModel(['progress', 'itemStyle']).getItemStyle());
            progress.z2EmphasisLift = 0;
            setStatesStylesFromModel(progress, itemModel);
            enableHoverEmphasis(progress, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
          }
        });
        this._progressEls = progressList;
      }
    };

    GaugeView.prototype._renderAnchor = function (seriesModel, posInfo) {
      var anchorModel = seriesModel.getModel('anchor');
      var showAnchor = anchorModel.get('show');

      if (showAnchor) {
        var anchorSize = anchorModel.get('size');
        var anchorType = anchorModel.get('icon');
        var offsetCenter = anchorModel.get('offsetCenter');
        var anchorKeepAspect = anchorModel.get('keepAspect');
        var anchor = createSymbol(anchorType, posInfo.cx - anchorSize / 2 + parsePercent$2(offsetCenter[0], posInfo.r), posInfo.cy - anchorSize / 2 + parsePercent$2(offsetCenter[1], posInfo.r), anchorSize, anchorSize, null, anchorKeepAspect);
        anchor.z2 = anchorModel.get('showAbove') ? 1 : 0;
        anchor.setStyle(anchorModel.getModel('itemStyle').getItemStyle());
        this.group.add(anchor);
      }
    };

    GaugeView.prototype._renderTitleAndDetail = function (seriesModel, ecModel, api, getColor, posInfo) {
      var _this = this;

      var data = seriesModel.getData();
      var valueDim = data.mapDimension('value');
      var minVal = +seriesModel.get('min');
      var maxVal = +seriesModel.get('max');
      var contentGroup = new Group();
      var newTitleEls = [];
      var newDetailEls = [];
      var hasAnimation = seriesModel.isAnimationEnabled();
      data.diff(this._data).add(function (idx) {
        newTitleEls[idx] = new ZRText({
          silent: true
        });
        newDetailEls[idx] = new ZRText({
          silent: true
        });
      }).update(function (idx, oldIdx) {
        newTitleEls[idx] = _this._titleEls[oldIdx];
        newDetailEls[idx] = _this._detailEls[oldIdx];
      }).execute();
      data.each(function (idx) {
        var itemModel = data.getItemModel(idx);
        var value = data.get(valueDim, idx);
        var itemGroup = new Group();
        var autoColor = getColor(linearMap(value, [minVal, maxVal], [0, 1], true));
        var itemTitleModel = itemModel.getModel('title');

        if (itemTitleModel.get('show')) {
          var titleOffsetCenter = itemTitleModel.get('offsetCenter');
          var titleX = posInfo.cx + parsePercent$2(titleOffsetCenter[0], posInfo.r);
          var titleY = posInfo.cy + parsePercent$2(titleOffsetCenter[1], posInfo.r);
          var labelEl = newTitleEls[idx];
          labelEl.attr({
            style: createTextStyle(itemTitleModel, {
              x: titleX,
              y: titleY,
              text: data.getName(idx),
              align: 'center',
              verticalAlign: 'middle'
            }, {
              inheritColor: autoColor
            })
          });
          setLabelValueAnimation(labelEl, {
            normal: itemTitleModel
          }, seriesModel.getRawValue(idx), function () {
            return data.getName(idx);
          });
          hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel);
          itemGroup.add(labelEl);
        }

        var itemDetailModel = itemModel.getModel('detail');

        if (itemDetailModel.get('show')) {
          var detailOffsetCenter = itemDetailModel.get('offsetCenter');
          var detailX = posInfo.cx + parsePercent$2(detailOffsetCenter[0], posInfo.r);
          var detailY = posInfo.cy + parsePercent$2(detailOffsetCenter[1], posInfo.r);
          var width = parsePercent$2(itemDetailModel.get('width'), posInfo.r);
          var height = parsePercent$2(itemDetailModel.get('height'), posInfo.r);
          var detailColor = seriesModel.get(['progress', 'show']) ? data.getItemVisual(idx, 'style').fill : autoColor;
          var labelEl = newDetailEls[idx];
          var formatter_1 = itemDetailModel.get('formatter');
          labelEl.attr({
            style: createTextStyle(itemDetailModel, {
              x: detailX,
              y: detailY,
              text: formatLabel(value, formatter_1),
              width: isNaN(width) ? null : width,
              height: isNaN(height) ? null : height,
              align: 'center',
              verticalAlign: 'middle'
            }, {
              inheritColor: detailColor
            })
          });
          setLabelValueAnimation(labelEl, {
            normal: itemDetailModel
          }, seriesModel.getRawValue(idx), function (value) {
            return formatLabel(value, formatter_1);
          });
          hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel);
          itemGroup.add(labelEl);
        }

        contentGroup.add(itemGroup);
      });
      this.group.add(contentGroup);
      this._titleEls = newTitleEls;
      this._detailEls = newDetailEls;
    };

    GaugeView.type = 'gauge';
    return GaugeView;
  }(ChartView);

  ChartView.registerClass(GaugeView);

  var FunnelSeriesModel = function (_super) {
    __extends(FunnelSeriesModel, _super);

    function FunnelSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = FunnelSeriesModel.type;
      _this.useColorPaletteOnData = true;
      return _this;
    }

    FunnelSeriesModel.prototype.init = function (option) {
      _super.prototype.init.apply(this, arguments);

      this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this));

      this._defaultLabelLine(option);
    };

    FunnelSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListSimply(this, {
        coordDimensions: ['value'],
        encodeDefaulter: curry(makeSeriesEncodeForNameBased, this)
      });
    };

    FunnelSeriesModel.prototype._defaultLabelLine = function (option) {
      defaultEmphasis(option, 'labelLine', ['show']);
      var labelLineNormalOpt = option.labelLine;
      var labelLineEmphasisOpt = option.emphasis.labelLine;
      labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show;
      labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show;
    };

    FunnelSeriesModel.prototype.getDataParams = function (dataIndex) {
      var data = this.getData();

      var params = _super.prototype.getDataParams.call(this, dataIndex);

      var valueDim = data.mapDimension('value');
      var sum = data.getSum(valueDim);
      params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) / sum * 100).toFixed(2);
      params.$vars.push('percent');
      return params;
    };

    FunnelSeriesModel.type = 'series.funnel';
    FunnelSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      left: 80,
      top: 60,
      right: 80,
      bottom: 60,
      minSize: '0%',
      maxSize: '100%',
      sort: 'descending',
      orient: 'vertical',
      gap: 0,
      funnelAlign: 'center',
      label: {
        show: true,
        position: 'outer'
      },
      labelLine: {
        show: true,
        length: 20,
        lineStyle: {
          width: 1
        }
      },
      itemStyle: {
        borderColor: '#fff',
        borderWidth: 1
      },
      emphasis: {
        label: {
          show: true
        }
      },
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      }
    };
    return FunnelSeriesModel;
  }(SeriesModel);

  ComponentModel.registerClass(FunnelSeriesModel);
  var opacityAccessPath = ['itemStyle', 'opacity'];

  var FunnelPiece = function (_super) {
    __extends(FunnelPiece, _super);

    function FunnelPiece(data, idx) {
      var _this = _super.call(this) || this;

      var polygon = _this;
      var labelLine = new Polyline();
      var text = new ZRText();
      polygon.setTextContent(text);

      _this.setTextGuideLine(labelLine);

      _this.updateData(data, idx, true);

      return _this;
    }

    FunnelPiece.prototype.updateData = function (data, idx, firstCreate) {
      var polygon = this;
      var seriesModel = data.hostModel;
      var itemModel = data.getItemModel(idx);
      var layout = data.getItemLayout(idx);
      var emphasisModel = itemModel.getModel('emphasis');
      var opacity = itemModel.get(opacityAccessPath);
      opacity = opacity == null ? 1 : opacity;
      polygon.useStyle(data.getItemVisual(idx, 'style'));
      polygon.style.lineJoin = 'round';

      if (firstCreate) {
        polygon.setShape({
          points: layout.points
        });
        polygon.style.opacity = 0;
        initProps(polygon, {
          style: {
            opacity: opacity
          }
        }, seriesModel, idx);
      } else {
        updateProps(polygon, {
          style: {
            opacity: opacity
          },
          shape: {
            points: layout.points
          }
        }, seriesModel, idx);
      }

      setStatesStylesFromModel(polygon, itemModel);

      this._updateLabel(data, idx);

      enableHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
    };

    FunnelPiece.prototype._updateLabel = function (data, idx) {
      var polygon = this;
      var labelLine = this.getTextGuideLine();
      var labelText = polygon.getTextContent();
      var seriesModel = data.hostModel;
      var itemModel = data.getItemModel(idx);
      var layout = data.getItemLayout(idx);
      var labelLayout = layout.label;
      var style = data.getItemVisual(idx, 'style');
      var visualColor = style.fill;
      setLabelStyle(labelText, getLabelStatesModels(itemModel), {
        labelFetcher: data.hostModel,
        labelDataIndex: idx,
        defaultOpacity: style.opacity,
        defaultText: data.getName(idx)
      }, {
        normal: {
          align: labelLayout.textAlign,
          verticalAlign: labelLayout.verticalAlign
        }
      });
      polygon.setTextConfig({
        local: true,
        inside: !!labelLayout.inside,
        insideStroke: visualColor,
        outsideFill: visualColor
      });
      var linePoints = labelLayout.linePoints;
      labelLine.setShape({
        points: linePoints
      });
      polygon.textGuideLineConfig = {
        anchor: linePoints ? new Point(linePoints[0][0], linePoints[0][1]) : null
      };
      updateProps(labelText, {
        style: {
          x: labelLayout.x,
          y: labelLayout.y
        }
      }, seriesModel, idx);
      labelText.attr({
        rotation: labelLayout.rotation,
        originX: labelLayout.x,
        originY: labelLayout.y,
        z2: 10
      });
      setLabelLineStyle(polygon, getLabelLineStatesModels(itemModel), {
        stroke: visualColor
      });
    };

    return FunnelPiece;
  }(Polygon);

  var FunnelView = function (_super) {
    __extends(FunnelView, _super);

    function FunnelView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = FunnelView.type;
      _this.ignoreLabelLineUpdate = true;
      return _this;
    }

    FunnelView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var oldData = this._data;
      var group = this.group;
      data.diff(oldData).add(function (idx) {
        var funnelPiece = new FunnelPiece(data, idx);
        data.setItemGraphicEl(idx, funnelPiece);
        group.add(funnelPiece);
      }).update(function (newIdx, oldIdx) {
        var piece = oldData.getItemGraphicEl(oldIdx);
        piece.updateData(data, newIdx);
        group.add(piece);
        data.setItemGraphicEl(newIdx, piece);
      }).remove(function (idx) {
        var piece = oldData.getItemGraphicEl(idx);
        removeElementWithFadeOut(piece, seriesModel, idx);
      }).execute();
      this._data = data;
    };

    FunnelView.prototype.remove = function () {
      this.group.removeAll();
      this._data = null;
    };

    FunnelView.prototype.dispose = function () {};

    FunnelView.type = 'funnel';
    return FunnelView;
  }(ChartView);

  ChartView.registerClass(FunnelView);

  function getViewRect$3(seriesModel, api) {
    return getLayoutRect(seriesModel.getBoxLayoutParams(), {
      width: api.getWidth(),
      height: api.getHeight()
    });
  }

  function getSortedIndices(data, sort) {
    var valueDim = data.mapDimension('value');
    var valueArr = data.mapArray(valueDim, function (val) {
      return val;
    });
    var indices = [];
    var isAscending = sort === 'ascending';

    for (var i = 0, len = data.count(); i < len; i++) {
      indices[i] = i;
    }

    if (typeof sort === 'function') {
      indices.sort(sort);
    } else if (sort !== 'none') {
      indices.sort(function (a, b) {
        return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a];
      });
    }

    return indices;
  }

  function labelLayout(data) {
    var seriesModel = data.hostModel;
    var orient = seriesModel.get('orient');
    data.each(function (idx) {
      var itemModel = data.getItemModel(idx);
      var labelModel = itemModel.getModel('label');
      var labelPosition = labelModel.get('position');
      var labelLineModel = itemModel.getModel('labelLine');
      var layout = data.getItemLayout(idx);
      var points = layout.points;
      var isLabelInside = labelPosition === 'inner' || labelPosition === 'inside' || labelPosition === 'center' || labelPosition === 'insideLeft' || labelPosition === 'insideRight';
      var textAlign;
      var textX;
      var textY;
      var linePoints;

      if (isLabelInside) {
        if (labelPosition === 'insideLeft') {
          textX = (points[0][0] + points[3][0]) / 2 + 5;
          textY = (points[0][1] + points[3][1]) / 2;
          textAlign = 'left';
        } else if (labelPosition === 'insideRight') {
          textX = (points[1][0] + points[2][0]) / 2 - 5;
          textY = (points[1][1] + points[2][1]) / 2;
          textAlign = 'right';
        } else {
          textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
          textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
          textAlign = 'center';
        }

        linePoints = [[textX, textY], [textX, textY]];
      } else {
        var x1 = void 0;
        var y1 = void 0;
        var x2 = void 0;
        var y2 = void 0;
        var labelLineLen = labelLineModel.get('length');

        if (true) {
          if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) {
            labelPosition = 'left';
            console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.');
          }

          if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) {
            labelPosition = 'bottom';
            console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.');
          }
        }

        if (labelPosition === 'left') {
          x1 = (points[3][0] + points[0][0]) / 2;
          y1 = (points[3][1] + points[0][1]) / 2;
          x2 = x1 - labelLineLen;
          textX = x2 - 5;
          textAlign = 'right';
        } else if (labelPosition === 'right') {
          x1 = (points[1][0] + points[2][0]) / 2;
          y1 = (points[1][1] + points[2][1]) / 2;
          x2 = x1 + labelLineLen;
          textX = x2 + 5;
          textAlign = 'left';
        } else if (labelPosition === 'top') {
          x1 = (points[3][0] + points[0][0]) / 2;
          y1 = (points[3][1] + points[0][1]) / 2;
          y2 = y1 - labelLineLen;
          textY = y2 - 5;
          textAlign = 'center';
        } else if (labelPosition === 'bottom') {
          x1 = (points[1][0] + points[2][0]) / 2;
          y1 = (points[1][1] + points[2][1]) / 2;
          y2 = y1 + labelLineLen;
          textY = y2 + 5;
          textAlign = 'center';
        } else if (labelPosition === 'rightTop') {
          x1 = orient === 'horizontal' ? points[3][0] : points[1][0];
          y1 = orient === 'horizontal' ? points[3][1] : points[1][1];

          if (orient === 'horizontal') {
            y2 = y1 - labelLineLen;
            textY = y2 - 5;
            textAlign = 'center';
          } else {
            x2 = x1 + labelLineLen;
            textX = x2 + 5;
            textAlign = 'top';
          }
        } else if (labelPosition === 'rightBottom') {
          x1 = points[2][0];
          y1 = points[2][1];

          if (orient === 'horizontal') {
            y2 = y1 + labelLineLen;
            textY = y2 + 5;
            textAlign = 'center';
          } else {
            x2 = x1 + labelLineLen;
            textX = x2 + 5;
            textAlign = 'bottom';
          }
        } else if (labelPosition === 'leftTop') {
          x1 = points[0][0];
          y1 = orient === 'horizontal' ? points[0][1] : points[1][1];

          if (orient === 'horizontal') {
            y2 = y1 - labelLineLen;
            textY = y2 - 5;
            textAlign = 'center';
          } else {
            x2 = x1 - labelLineLen;
            textX = x2 - 5;
            textAlign = 'right';
          }
        } else if (labelPosition === 'leftBottom') {
          x1 = orient === 'horizontal' ? points[1][0] : points[3][0];
          y1 = orient === 'horizontal' ? points[1][1] : points[2][1];

          if (orient === 'horizontal') {
            y2 = y1 + labelLineLen;
            textY = y2 + 5;
            textAlign = 'center';
          } else {
            x2 = x1 - labelLineLen;
            textX = x2 - 5;
            textAlign = 'right';
          }
        } else {
          x1 = (points[1][0] + points[2][0]) / 2;
          y1 = (points[1][1] + points[2][1]) / 2;

          if (orient === 'horizontal') {
            y2 = y1 + labelLineLen;
            textY = y2 + 5;
            textAlign = 'center';
          } else {
            x2 = x1 + labelLineLen;
            textX = x2 + 5;
            textAlign = 'left';
          }
        }

        if (orient === 'horizontal') {
          x2 = x1;
          textX = x2;
        } else {
          y2 = y1;
          textY = y2;
        }

        linePoints = [[x1, y1], [x2, y2]];
      }

      layout.label = {
        linePoints: linePoints,
        x: textX,
        y: textY,
        verticalAlign: 'middle',
        textAlign: textAlign,
        inside: isLabelInside
      };
    });
  }

  function funnelLayout(ecModel, api) {
    ecModel.eachSeriesByType('funnel', function (seriesModel) {
      var data = seriesModel.getData();
      var valueDim = data.mapDimension('value');
      var sort = seriesModel.get('sort');
      var viewRect = getViewRect$3(seriesModel, api);
      var orient = seriesModel.get('orient');
      var viewWidth = viewRect.width;
      var viewHeight = viewRect.height;
      var indices = getSortedIndices(data, sort);
      var x = viewRect.x;
      var y = viewRect.y;
      var sizeExtent = orient === 'horizontal' ? [parsePercent$2(seriesModel.get('minSize'), viewHeight), parsePercent$2(seriesModel.get('maxSize'), viewHeight)] : [parsePercent$2(seriesModel.get('minSize'), viewWidth), parsePercent$2(seriesModel.get('maxSize'), viewWidth)];
      var dataExtent = data.getDataExtent(valueDim);
      var min = seriesModel.get('min');
      var max = seriesModel.get('max');

      if (min == null) {
        min = Math.min(dataExtent[0], 0);
      }

      if (max == null) {
        max = dataExtent[1];
      }

      var funnelAlign = seriesModel.get('funnelAlign');
      var gap = seriesModel.get('gap');
      var viewSize = orient === 'horizontal' ? viewWidth : viewHeight;
      var itemSize = (viewSize - gap * (data.count() - 1)) / data.count();

      var getLinePoints = function (idx, offset) {
        if (orient === 'horizontal') {
          var val_1 = data.get(valueDim, idx) || 0;
          var itemHeight = linearMap(val_1, [min, max], sizeExtent, true);
          var y0 = void 0;

          switch (funnelAlign) {
            case 'top':
              y0 = y;
              break;

            case 'center':
              y0 = y + (viewHeight - itemHeight) / 2;
              break;

            case 'bottom':
              y0 = y + (viewHeight - itemHeight);
              break;
          }

          return [[offset, y0], [offset, y0 + itemHeight]];
        }

        var val = data.get(valueDim, idx) || 0;
        var itemWidth = linearMap(val, [min, max], sizeExtent, true);
        var x0;

        switch (funnelAlign) {
          case 'left':
            x0 = x;
            break;

          case 'center':
            x0 = x + (viewWidth - itemWidth) / 2;
            break;

          case 'right':
            x0 = x + viewWidth - itemWidth;
            break;
        }

        return [[x0, offset], [x0 + itemWidth, offset]];
      };

      if (sort === 'ascending') {
        itemSize = -itemSize;
        gap = -gap;

        if (orient === 'horizontal') {
          x += viewWidth;
        } else {
          y += viewHeight;
        }

        indices = indices.reverse();
      }

      for (var i = 0; i < indices.length; i++) {
        var idx = indices[i];
        var nextIdx = indices[i + 1];
        var itemModel = data.getItemModel(idx);

        if (orient === 'horizontal') {
          var width = itemModel.get(['itemStyle', 'width']);

          if (width == null) {
            width = itemSize;
          } else {
            width = parsePercent$2(width, viewWidth);

            if (sort === 'ascending') {
              width = -width;
            }
          }

          var start = getLinePoints(idx, x);
          var end = getLinePoints(nextIdx, x + width);
          x += width + gap;
          data.setItemLayout(idx, {
            points: start.concat(end.slice().reverse())
          });
        } else {
          var height = itemModel.get(['itemStyle', 'height']);

          if (height == null) {
            height = itemSize;
          } else {
            height = parsePercent$2(height, viewHeight);

            if (sort === 'ascending') {
              height = -height;
            }
          }

          var start = getLinePoints(idx, y);
          var end = getLinePoints(nextIdx, y + height);
          y += height + gap;
          data.setItemLayout(idx, {
            points: start.concat(end.slice().reverse())
          });
        }
      }

      labelLayout(data);
    });
  }

  registerLayout(funnelLayout);
  registerProcessor(dataFilter('funnel'));

  function parallelPreprocessor(option) {
    createParallelIfNeeded(option);
    mergeAxisOptionFromParallel(option);
  }

  function createParallelIfNeeded(option) {
    if (option.parallel) {
      return;
    }

    var hasParallelSeries = false;
    each(option.series, function (seriesOpt) {
      if (seriesOpt && seriesOpt.type === 'parallel') {
        hasParallelSeries = true;
      }
    });

    if (hasParallelSeries) {
      option.parallel = [{}];
    }
  }

  function mergeAxisOptionFromParallel(option) {
    var axes = normalizeToArray(option.parallelAxis);
    each(axes, function (axisOption) {
      if (!isObject(axisOption)) {
        return;
      }

      var parallelIndex = axisOption.parallelIndex || 0;
      var parallelOption = normalizeToArray(option.parallel)[parallelIndex];

      if (parallelOption && parallelOption.parallelAxisDefault) {
        merge(axisOption, parallelOption.parallelAxisDefault, false);
      }
    });
  }

  var ParallelAxis = function (_super) {
    __extends(ParallelAxis, _super);

    function ParallelAxis(dim, scale, coordExtent, axisType, axisIndex) {
      var _this = _super.call(this, dim, scale, coordExtent) || this;

      _this.type = axisType || 'value';
      _this.axisIndex = axisIndex;
      return _this;
    }

    ParallelAxis.prototype.isHorizontal = function () {
      return this.coordinateSystem.getModel().get('layout') !== 'horizontal';
    };

    return ParallelAxis;
  }(Axis);

  function sliderMove(delta, handleEnds, extent, handleIndex, minSpan, maxSpan) {
    delta = delta || 0;
    var extentSpan = extent[1] - extent[0];

    if (minSpan != null) {
      minSpan = restrict(minSpan, [0, extentSpan]);
    }

    if (maxSpan != null) {
      maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0);
    }

    if (handleIndex === 'all') {
      var handleSpan = Math.abs(handleEnds[1] - handleEnds[0]);
      handleSpan = restrict(handleSpan, [0, extentSpan]);
      minSpan = maxSpan = restrict(handleSpan, [minSpan, maxSpan]);
      handleIndex = 0;
    }

    handleEnds[0] = restrict(handleEnds[0], extent);
    handleEnds[1] = restrict(handleEnds[1], extent);
    var originalDistSign = getSpanSign(handleEnds, handleIndex);
    handleEnds[handleIndex] += delta;
    var extentMinSpan = minSpan || 0;
    var realExtent = extent.slice();
    originalDistSign.sign < 0 ? realExtent[0] += extentMinSpan : realExtent[1] -= extentMinSpan;
    handleEnds[handleIndex] = restrict(handleEnds[handleIndex], realExtent);
    var currDistSign;
    currDistSign = getSpanSign(handleEnds, handleIndex);

    if (minSpan != null && (currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan)) {
      handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan;
    }

    currDistSign = getSpanSign(handleEnds, handleIndex);

    if (maxSpan != null && currDistSign.span > maxSpan) {
      handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan;
    }

    return handleEnds;
  }

  function getSpanSign(handleEnds, handleIndex) {
    var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex];
    return {
      span: Math.abs(dist),
      sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1
    };
  }

  function restrict(value, extend) {
    return Math.min(extend[1] != null ? extend[1] : Infinity, Math.max(extend[0] != null ? extend[0] : -Infinity, value));
  }

  var each$6 = each;
  var mathMin$8 = Math.min;
  var mathMax$8 = Math.max;
  var mathFloor$2 = Math.floor;
  var mathCeil$1 = Math.ceil;
  var round$2 = round$1;
  var PI$8 = Math.PI;

  var Parallel = function () {
    function Parallel(parallelModel, ecModel, api) {
      this.type = 'parallel';
      this._axesMap = createHashMap();
      this._axesLayout = {};
      this.dimensions = parallelModel.dimensions;
      this._model = parallelModel;

      this._init(parallelModel, ecModel, api);
    }

    Parallel.prototype._init = function (parallelModel, ecModel, api) {
      var dimensions = parallelModel.dimensions;
      var parallelAxisIndex = parallelModel.parallelAxisIndex;
      each$6(dimensions, function (dim, idx) {
        var axisIndex = parallelAxisIndex[idx];
        var axisModel = ecModel.getComponent('parallelAxis', axisIndex);

        var axis = this._axesMap.set(dim, new ParallelAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisIndex));

        var isCategory = axis.type === 'category';
        axis.onBand = isCategory && axisModel.get('boundaryGap');
        axis.inverse = axisModel.get('inverse');
        axisModel.axis = axis;
        axis.model = axisModel;
        axis.coordinateSystem = axisModel.coordinateSystem = this;
      }, this);
    };

    Parallel.prototype.update = function (ecModel, api) {
      this._updateAxesFromSeries(this._model, ecModel);
    };

    Parallel.prototype.containPoint = function (point) {
      var layoutInfo = this._makeLayoutInfo();

      var axisBase = layoutInfo.axisBase;
      var layoutBase = layoutInfo.layoutBase;
      var pixelDimIndex = layoutInfo.pixelDimIndex;
      var pAxis = point[1 - pixelDimIndex];
      var pLayout = point[pixelDimIndex];
      return pAxis >= axisBase && pAxis <= axisBase + layoutInfo.axisLength && pLayout >= layoutBase && pLayout <= layoutBase + layoutInfo.layoutLength;
    };

    Parallel.prototype.getModel = function () {
      return this._model;
    };

    Parallel.prototype._updateAxesFromSeries = function (parallelModel, ecModel) {
      ecModel.eachSeries(function (seriesModel) {
        if (!parallelModel.contains(seriesModel, ecModel)) {
          return;
        }

        var data = seriesModel.getData();
        each$6(this.dimensions, function (dim) {
          var axis = this._axesMap.get(dim);

          axis.scale.unionExtentFromData(data, data.mapDimension(dim));
          niceScaleExtent(axis.scale, axis.model);
        }, this);
      }, this);
    };

    Parallel.prototype.resize = function (parallelModel, api) {
      this._rect = getLayoutRect(parallelModel.getBoxLayoutParams(), {
        width: api.getWidth(),
        height: api.getHeight()
      });

      this._layoutAxes();
    };

    Parallel.prototype.getRect = function () {
      return this._rect;
    };

    Parallel.prototype._makeLayoutInfo = function () {
      var parallelModel = this._model;
      var rect = this._rect;
      var xy = ['x', 'y'];
      var wh = ['width', 'height'];
      var layout = parallelModel.get('layout');
      var pixelDimIndex = layout === 'horizontal' ? 0 : 1;
      var layoutLength = rect[wh[pixelDimIndex]];
      var layoutExtent = [0, layoutLength];
      var axisCount = this.dimensions.length;
      var axisExpandWidth = restrict$1(parallelModel.get('axisExpandWidth'), layoutExtent);
      var axisExpandCount = restrict$1(parallelModel.get('axisExpandCount') || 0, [0, axisCount]);
      var axisExpandable = parallelModel.get('axisExpandable') && axisCount > 3 && axisCount > axisExpandCount && axisExpandCount > 1 && axisExpandWidth > 0 && layoutLength > 0;
      var axisExpandWindow = parallelModel.get('axisExpandWindow');
      var winSize;

      if (!axisExpandWindow) {
        winSize = restrict$1(axisExpandWidth * (axisExpandCount - 1), layoutExtent);
        var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor$2(axisCount / 2);
        axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2];
        axisExpandWindow[1] = axisExpandWindow[0] + winSize;
      } else {
        winSize = restrict$1(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent);
        axisExpandWindow[1] = axisExpandWindow[0] + winSize;
      }

      var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount);
      axisCollapseWidth < 3 && (axisCollapseWidth = 0);
      var winInnerIndices = [mathFloor$2(round$2(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, mathCeil$1(round$2(axisExpandWindow[1] / axisExpandWidth, 1)) - 1];
      var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0];
      return {
        layout: layout,
        pixelDimIndex: pixelDimIndex,
        layoutBase: rect[xy[pixelDimIndex]],
        layoutLength: layoutLength,
        axisBase: rect[xy[1 - pixelDimIndex]],
        axisLength: rect[wh[1 - pixelDimIndex]],
        axisExpandable: axisExpandable,
        axisExpandWidth: axisExpandWidth,
        axisCollapseWidth: axisCollapseWidth,
        axisExpandWindow: axisExpandWindow,
        axisCount: axisCount,
        winInnerIndices: winInnerIndices,
        axisExpandWindow0Pos: axisExpandWindow0Pos
      };
    };

    Parallel.prototype._layoutAxes = function () {
      var rect = this._rect;
      var axes = this._axesMap;
      var dimensions = this.dimensions;

      var layoutInfo = this._makeLayoutInfo();

      var layout = layoutInfo.layout;
      axes.each(function (axis) {
        var axisExtent = [0, layoutInfo.axisLength];
        var idx = axis.inverse ? 1 : 0;
        axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
      });
      each$6(dimensions, function (dim, idx) {
        var posInfo = (layoutInfo.axisExpandable ? layoutAxisWithExpand : layoutAxisWithoutExpand)(idx, layoutInfo);
        var positionTable = {
          horizontal: {
            x: posInfo.position,
            y: layoutInfo.axisLength
          },
          vertical: {
            x: 0,
            y: posInfo.position
          }
        };
        var rotationTable = {
          horizontal: PI$8 / 2,
          vertical: 0
        };
        var position = [positionTable[layout].x + rect.x, positionTable[layout].y + rect.y];
        var rotation = rotationTable[layout];
        var transform = create$1();
        rotate(transform, transform, rotation);
        translate(transform, transform, position);
        this._axesLayout[dim] = {
          position: position,
          rotation: rotation,
          transform: transform,
          axisNameAvailableWidth: posInfo.axisNameAvailableWidth,
          axisLabelShow: posInfo.axisLabelShow,
          nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth,
          tickDirection: 1,
          labelDirection: 1
        };
      }, this);
    };

    Parallel.prototype.getAxis = function (dim) {
      return this._axesMap.get(dim);
    };

    Parallel.prototype.dataToPoint = function (value, dim) {
      return this.axisCoordToPoint(this._axesMap.get(dim).dataToCoord(value), dim);
    };

    Parallel.prototype.eachActiveState = function (data, callback, start, end) {
      start == null && (start = 0);
      end == null && (end = data.count());
      var axesMap = this._axesMap;
      var dimensions = this.dimensions;
      var dataDimensions = [];
      var axisModels = [];
      each(dimensions, function (axisDim) {
        dataDimensions.push(data.mapDimension(axisDim));
        axisModels.push(axesMap.get(axisDim).model);
      });
      var hasActiveSet = this.hasAxisBrushed();

      for (var dataIndex = start; dataIndex < end; dataIndex++) {
        var activeState = void 0;

        if (!hasActiveSet) {
          activeState = 'normal';
        } else {
          activeState = 'active';
          var values = data.getValues(dataDimensions, dataIndex);

          for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
            var state = axisModels[j].getActiveState(values[j]);

            if (state === 'inactive') {
              activeState = 'inactive';
              break;
            }
          }
        }

        callback(activeState, dataIndex);
      }
    };

    Parallel.prototype.hasAxisBrushed = function () {
      var dimensions = this.dimensions;
      var axesMap = this._axesMap;
      var hasActiveSet = false;

      for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
        if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') {
          hasActiveSet = true;
        }
      }

      return hasActiveSet;
    };

    Parallel.prototype.axisCoordToPoint = function (coord, dim) {
      var axisLayout = this._axesLayout[dim];
      return applyTransform$1([coord, 0], axisLayout.transform);
    };

    Parallel.prototype.getAxisLayout = function (dim) {
      return clone(this._axesLayout[dim]);
    };

    Parallel.prototype.getSlidedAxisExpandWindow = function (point) {
      var layoutInfo = this._makeLayoutInfo();

      var pixelDimIndex = layoutInfo.pixelDimIndex;
      var axisExpandWindow = layoutInfo.axisExpandWindow.slice();
      var winSize = axisExpandWindow[1] - axisExpandWindow[0];
      var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)];

      if (!this.containPoint(point)) {
        return {
          behavior: 'none',
          axisExpandWindow: axisExpandWindow
        };
      }

      var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos;
      var delta;
      var behavior = 'slide';
      var axisCollapseWidth = layoutInfo.axisCollapseWidth;

      var triggerArea = this._model.get('axisExpandSlideTriggerArea');

      var useJump = triggerArea[0] != null;

      if (axisCollapseWidth) {
        if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) {
          behavior = 'jump';
          delta = pointCoord - winSize * triggerArea[2];
        } else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) {
          behavior = 'jump';
          delta = pointCoord - winSize * (1 - triggerArea[2]);
        } else {
          (delta = pointCoord - winSize * triggerArea[1]) >= 0 && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 && (delta = 0);
        }

        delta *= layoutInfo.axisExpandWidth / axisCollapseWidth;
        delta ? sliderMove(delta, axisExpandWindow, extent, 'all') : behavior = 'none';
      } else {
        var winSize2 = axisExpandWindow[1] - axisExpandWindow[0];
        var pos = extent[1] * pointCoord / winSize2;
        axisExpandWindow = [mathMax$8(0, pos - winSize2 / 2)];
        axisExpandWindow[1] = mathMin$8(extent[1], axisExpandWindow[0] + winSize2);
        axisExpandWindow[0] = axisExpandWindow[1] - winSize2;
      }

      return {
        axisExpandWindow: axisExpandWindow,
        behavior: behavior
      };
    };

    return Parallel;
  }();

  function restrict$1(len, extent) {
    return mathMin$8(mathMax$8(len, extent[0]), extent[1]);
  }

  function layoutAxisWithoutExpand(axisIndex, layoutInfo) {
    var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1);
    return {
      position: step * axisIndex,
      axisNameAvailableWidth: step,
      axisLabelShow: true
    };
  }

  function layoutAxisWithExpand(axisIndex, layoutInfo) {
    var layoutLength = layoutInfo.layoutLength;
    var axisExpandWidth = layoutInfo.axisExpandWidth;
    var axisCount = layoutInfo.axisCount;
    var axisCollapseWidth = layoutInfo.axisCollapseWidth;
    var winInnerIndices = layoutInfo.winInnerIndices;
    var position;
    var axisNameAvailableWidth = axisCollapseWidth;
    var axisLabelShow = false;
    var nameTruncateMaxWidth;

    if (axisIndex < winInnerIndices[0]) {
      position = axisIndex * axisCollapseWidth;
      nameTruncateMaxWidth = axisCollapseWidth;
    } else if (axisIndex <= winInnerIndices[1]) {
      position = layoutInfo.axisExpandWindow0Pos + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0];
      axisNameAvailableWidth = axisExpandWidth;
      axisLabelShow = true;
    } else {
      position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth;
      nameTruncateMaxWidth = axisCollapseWidth;
    }

    return {
      position: position,
      axisNameAvailableWidth: axisNameAvailableWidth,
      axisLabelShow: axisLabelShow,
      nameTruncateMaxWidth: nameTruncateMaxWidth
    };
  }

  function create$2(ecModel, api) {
    var coordSysList = [];
    ecModel.eachComponent('parallel', function (parallelModel, idx) {
      var coordSys = new Parallel(parallelModel, ecModel, api);
      coordSys.name = 'parallel_' + idx;
      coordSys.resize(parallelModel, api);
      parallelModel.coordinateSystem = coordSys;
      coordSys.model = parallelModel;
      coordSysList.push(coordSys);
    });
    ecModel.eachSeries(function (seriesModel) {
      if (seriesModel.get('coordinateSystem') === 'parallel') {
        var parallelModel = seriesModel.getReferringComponents('parallel', SINGLE_REFERRING).models[0];
        seriesModel.coordinateSystem = parallelModel.coordinateSystem;
      }
    });
    return coordSysList;
  }

  CoordinateSystemManager.register('parallel', {
    create: create$2
  });

  var ParallelAxisModel = function (_super) {
    __extends(ParallelAxisModel, _super);

    function ParallelAxisModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelAxisModel.type;
      _this.activeIntervals = [];
      return _this;
    }

    ParallelAxisModel.prototype.getAreaSelectStyle = function () {
      return makeStyleMapper([['fill', 'color'], ['lineWidth', 'borderWidth'], ['stroke', 'borderColor'], ['width', 'width'], ['opacity', 'opacity']])(this.getModel('areaSelectStyle'));
    };

    ParallelAxisModel.prototype.setActiveIntervals = function (intervals) {
      var activeIntervals = this.activeIntervals = clone(intervals);

      if (activeIntervals) {
        for (var i = activeIntervals.length - 1; i >= 0; i--) {
          asc(activeIntervals[i]);
        }
      }
    };

    ParallelAxisModel.prototype.getActiveState = function (value) {
      var activeIntervals = this.activeIntervals;

      if (!activeIntervals.length) {
        return 'normal';
      }

      if (value == null || isNaN(+value)) {
        return 'inactive';
      }

      if (activeIntervals.length === 1) {
        var interval = activeIntervals[0];

        if (interval[0] <= value && value <= interval[1]) {
          return 'active';
        }
      } else {
        for (var i = 0, len = activeIntervals.length; i < len; i++) {
          if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) {
            return 'active';
          }
        }
      }

      return 'inactive';
    };

    return ParallelAxisModel;
  }(ComponentModel);

  var defaultOption$1 = {
    type: 'value',
    areaSelectStyle: {
      width: 20,
      borderWidth: 1,
      borderColor: 'rgba(160,197,232)',
      color: 'rgba(160,197,232)',
      opacity: 0.3
    },
    realtime: true,
    z: 10
  };
  ComponentModel.registerClass(ParallelAxisModel);
  mixin(ParallelAxisModel, AxisModelCommonMixin);
  axisModelCreator('parallel', ParallelAxisModel, defaultOption$1);

  var ParallelModel = function (_super) {
    __extends(ParallelModel, _super);

    function ParallelModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelModel.type;
      return _this;
    }

    ParallelModel.prototype.init = function () {
      _super.prototype.init.apply(this, arguments);

      this.mergeOption({});
    };

    ParallelModel.prototype.mergeOption = function (newOption) {
      var thisOption = this.option;
      newOption && merge(thisOption, newOption, true);

      this._initDimensions();
    };

    ParallelModel.prototype.contains = function (model, ecModel) {
      var parallelIndex = model.get('parallelIndex');
      return parallelIndex != null && ecModel.getComponent('parallel', parallelIndex) === this;
    };

    ParallelModel.prototype.setAxisExpand = function (opt) {
      each(['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'], function (name) {
        if (opt.hasOwnProperty(name)) {
          this.option[name] = opt[name];
        }
      }, this);
    };

    ParallelModel.prototype._initDimensions = function () {
      var dimensions = this.dimensions = [];
      var parallelAxisIndex = this.parallelAxisIndex = [];
      var axisModels = filter(this.ecModel.queryComponents({
        mainType: 'parallelAxis'
      }), function (axisModel) {
        return (axisModel.get('parallelIndex') || 0) === this.componentIndex;
      }, this);
      each(axisModels, function (axisModel) {
        dimensions.push('dim' + axisModel.get('dim'));
        parallelAxisIndex.push(axisModel.componentIndex);
      });
    };

    ParallelModel.type = 'parallel';
    ParallelModel.dependencies = ['parallelAxis'];
    ParallelModel.layoutMode = 'box';
    ParallelModel.defaultOption = {
      zlevel: 0,
      z: 0,
      left: 80,
      top: 60,
      right: 80,
      bottom: 60,
      layout: 'horizontal',
      axisExpandable: false,
      axisExpandCenter: null,
      axisExpandCount: 0,
      axisExpandWidth: 50,
      axisExpandRate: 17,
      axisExpandDebounce: 50,
      axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4],
      axisExpandTriggerOn: 'click',
      parallelAxisDefault: null
    };
    return ParallelModel;
  }(ComponentModel);

  ComponentModel.registerClass(ParallelModel);
  var actionInfo$1 = {
    type: 'axisAreaSelect',
    event: 'axisAreaSelected'
  };
  registerAction(actionInfo$1, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'parallelAxis',
      query: payload
    }, function (parallelAxisModel) {
      parallelAxisModel.axis.model.setActiveIntervals(payload.intervals);
    });
  });
  registerAction('parallelAxisExpand', function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'parallel',
      query: payload
    }, function (parallelModel) {
      parallelModel.setAxisExpand(payload);
    });
  });
  var BRUSH_PANEL_GLOBAL = true;
  var mathMin$9 = Math.min;
  var mathMax$9 = Math.max;
  var mathPow$2 = Math.pow;
  var COVER_Z = 10000;
  var UNSELECT_THRESHOLD = 6;
  var MIN_RESIZE_LINE_WIDTH = 6;
  var MUTEX_RESOURCE_KEY = 'globalPan';
  var DIRECTION_MAP = {
    w: [0, 0],
    e: [0, 1],
    n: [1, 0],
    s: [1, 1]
  };
  var CURSOR_MAP = {
    w: 'ew',
    e: 'ew',
    n: 'ns',
    s: 'ns',
    ne: 'nesw',
    sw: 'nesw',
    nw: 'nwse',
    se: 'nwse'
  };
  var DEFAULT_BRUSH_OPT = {
    brushStyle: {
      lineWidth: 2,
      stroke: 'rgba(210,219,238,0.3)',
      fill: '#D2DBEE'
    },
    transformable: true,
    brushMode: 'single',
    removeOnClick: false
  };
  var baseUID = 0;

  var BrushController = function (_super) {
    __extends(BrushController, _super);

    function BrushController(zr) {
      var _this = _super.call(this) || this;

      _this._track = [];
      _this._covers = [];
      _this._handlers = {};

      if (true) {
        assert(zr);
      }

      _this._zr = zr;
      _this.group = new Group();
      _this._uid = 'brushController_' + baseUID++;
      each(pointerHandlers, function (handler, eventName) {
        this._handlers[eventName] = bind(handler, this);
      }, _this);
      return _this;
    }

    BrushController.prototype.enableBrush = function (brushOption) {
      if (true) {
        assert(this._mounted);
      }

      this._brushType && this._doDisableBrush();
      brushOption.brushType && this._doEnableBrush(brushOption);
      return this;
    };

    BrushController.prototype._doEnableBrush = function (brushOption) {
      var zr = this._zr;

      if (!this._enableGlobalPan) {
        take(zr, MUTEX_RESOURCE_KEY, this._uid);
      }

      each(this._handlers, function (handler, eventName) {
        zr.on(eventName, handler);
      });
      this._brushType = brushOption.brushType;
      this._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
    };

    BrushController.prototype._doDisableBrush = function () {
      var zr = this._zr;
      release(zr, MUTEX_RESOURCE_KEY, this._uid);
      each(this._handlers, function (handler, eventName) {
        zr.off(eventName, handler);
      });
      this._brushType = this._brushOption = null;
    };

    BrushController.prototype.setPanels = function (panelOpts) {
      if (panelOpts && panelOpts.length) {
        var panels_1 = this._panels = {};
        each(panelOpts, function (panelOpts) {
          panels_1[panelOpts.panelId] = clone(panelOpts);
        });
      } else {
        this._panels = null;
      }

      return this;
    };

    BrushController.prototype.mount = function (opt) {
      opt = opt || {};

      if (true) {
        this._mounted = true;
      }

      this._enableGlobalPan = opt.enableGlobalPan;
      var thisGroup = this.group;

      this._zr.add(thisGroup);

      thisGroup.attr({
        x: opt.x || 0,
        y: opt.y || 0,
        rotation: opt.rotation || 0,
        scaleX: opt.scaleX || 1,
        scaleY: opt.scaleY || 1
      });
      this._transform = thisGroup.getLocalTransform();
      return this;
    };

    BrushController.prototype.updateCovers = function (coverConfigList) {
      if (true) {
        assert(this._mounted);
      }

      coverConfigList = map(coverConfigList, function (coverConfig) {
        return merge(clone(DEFAULT_BRUSH_OPT), coverConfig, true);
      });
      var tmpIdPrefix = '\0-brush-index-';
      var oldCovers = this._covers;
      var newCovers = this._covers = [];
      var controller = this;
      var creatingCover = this._creatingCover;
      new DataDiffer(oldCovers, coverConfigList, oldGetKey, getKey).add(addOrUpdate).update(addOrUpdate).remove(remove).execute();
      return this;

      function getKey(brushOption, index) {
        return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + '-' + brushOption.brushType;
      }

      function oldGetKey(cover, index) {
        return getKey(cover.__brushOption, index);
      }

      function addOrUpdate(newIndex, oldIndex) {
        var newBrushInternal = coverConfigList[newIndex];

        if (oldIndex != null && oldCovers[oldIndex] === creatingCover) {
          newCovers[newIndex] = oldCovers[oldIndex];
        } else {
          var cover = newCovers[newIndex] = oldIndex != null ? (oldCovers[oldIndex].__brushOption = newBrushInternal, oldCovers[oldIndex]) : endCreating(controller, createCover(controller, newBrushInternal));
          updateCoverAfterCreation(controller, cover);
        }
      }

      function remove(oldIndex) {
        if (oldCovers[oldIndex] !== creatingCover) {
          controller.group.remove(oldCovers[oldIndex]);
        }
      }
    };

    BrushController.prototype.unmount = function () {
      if (true) {
        if (!this._mounted) {
          return;
        }
      }

      this.enableBrush(false);
      clearCovers(this);

      this._zr.remove(this.group);

      if (true) {
        this._mounted = false;
      }

      return this;
    };

    BrushController.prototype.dispose = function () {
      this.unmount();
      this.off();
    };

    return BrushController;
  }(Eventful);

  function createCover(controller, brushOption) {
    var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
    cover.__brushOption = brushOption;
    updateZ(cover, brushOption);
    controller.group.add(cover);
    return cover;
  }

  function endCreating(controller, creatingCover) {
    var coverRenderer = getCoverRenderer(creatingCover);

    if (coverRenderer.endCreating) {
      coverRenderer.endCreating(controller, creatingCover);
      updateZ(creatingCover, creatingCover.__brushOption);
    }

    return creatingCover;
  }

  function updateCoverShape(controller, cover) {
    var brushOption = cover.__brushOption;
    getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption);
  }

  function updateZ(cover, brushOption) {
    var z = brushOption.z;
    z == null && (z = COVER_Z);
    cover.traverse(function (el) {
      el.z = z;
      el.z2 = z;
    });
  }

  function updateCoverAfterCreation(controller, cover) {
    getCoverRenderer(cover).updateCommon(controller, cover);
    updateCoverShape(controller, cover);
  }

  function getCoverRenderer(cover) {
    return coverRenderers[cover.__brushOption.brushType];
  }

  function getPanelByPoint(controller, e, localCursorPoint) {
    var panels = controller._panels;

    if (!panels) {
      return BRUSH_PANEL_GLOBAL;
    }

    var panel;
    var transform = controller._transform;
    each(panels, function (pn) {
      pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn);
    });
    return panel;
  }

  function getPanelByCover(controller, cover) {
    var panels = controller._panels;

    if (!panels) {
      return BRUSH_PANEL_GLOBAL;
    }

    var panelId = cover.__brushOption.panelId;
    return panelId != null ? panels[panelId] : BRUSH_PANEL_GLOBAL;
  }

  function clearCovers(controller) {
    var covers = controller._covers;
    var originalLength = covers.length;
    each(covers, function (cover) {
      controller.group.remove(cover);
    }, controller);
    covers.length = 0;
    return !!originalLength;
  }

  function trigger$1(controller, opt) {
    var areas = map(controller._covers, function (cover) {
      var brushOption = cover.__brushOption;
      var range = clone(brushOption.range);
      return {
        brushType: brushOption.brushType,
        panelId: brushOption.panelId,
        range: range
      };
    });
    controller.trigger('brush', {
      areas: areas,
      isEnd: !!opt.isEnd,
      removeOnClick: !!opt.removeOnClick
    });
  }

  function shouldShowCover(controller) {
    var track = controller._track;

    if (!track.length) {
      return false;
    }

    var p2 = track[track.length - 1];
    var p1 = track[0];
    var dx = p2[0] - p1[0];
    var dy = p2[1] - p1[1];
    var dist = mathPow$2(dx * dx + dy * dy, 0.5);
    return dist > UNSELECT_THRESHOLD;
  }

  function getTrackEnds(track) {
    var tail = track.length - 1;
    tail < 0 && (tail = 0);
    return [track[0], track[tail]];
  }

  function createBaseRectCover(rectRangeConverter, controller, brushOption, edgeNameSequences) {
    var cover = new Group();
    cover.add(new Rect({
      name: 'main',
      style: makeStyle(brushOption),
      silent: true,
      draggable: true,
      cursor: 'move',
      drift: curry(driftRect, rectRangeConverter, controller, cover, ['n', 's', 'w', 'e']),
      ondragend: curry(trigger$1, controller, {
        isEnd: true
      })
    }));
    each(edgeNameSequences, function (nameSequence) {
      cover.add(new Rect({
        name: nameSequence.join(''),
        style: {
          opacity: 0
        },
        draggable: true,
        silent: true,
        invisible: true,
        drift: curry(driftRect, rectRangeConverter, controller, cover, nameSequence),
        ondragend: curry(trigger$1, controller, {
          isEnd: true
        })
      }));
    });
    return cover;
  }

  function updateBaseRect(controller, cover, localRange, brushOption) {
    var lineWidth = brushOption.brushStyle.lineWidth || 0;
    var handleSize = mathMax$9(lineWidth, MIN_RESIZE_LINE_WIDTH);
    var x = localRange[0][0];
    var y = localRange[1][0];
    var xa = x - lineWidth / 2;
    var ya = y - lineWidth / 2;
    var x2 = localRange[0][1];
    var y2 = localRange[1][1];
    var x2a = x2 - handleSize + lineWidth / 2;
    var y2a = y2 - handleSize + lineWidth / 2;
    var width = x2 - x;
    var height = y2 - y;
    var widtha = width + lineWidth;
    var heighta = height + lineWidth;
    updateRectShape(controller, cover, 'main', x, y, width, height);

    if (brushOption.transformable) {
      updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta);
      updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta);
      updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize);
      updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize);
      updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize);
      updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize);
      updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize);
      updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize);
    }
  }

  function updateCommon(controller, cover) {
    var brushOption = cover.__brushOption;
    var transformable = brushOption.transformable;
    var mainEl = cover.childAt(0);
    mainEl.useStyle(makeStyle(brushOption));
    mainEl.attr({
      silent: !transformable,
      cursor: transformable ? 'move' : 'default'
    });
    each([['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']], function (nameSequence) {
      var el = cover.childOfName(nameSequence.join(''));
      var globalDir = nameSequence.length === 1 ? getGlobalDirection1(controller, nameSequence[0]) : getGlobalDirection2(controller, nameSequence);
      el && el.attr({
        silent: !transformable,
        invisible: !transformable,
        cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null
      });
    });
  }

  function updateRectShape(controller, cover, name, x, y, w, h) {
    var el = cover.childOfName(name);
    el && el.setShape(pointsToRect(clipByPanel(controller, cover, [[x, y], [x + w, y + h]])));
  }

  function makeStyle(brushOption) {
    return defaults({
      strokeNoScale: true
    }, brushOption.brushStyle);
  }

  function formatRectRange(x, y, x2, y2) {
    var min = [mathMin$9(x, x2), mathMin$9(y, y2)];
    var max = [mathMax$9(x, x2), mathMax$9(y, y2)];
    return [[min[0], max[0]], [min[1], max[1]]];
  }

  function getTransform$1(controller) {
    return getTransform(controller.group);
  }

  function getGlobalDirection1(controller, localDirName) {
    var map = {
      w: 'left',
      e: 'right',
      n: 'top',
      s: 'bottom'
    };
    var inverseMap = {
      left: 'w',
      right: 'e',
      top: 'n',
      bottom: 's'
    };
    var dir = transformDirection(map[localDirName], getTransform$1(controller));
    return inverseMap[dir];
  }

  function getGlobalDirection2(controller, localDirNameSeq) {
    var globalDir = [getGlobalDirection1(controller, localDirNameSeq[0]), getGlobalDirection1(controller, localDirNameSeq[1])];
    (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse();
    return globalDir.join('');
  }

  function driftRect(rectRangeConverter, controller, cover, dirNameSequence, dx, dy) {
    var brushOption = cover.__brushOption;
    var rectRange = rectRangeConverter.toRectRange(brushOption.range);
    var localDelta = toLocalDelta(controller, dx, dy);
    each(dirNameSequence, function (dirName) {
      var ind = DIRECTION_MAP[dirName];
      rectRange[ind[0]][ind[1]] += localDelta[ind[0]];
    });
    brushOption.range = rectRangeConverter.fromRectRange(formatRectRange(rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]));
    updateCoverAfterCreation(controller, cover);
    trigger$1(controller, {
      isEnd: false
    });
  }

  function driftPolygon(controller, cover, dx, dy) {
    var range = cover.__brushOption.range;
    var localDelta = toLocalDelta(controller, dx, dy);
    each(range, function (point) {
      point[0] += localDelta[0];
      point[1] += localDelta[1];
    });
    updateCoverAfterCreation(controller, cover);
    trigger$1(controller, {
      isEnd: false
    });
  }

  function toLocalDelta(controller, dx, dy) {
    var thisGroup = controller.group;
    var localD = thisGroup.transformCoordToLocal(dx, dy);
    var localZero = thisGroup.transformCoordToLocal(0, 0);
    return [localD[0] - localZero[0], localD[1] - localZero[1]];
  }

  function clipByPanel(controller, cover, data) {
    var panel = getPanelByCover(controller, cover);
    return panel && panel !== BRUSH_PANEL_GLOBAL ? panel.clipPath(data, controller._transform) : clone(data);
  }

  function pointsToRect(points) {
    var xmin = mathMin$9(points[0][0], points[1][0]);
    var ymin = mathMin$9(points[0][1], points[1][1]);
    var xmax = mathMax$9(points[0][0], points[1][0]);
    var ymax = mathMax$9(points[0][1], points[1][1]);
    return {
      x: xmin,
      y: ymin,
      width: xmax - xmin,
      height: ymax - ymin
    };
  }

  function resetCursor(controller, e, localCursorPoint) {
    if (!controller._brushType || isOutsideZrArea(controller, e.offsetX, e.offsetY)) {
      return;
    }

    var zr = controller._zr;
    var covers = controller._covers;
    var currPanel = getPanelByPoint(controller, e, localCursorPoint);

    if (!controller._dragging) {
      for (var i = 0; i < covers.length; i++) {
        var brushOption = covers[i].__brushOption;

        if (currPanel && (currPanel === BRUSH_PANEL_GLOBAL || brushOption.panelId === currPanel.panelId) && coverRenderers[brushOption.brushType].contain(covers[i], localCursorPoint[0], localCursorPoint[1])) {
          return;
        }
      }
    }

    currPanel && zr.setCursorStyle('crosshair');
  }

  function preventDefault(e) {
    var rawE = e.event;
    rawE.preventDefault && rawE.preventDefault();
  }

  function mainShapeContain(cover, x, y) {
    return cover.childOfName('main').contain(x, y);
  }

  function updateCoverByMouse(controller, e, localCursorPoint, isEnd) {
    var creatingCover = controller._creatingCover;
    var panel = controller._creatingPanel;
    var thisBrushOption = controller._brushOption;
    var eventParams;

    controller._track.push(localCursorPoint.slice());

    if (shouldShowCover(controller) || creatingCover) {
      if (panel && !creatingCover) {
        thisBrushOption.brushMode === 'single' && clearCovers(controller);
        var brushOption = clone(thisBrushOption);
        brushOption.brushType = determineBrushType(brushOption.brushType, panel);
        brushOption.panelId = panel === BRUSH_PANEL_GLOBAL ? null : panel.panelId;
        creatingCover = controller._creatingCover = createCover(controller, brushOption);

        controller._covers.push(creatingCover);
      }

      if (creatingCover) {
        var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)];
        var coverBrushOption = creatingCover.__brushOption;
        coverBrushOption.range = coverRenderer.getCreatingRange(clipByPanel(controller, creatingCover, controller._track));

        if (isEnd) {
          endCreating(controller, creatingCover);
          coverRenderer.updateCommon(controller, creatingCover);
        }

        updateCoverShape(controller, creatingCover);
        eventParams = {
          isEnd: isEnd
        };
      }
    } else if (isEnd && thisBrushOption.brushMode === 'single' && thisBrushOption.removeOnClick) {
      if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) {
        eventParams = {
          isEnd: isEnd,
          removeOnClick: true
        };
      }
    }

    return eventParams;
  }

  function determineBrushType(brushType, panel) {
    if (brushType === 'auto') {
      if (true) {
        assert(panel && panel.defaultBrushType, 'MUST have defaultBrushType when brushType is "atuo"');
      }

      return panel.defaultBrushType;
    }

    return brushType;
  }

  var pointerHandlers = {
    mousedown: function (e) {
      if (this._dragging) {
        handleDragEnd(this, e);
      } else if (!e.target || !e.target.draggable) {
        preventDefault(e);
        var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
        this._creatingCover = null;
        var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint);

        if (panel) {
          this._dragging = true;
          this._track = [localCursorPoint.slice()];
        }
      }
    },
    mousemove: function (e) {
      var x = e.offsetX;
      var y = e.offsetY;
      var localCursorPoint = this.group.transformCoordToLocal(x, y);
      resetCursor(this, e, localCursorPoint);

      if (this._dragging) {
        preventDefault(e);
        var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);
        eventParams && trigger$1(this, eventParams);
      }
    },
    mouseup: function (e) {
      handleDragEnd(this, e);
    }
  };

  function handleDragEnd(controller, e) {
    if (controller._dragging) {
      preventDefault(e);
      var x = e.offsetX;
      var y = e.offsetY;
      var localCursorPoint = controller.group.transformCoordToLocal(x, y);
      var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);
      controller._dragging = false;
      controller._track = [];
      controller._creatingCover = null;
      eventParams && trigger$1(controller, eventParams);
    }
  }

  function isOutsideZrArea(controller, x, y) {
    var zr = controller._zr;
    return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();
  }

  var coverRenderers = {
    lineX: getLineRenderer(0),
    lineY: getLineRenderer(1),
    rect: {
      createCover: function (controller, brushOption) {
        function returnInput(range) {
          return range;
        }

        return createBaseRectCover({
          toRectRange: returnInput,
          fromRectRange: returnInput
        }, controller, brushOption, [['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']]);
      },
      getCreatingRange: function (localTrack) {
        var ends = getTrackEnds(localTrack);
        return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);
      },
      updateCoverShape: function (controller, cover, localRange, brushOption) {
        updateBaseRect(controller, cover, localRange, brushOption);
      },
      updateCommon: updateCommon,
      contain: mainShapeContain
    },
    polygon: {
      createCover: function (controller, brushOption) {
        var cover = new Group();
        cover.add(new Polyline({
          name: 'main',
          style: makeStyle(brushOption),
          silent: true
        }));
        return cover;
      },
      getCreatingRange: function (localTrack) {
        return localTrack;
      },
      endCreating: function (controller, cover) {
        cover.remove(cover.childAt(0));
        cover.add(new Polygon({
          name: 'main',
          draggable: true,
          drift: curry(driftPolygon, controller, cover),
          ondragend: curry(trigger$1, controller, {
            isEnd: true
          })
        }));
      },
      updateCoverShape: function (controller, cover, localRange, brushOption) {
        cover.childAt(0).setShape({
          points: clipByPanel(controller, cover, localRange)
        });
      },
      updateCommon: updateCommon,
      contain: mainShapeContain
    }
  };

  function getLineRenderer(xyIndex) {
    return {
      createCover: function (controller, brushOption) {
        return createBaseRectCover({
          toRectRange: function (range) {
            var rectRange = [range, [0, 100]];
            xyIndex && rectRange.reverse();
            return rectRange;
          },
          fromRectRange: function (rectRange) {
            return rectRange[xyIndex];
          }
        }, controller, brushOption, [[['w'], ['e']], [['n'], ['s']]][xyIndex]);
      },
      getCreatingRange: function (localTrack) {
        var ends = getTrackEnds(localTrack);
        var min = mathMin$9(ends[0][xyIndex], ends[1][xyIndex]);
        var max = mathMax$9(ends[0][xyIndex], ends[1][xyIndex]);
        return [min, max];
      },
      updateCoverShape: function (controller, cover, localRange, brushOption) {
        var otherExtent;
        var panel = getPanelByCover(controller, cover);

        if (panel !== BRUSH_PANEL_GLOBAL && panel.getLinearBrushOtherExtent) {
          otherExtent = panel.getLinearBrushOtherExtent(xyIndex);
        } else {
          var zr = controller._zr;
          otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]];
        }

        var rectRange = [localRange, otherExtent];
        xyIndex && rectRange.reverse();
        updateBaseRect(controller, cover, rectRange, brushOption);
      },
      updateCommon: updateCommon,
      contain: mainShapeContain
    };
  }

  function makeRectPanelClipPath(rect) {
    rect = normalizeRect(rect);
    return function (localPoints) {
      return clipPointsByRect(localPoints, rect);
    };
  }

  function makeLinearBrushOtherExtent(rect, specifiedXYIndex) {
    rect = normalizeRect(rect);
    return function (xyIndex) {
      var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex;
      var brushWidth = idx ? rect.width : rect.height;
      var base = idx ? rect.x : rect.y;
      return [base, base + (brushWidth || 0)];
    };
  }

  function makeRectIsTargetByCursor(rect, api, targetModel) {
    var boundingRect = normalizeRect(rect);
    return function (e, localCursorPoint) {
      return boundingRect.contain(localCursorPoint[0], localCursorPoint[1]) && !onIrrelevantElement(e, api, targetModel);
    };
  }

  function normalizeRect(rect) {
    return BoundingRect.create(rect);
  }

  var elementList = ['axisLine', 'axisTickLabel', 'axisName'];

  var ParallelAxisView = function (_super) {
    __extends(ParallelAxisView, _super);

    function ParallelAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelAxisView.type;
      return _this;
    }

    ParallelAxisView.prototype.init = function (ecModel, api) {
      _super.prototype.init.apply(this, arguments);

      (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this));
    };

    ParallelAxisView.prototype.render = function (axisModel, ecModel, api, payload) {
      if (fromAxisAreaSelect(axisModel, ecModel, payload)) {
        return;
      }

      this.axisModel = axisModel;
      this.api = api;
      this.group.removeAll();
      var oldAxisGroup = this._axisGroup;
      this._axisGroup = new Group();
      this.group.add(this._axisGroup);

      if (!axisModel.get('show')) {
        return;
      }

      var coordSysModel = getCoordSysModel(axisModel, ecModel);
      var coordSys = coordSysModel.coordinateSystem;
      var areaSelectStyle = axisModel.getAreaSelectStyle();
      var areaWidth = areaSelectStyle.width;
      var dim = axisModel.axis.dim;
      var axisLayout = coordSys.getAxisLayout(dim);
      var builderOpt = extend({
        strokeContainThreshold: areaWidth
      }, axisLayout);
      var axisBuilder = new AxisBuilder(axisModel, builderOpt);
      each(elementList, axisBuilder.add, axisBuilder);

      this._axisGroup.add(axisBuilder.getGroup());

      this._refreshBrushController(builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api);

      groupTransition(oldAxisGroup, this._axisGroup, axisModel);
    };

    ParallelAxisView.prototype._refreshBrushController = function (builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api) {
      var extent = axisModel.axis.getExtent();
      var extentLen = extent[1] - extent[0];
      var extra = Math.min(30, Math.abs(extentLen) * 0.1);
      var rect = BoundingRect.create({
        x: extent[0],
        y: -areaWidth / 2,
        width: extentLen,
        height: areaWidth
      });
      rect.x -= extra;
      rect.width += 2 * extra;

      this._brushController.mount({
        enableGlobalPan: true,
        rotation: builderOpt.rotation,
        x: builderOpt.position[0],
        y: builderOpt.position[1]
      }).setPanels([{
        panelId: 'pl',
        clipPath: makeRectPanelClipPath(rect),
        isTargetByCursor: makeRectIsTargetByCursor(rect, api, coordSysModel),
        getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect, 0)
      }]).enableBrush({
        brushType: 'lineX',
        brushStyle: areaSelectStyle,
        removeOnClick: true
      }).updateCovers(getCoverInfoList(axisModel));
    };

    ParallelAxisView.prototype._onBrush = function (eventParam) {
      var coverInfoList = eventParam.areas;
      var axisModel = this.axisModel;
      var axis = axisModel.axis;
      var intervals = map(coverInfoList, function (coverInfo) {
        return [axis.coordToData(coverInfo.range[0], true), axis.coordToData(coverInfo.range[1], true)];
      });

      if (!axisModel.option.realtime === eventParam.isEnd || eventParam.removeOnClick) {
        this.api.dispatchAction({
          type: 'axisAreaSelect',
          parallelAxisId: axisModel.id,
          intervals: intervals
        });
      }
    };

    ParallelAxisView.prototype.dispose = function () {
      this._brushController.dispose();
    };

    ParallelAxisView.type = 'parallelAxis';
    return ParallelAxisView;
  }(ComponentView);

  ComponentView.registerClass(ParallelAxisView);

  function fromAxisAreaSelect(axisModel, ecModel, payload) {
    return payload && payload.type === 'axisAreaSelect' && ecModel.findComponents({
      mainType: 'parallelAxis',
      query: payload
    })[0] === axisModel;
  }

  function getCoverInfoList(axisModel) {
    var axis = axisModel.axis;
    return map(axisModel.activeIntervals, function (interval) {
      return {
        brushType: 'lineX',
        panelId: 'pl',
        range: [axis.dataToCoord(interval[0], true), axis.dataToCoord(interval[1], true)]
      };
    });
  }

  function getCoordSysModel(axisModel, ecModel) {
    return ecModel.getComponent('parallel', axisModel.get('parallelIndex'));
  }

  var CLICK_THRESHOLD = 5;

  var ParallelView = function (_super) {
    __extends(ParallelView, _super);

    function ParallelView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelView.type;
      return _this;
    }

    ParallelView.prototype.render = function (parallelModel, ecModel, api) {
      this._model = parallelModel;
      this._api = api;

      if (!this._handlers) {
        this._handlers = {};
        each(handlers, function (handler, eventName) {
          api.getZr().on(eventName, this._handlers[eventName] = bind(handler, this));
        }, this);
      }

      createOrUpdate(this, '_throttledDispatchExpand', parallelModel.get('axisExpandRate'), 'fixRate');
    };

    ParallelView.prototype.dispose = function (ecModel, api) {
      each(this._handlers, function (handler, eventName) {
        api.getZr().off(eventName, handler);
      });
      this._handlers = null;
    };

    ParallelView.prototype._throttledDispatchExpand = function (opt) {
      this._dispatchExpand(opt);
    };

    ParallelView.prototype._dispatchExpand = function (opt) {
      opt && this._api.dispatchAction(extend({
        type: 'parallelAxisExpand'
      }, opt));
    };

    ParallelView.type = 'parallel';
    return ParallelView;
  }(ComponentView);

  ComponentView.registerClass(ParallelView);
  var handlers = {
    mousedown: function (e) {
      if (checkTrigger(this, 'click')) {
        this._mouseDownPoint = [e.offsetX, e.offsetY];
      }
    },
    mouseup: function (e) {
      var mouseDownPoint = this._mouseDownPoint;

      if (checkTrigger(this, 'click') && mouseDownPoint) {
        var point = [e.offsetX, e.offsetY];
        var dist = Math.pow(mouseDownPoint[0] - point[0], 2) + Math.pow(mouseDownPoint[1] - point[1], 2);

        if (dist > CLICK_THRESHOLD) {
          return;
        }

        var result = this._model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]);

        result.behavior !== 'none' && this._dispatchExpand({
          axisExpandWindow: result.axisExpandWindow
        });
      }

      this._mouseDownPoint = null;
    },
    mousemove: function (e) {
      if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) {
        return;
      }

      var model = this._model;
      var result = model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]);
      var behavior = result.behavior;
      behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce'));

      this._throttledDispatchExpand(behavior === 'none' ? null : {
        axisExpandWindow: result.axisExpandWindow,
        animation: behavior === 'jump' ? null : {
          duration: 0
        }
      });
    }
  };

  function checkTrigger(view, triggerOn) {
    var model = view._model;
    return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn;
  }

  registerPreprocessor(parallelPreprocessor);

  var ParallelSeriesModel = function (_super) {
    __extends(ParallelSeriesModel, _super);

    function ParallelSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelSeriesModel.type;
      _this.visualStyleAccessPath = 'lineStyle';
      _this.visualDrawType = 'stroke';
      return _this;
    }

    ParallelSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this, {
        useEncodeDefaulter: bind(makeDefaultEncode, null, this)
      });
    };

    ParallelSeriesModel.prototype.getRawIndicesByActiveState = function (activeState) {
      var coordSys = this.coordinateSystem;
      var data = this.getData();
      var indices = [];
      coordSys.eachActiveState(data, function (theActiveState, dataIndex) {
        if (activeState === theActiveState) {
          indices.push(data.getRawIndex(dataIndex));
        }
      });
      return indices;
    };

    ParallelSeriesModel.type = 'series.parallel';
    ParallelSeriesModel.dependencies = ['parallel'];
    ParallelSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'parallel',
      parallelIndex: 0,
      label: {
        show: false
      },
      inactiveOpacity: 0.05,
      activeOpacity: 1,
      lineStyle: {
        width: 1,
        opacity: 0.45,
        type: 'solid'
      },
      emphasis: {
        label: {
          show: false
        }
      },
      progressive: 500,
      smooth: false,
      animationEasing: 'linear'
    };
    return ParallelSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(ParallelSeriesModel);

  function makeDefaultEncode(seriesModel) {
    var parallelModel = seriesModel.ecModel.getComponent('parallel', seriesModel.get('parallelIndex'));

    if (!parallelModel) {
      return;
    }

    var encodeDefine = {};
    each(parallelModel.dimensions, function (axisDim) {
      var dataDimIndex = convertDimNameToNumber(axisDim);
      encodeDefine[axisDim] = dataDimIndex;
    });
    return encodeDefine;
  }

  function convertDimNameToNumber(dimName) {
    return +dimName.replace('dim', '');
  }

  var DEFAULT_SMOOTH = 0.3;

  var ParallelView$1 = function (_super) {
    __extends(ParallelView, _super);

    function ParallelView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ParallelView.type;
      _this._dataGroup = new Group();
      _this._initialized = false;
      return _this;
    }

    ParallelView.prototype.init = function () {
      this.group.add(this._dataGroup);
    };

    ParallelView.prototype.render = function (seriesModel, ecModel, api, payload) {
      var dataGroup = this._dataGroup;
      var data = seriesModel.getData();
      var oldData = this._data;
      var coordSys = seriesModel.coordinateSystem;
      var dimensions = coordSys.dimensions;
      var seriesScope = makeSeriesScope$2(seriesModel);
      data.diff(oldData).add(add).update(update).remove(remove).execute();

      function add(newDataIndex) {
        var line = addEl(data, dataGroup, newDataIndex, dimensions, coordSys);
        updateElCommon(line, data, newDataIndex, seriesScope);
      }

      function update(newDataIndex, oldDataIndex) {
        var line = oldData.getItemGraphicEl(oldDataIndex);
        var points = createLinePoints(data, newDataIndex, dimensions, coordSys);
        data.setItemGraphicEl(newDataIndex, line);
        updateProps(line, {
          shape: {
            points: points
          }
        }, seriesModel, newDataIndex);
        updateElCommon(line, data, newDataIndex, seriesScope);
      }

      function remove(oldDataIndex) {
        var line = oldData.getItemGraphicEl(oldDataIndex);
        dataGroup.remove(line);
      }

      if (!this._initialized) {
        this._initialized = true;
        var clipPath = createGridClipShape(coordSys, seriesModel, function () {
          setTimeout(function () {
            dataGroup.removeClipPath();
          });
        });
        dataGroup.setClipPath(clipPath);
      }

      this._data = data;
    };

    ParallelView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
      this._initialized = true;
      this._data = null;

      this._dataGroup.removeAll();
    };

    ParallelView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) {
      var data = seriesModel.getData();
      var coordSys = seriesModel.coordinateSystem;
      var dimensions = coordSys.dimensions;
      var seriesScope = makeSeriesScope$2(seriesModel);

      for (var dataIndex = taskParams.start; dataIndex < taskParams.end; dataIndex++) {
        var line = addEl(data, this._dataGroup, dataIndex, dimensions, coordSys);
        line.incremental = true;
        updateElCommon(line, data, dataIndex, seriesScope);
      }
    };

    ParallelView.prototype.remove = function () {
      this._dataGroup && this._dataGroup.removeAll();
      this._data = null;
    };

    ParallelView.type = 'parallel';
    return ParallelView;
  }(ChartView);

  function createGridClipShape(coordSys, seriesModel, cb) {
    var parallelModel = coordSys.model;
    var rect = coordSys.getRect();
    var rectEl = new Rect({
      shape: {
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height
      }
    });
    var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height';
    rectEl.setShape(dim, 0);
    initProps(rectEl, {
      shape: {
        width: rect.width,
        height: rect.height
      }
    }, seriesModel, cb);
    return rectEl;
  }

  function createLinePoints(data, dataIndex, dimensions, coordSys) {
    var points = [];

    for (var i = 0; i < dimensions.length; i++) {
      var dimName = dimensions[i];
      var value = data.get(data.mapDimension(dimName), dataIndex);

      if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) {
        points.push(coordSys.dataToPoint(value, dimName));
      }
    }

    return points;
  }

  function addEl(data, dataGroup, dataIndex, dimensions, coordSys) {
    var points = createLinePoints(data, dataIndex, dimensions, coordSys);
    var line = new Polyline({
      shape: {
        points: points
      },
      z2: 10
    });
    dataGroup.add(line);
    data.setItemGraphicEl(dataIndex, line);
    return line;
  }

  function makeSeriesScope$2(seriesModel) {
    var smooth = seriesModel.get('smooth', true);
    smooth === true && (smooth = DEFAULT_SMOOTH);
    smooth = numericToNumber(smooth);
    eqNaN(smooth) && (smooth = 0);
    return {
      smooth: smooth
    };
  }

  function updateElCommon(el, data, dataIndex, seriesScope) {
    el.useStyle(data.getItemVisual(dataIndex, 'style'));
    el.style.fill = null;
    el.setShape('smooth', seriesScope.smooth);
    var itemModel = data.getItemModel(dataIndex);
    var emphasisModel = itemModel.getModel('emphasis');
    setStatesStylesFromModel(el, itemModel, 'lineStyle');
    enableHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
  }

  function isEmptyValue(val, axisType) {
    return axisType === 'category' ? val == null : val == null || isNaN(val);
  }

  ChartView.registerClass(ParallelView$1);
  var opacityAccessPath$1 = ['lineStyle', 'opacity'];
  var parallelVisual = {
    seriesType: 'parallel',
    reset: function (seriesModel, ecModel) {
      var coordSys = seriesModel.coordinateSystem;
      var opacityMap = {
        normal: seriesModel.get(['lineStyle', 'opacity']),
        active: seriesModel.get('activeOpacity'),
        inactive: seriesModel.get('inactiveOpacity')
      };
      return {
        progress: function (params, data) {
          coordSys.eachActiveState(data, function (activeState, dataIndex) {
            var opacity = opacityMap[activeState];

            if (activeState === 'normal' && data.hasItemOption) {
              var itemOpacity = data.getItemModel(dataIndex).get(opacityAccessPath$1, true);
              itemOpacity != null && (opacity = itemOpacity);
            }

            var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style');
            existsStyle.opacity = opacity;
          }, params.start, params.end);
        }
      };
    }
  };
  registerVisual(PRIORITY.VISUAL.BRUSH, parallelVisual);

  var SankeySeriesModel = function (_super) {
    __extends(SankeySeriesModel, _super);

    function SankeySeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SankeySeriesModel.type;
      return _this;
    }

    SankeySeriesModel.prototype.getInitialData = function (option, ecModel) {
      var links = option.edges || option.links;
      var nodes = option.data || option.nodes;
      var levels = option.levels;
      this.levelModels = [];
      var levelModels = this.levelModels;

      for (var i = 0; i < levels.length; i++) {
        if (levels[i].depth != null && levels[i].depth >= 0) {
          levelModels[levels[i].depth] = new Model(levels[i], this, ecModel);
        } else {
          if (true) {
            throw new Error('levels[i].depth is mandatory and should be natural number');
          }
        }
      }

      if (nodes && links) {
        var graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink);
        return graph.data;
      }

      function beforeLink(nodeData, edgeData) {
        nodeData.wrapMethod('getItemModel', function (model, idx) {
          var seriesModel = model.parentModel;
          var layout = seriesModel.getData().getItemLayout(idx);

          if (layout) {
            var nodeDepth = layout.depth;
            var levelModel = seriesModel.levelModels[nodeDepth];

            if (levelModel) {
              model.parentModel = levelModel;
            }
          }

          return model;
        });
        edgeData.wrapMethod('getItemModel', function (model, idx) {
          var seriesModel = model.parentModel;
          var edge = seriesModel.getGraph().getEdgeByIndex(idx);
          var layout = edge.node1.getLayout();

          if (layout) {
            var depth = layout.depth;
            var levelModel = seriesModel.levelModels[depth];

            if (levelModel) {
              model.parentModel = levelModel;
            }
          }

          return model;
        });
      }
    };

    SankeySeriesModel.prototype.setNodePosition = function (dataIndex, localPosition) {
      var dataItem = this.option.data[dataIndex];
      dataItem.localX = localPosition[0];
      dataItem.localY = localPosition[1];
    };

    SankeySeriesModel.prototype.getGraph = function () {
      return this.getData().graph;
    };

    SankeySeriesModel.prototype.getEdgeData = function () {
      return this.getGraph().edgeData;
    };

    SankeySeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      function noValue(val) {
        return isNaN(val) || val == null;
      }

      if (dataType === 'edge') {
        var params = this.getDataParams(dataIndex, dataType);
        var rawDataOpt = params.data;
        var edgeValue = params.value;
        var edgeName = rawDataOpt.source + ' -- ' + rawDataOpt.target;
        return createTooltipMarkup('nameValue', {
          name: edgeName,
          value: edgeValue,
          noValue: noValue(edgeValue)
        });
      } else {
        var node = this.getGraph().getNodeByIndex(dataIndex);
        var value = node.getLayout().value;
        var name_1 = this.getDataParams(dataIndex, dataType).data.name;
        return createTooltipMarkup('nameValue', {
          name: name_1,
          value: value,
          noValue: noValue(value)
        });
      }
    };

    SankeySeriesModel.prototype.optionUpdated = function () {
      var option = this.option;

      if (option.focusNodeAdjacency === true) {
        option.focusNodeAdjacency = 'allEdges';
      }
    };

    SankeySeriesModel.prototype.getDataParams = function (dataIndex, dataType) {
      var params = _super.prototype.getDataParams.call(this, dataIndex, dataType);

      if (params.value == null && dataType === 'node') {
        var node = this.getGraph().getNodeByIndex(dataIndex);
        var nodeValue = node.getLayout().value;
        params.value = nodeValue;
      }

      return params;
    };

    SankeySeriesModel.type = 'series.sankey';
    SankeySeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'view',
      left: '5%',
      top: '5%',
      right: '20%',
      bottom: '5%',
      orient: 'horizontal',
      nodeWidth: 20,
      nodeGap: 8,
      draggable: true,
      focusNodeAdjacency: false,
      layoutIterations: 32,
      label: {
        show: true,
        position: 'right',
        fontSize: 12
      },
      levels: [],
      nodeAlign: 'justify',
      lineStyle: {
        color: '#314656',
        opacity: 0.2,
        curveness: 0.5
      },
      emphasis: {
        label: {
          show: true
        },
        lineStyle: {
          opacity: 0.5
        }
      },
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      },
      animationEasing: 'linear',
      animationDuration: 1000
    };
    return SankeySeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(SankeySeriesModel);

  var SankeyPathShape = function () {
    function SankeyPathShape() {
      this.x1 = 0;
      this.y1 = 0;
      this.x2 = 0;
      this.y2 = 0;
      this.cpx1 = 0;
      this.cpy1 = 0;
      this.cpx2 = 0;
      this.cpy2 = 0;
      this.extent = 0;
    }

    return SankeyPathShape;
  }();

  var SankeyPath = function (_super) {
    __extends(SankeyPath, _super);

    function SankeyPath(opts) {
      return _super.call(this, opts) || this;
    }

    SankeyPath.prototype.getDefaultShape = function () {
      return new SankeyPathShape();
    };

    SankeyPath.prototype.buildPath = function (ctx, shape) {
      var extent = shape.extent;
      ctx.moveTo(shape.x1, shape.y1);
      ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2);

      if (shape.orient === 'vertical') {
        ctx.lineTo(shape.x2 + extent, shape.y2);
        ctx.bezierCurveTo(shape.cpx2 + extent, shape.cpy2, shape.cpx1 + extent, shape.cpy1, shape.x1 + extent, shape.y1);
      } else {
        ctx.lineTo(shape.x2, shape.y2 + extent);
        ctx.bezierCurveTo(shape.cpx2, shape.cpy2 + extent, shape.cpx1, shape.cpy1 + extent, shape.x1, shape.y1 + extent);
      }

      ctx.closePath();
    };

    SankeyPath.prototype.highlight = function () {
      enterEmphasis(this);
    };

    SankeyPath.prototype.downplay = function () {
      leaveEmphasis(this);
    };

    return SankeyPath;
  }(Path);

  var SankeyView = function (_super) {
    __extends(SankeyView, _super);

    function SankeyView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SankeyView.type;
      _this._focusAdjacencyDisabled = false;
      return _this;
    }

    SankeyView.prototype.render = function (seriesModel, ecModel, api) {
      var sankeyView = this;
      var graph = seriesModel.getGraph();
      var group = this.group;
      var layoutInfo = seriesModel.layoutInfo;
      var width = layoutInfo.width;
      var height = layoutInfo.height;
      var nodeData = seriesModel.getData();
      var edgeData = seriesModel.getData('edge');
      var orient = seriesModel.get('orient');
      this._model = seriesModel;
      group.removeAll();
      group.x = layoutInfo.x;
      group.y = layoutInfo.y;
      graph.eachEdge(function (edge) {
        var curve = new SankeyPath();
        var ecData = getECData(curve);
        ecData.dataIndex = edge.dataIndex;
        ecData.seriesIndex = seriesModel.seriesIndex;
        ecData.dataType = 'edge';
        var edgeModel = edge.getModel();
        var lineStyleModel = edgeModel.getModel('lineStyle');
        var curvature = lineStyleModel.get('curveness');
        var n1Layout = edge.node1.getLayout();
        var node1Model = edge.node1.getModel();
        var dragX1 = node1Model.get('localX');
        var dragY1 = node1Model.get('localY');
        var n2Layout = edge.node2.getLayout();
        var node2Model = edge.node2.getModel();
        var dragX2 = node2Model.get('localX');
        var dragY2 = node2Model.get('localY');
        var edgeLayout = edge.getLayout();
        var x1;
        var y1;
        var x2;
        var y2;
        var cpx1;
        var cpy1;
        var cpx2;
        var cpy2;
        curve.shape.extent = Math.max(1, edgeLayout.dy);
        curve.shape.orient = orient;

        if (orient === 'vertical') {
          x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy;
          y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy;
          x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty;
          y2 = dragY2 != null ? dragY2 * height : n2Layout.y;
          cpx1 = x1;
          cpy1 = y1 * (1 - curvature) + y2 * curvature;
          cpx2 = x2;
          cpy2 = y1 * curvature + y2 * (1 - curvature);
        } else {
          x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx;
          y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy;
          x2 = dragX2 != null ? dragX2 * width : n2Layout.x;
          y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty;
          cpx1 = x1 * (1 - curvature) + x2 * curvature;
          cpy1 = y1;
          cpx2 = x1 * curvature + x2 * (1 - curvature);
          cpy2 = y2;
        }

        curve.setShape({
          x1: x1,
          y1: y1,
          x2: x2,
          y2: y2,
          cpx1: cpx1,
          cpy1: cpy1,
          cpx2: cpx2,
          cpy2: cpy2
        });
        curve.useStyle(lineStyleModel.getItemStyle());

        switch (curve.style.fill) {
          case 'source':
            curve.style.fill = edge.node1.getVisual('color');
            curve.style.decal = edge.node1.getVisual('style').decal;
            break;

          case 'target':
            curve.style.fill = edge.node2.getVisual('color');
            curve.style.decal = edge.node2.getVisual('style').decal;
            break;

          case 'gradient':
            var sourceColor = edge.node1.getVisual('color');
            var targetColor = edge.node2.getVisual('color');

            if (typeof sourceColor === 'string' && typeof targetColor === 'string') {
              curve.style.fill = new LinearGradient(0, 0, 1, 0, [{
                color: sourceColor,
                offset: 0
              }, {
                color: targetColor,
                offset: 1
              }]);
            }

        }

        var emphasisModel = edgeModel.getModel('emphasis');
        setStatesStylesFromModel(curve, edgeModel, 'lineStyle', function (model) {
          return model.getItemStyle();
        });
        group.add(curve);
        edgeData.setItemGraphicEl(edge.dataIndex, curve);
        var focus = emphasisModel.get('focus');
        enableHoverEmphasis(curve, focus === 'adjacency' ? edge.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope'));
        getECData(curve).dataType = 'edge';
      });
      graph.eachNode(function (node) {
        var layout = node.getLayout();
        var itemModel = node.getModel();
        var dragX = itemModel.get('localX');
        var dragY = itemModel.get('localY');
        var emphasisModel = itemModel.getModel('emphasis');
        var rect = new Rect({
          shape: {
            x: dragX != null ? dragX * width : layout.x,
            y: dragY != null ? dragY * height : layout.y,
            width: layout.dx,
            height: layout.dy
          },
          style: itemModel.getModel('itemStyle').getItemStyle()
        });
        setLabelStyle(rect, getLabelStatesModels(itemModel), {
          labelFetcher: seriesModel,
          labelDataIndex: node.dataIndex,
          defaultText: node.id
        });
        rect.disableLabelAnimation = true;
        rect.setStyle('fill', node.getVisual('color'));
        rect.setStyle('decal', node.getVisual('style').decal);
        setStatesStylesFromModel(rect, itemModel);
        group.add(rect);
        nodeData.setItemGraphicEl(node.dataIndex, rect);
        getECData(rect).dataType = 'node';
        var focus = emphasisModel.get('focus');
        enableHoverEmphasis(rect, focus === 'adjacency' ? node.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope'));
      });
      nodeData.eachItemGraphicEl(function (el, dataIndex) {
        var itemModel = nodeData.getItemModel(dataIndex);

        if (itemModel.get('draggable')) {
          el.drift = function (dx, dy) {
            sankeyView._focusAdjacencyDisabled = true;
            this.shape.x += dx;
            this.shape.y += dy;
            this.dirty();
            api.dispatchAction({
              type: 'dragNode',
              seriesId: seriesModel.id,
              dataIndex: nodeData.getRawIndex(dataIndex),
              localX: this.shape.x / width,
              localY: this.shape.y / height
            });
          };

          el.ondragend = function () {
            sankeyView._focusAdjacencyDisabled = false;
          };

          el.draggable = true;
          el.cursor = 'move';
        }
      });

      if (!this._data && seriesModel.isAnimationEnabled()) {
        group.setClipPath(createGridClipShape$1(group.getBoundingRect(), seriesModel, function () {
          group.removeClipPath();
        }));
      }

      this._data = seriesModel.getData();
    };

    SankeyView.prototype.dispose = function () {};

    SankeyView.type = 'sankey';
    return SankeyView;
  }(ChartView);

  function createGridClipShape$1(rect, seriesModel, cb) {
    var rectEl = new Rect({
      shape: {
        x: rect.x - 10,
        y: rect.y - 10,
        width: 0,
        height: rect.height + 20
      }
    });
    initProps(rectEl, {
      shape: {
        width: rect.width + 20
      }
    }, seriesModel, cb);
    return rectEl;
  }

  ChartView.registerClass(SankeyView);
  registerAction({
    type: 'dragNode',
    event: 'dragnode',
    update: 'update'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'sankey',
      query: payload
    }, function (seriesModel) {
      seriesModel.setNodePosition(payload.dataIndex, [payload.localX, payload.localY]);
    });
  });

  function sankeyLayout(ecModel, api) {
    ecModel.eachSeriesByType('sankey', function (seriesModel) {
      var nodeWidth = seriesModel.get('nodeWidth');
      var nodeGap = seriesModel.get('nodeGap');
      var layoutInfo = getViewRect$4(seriesModel, api);
      seriesModel.layoutInfo = layoutInfo;
      var width = layoutInfo.width;
      var height = layoutInfo.height;
      var graph = seriesModel.getGraph();
      var nodes = graph.nodes;
      var edges = graph.edges;
      computeNodeValues(nodes);
      var filteredNodes = filter(nodes, function (node) {
        return node.getLayout().value === 0;
      });
      var iterations = filteredNodes.length !== 0 ? 0 : seriesModel.get('layoutIterations');
      var orient = seriesModel.get('orient');
      var nodeAlign = seriesModel.get('nodeAlign');
      layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign);
    });
  }

  function getViewRect$4(seriesModel, api) {
    return getLayoutRect(seriesModel.getBoxLayoutParams(), {
      width: api.getWidth(),
      height: api.getHeight()
    });
  }

  function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign) {
    computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign);
    computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient);
    computeEdgeDepths(nodes, orient);
  }

  function computeNodeValues(nodes) {
    each(nodes, function (node) {
      var value1 = sum(node.outEdges, getEdgeValue);
      var value2 = sum(node.inEdges, getEdgeValue);
      var nodeRawValue = node.getValue() || 0;
      var value = Math.max(value1, value2, nodeRawValue);
      node.setLayout({
        value: value
      }, true);
    });
  }

  function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign) {
    var remainEdges = [];
    var indegreeArr = [];
    var zeroIndegrees = [];
    var nextTargetNode = [];
    var x = 0;

    for (var i = 0; i < edges.length; i++) {
      remainEdges[i] = 1;
    }

    for (var i = 0; i < nodes.length; i++) {
      indegreeArr[i] = nodes[i].inEdges.length;

      if (indegreeArr[i] === 0) {
        zeroIndegrees.push(nodes[i]);
      }
    }

    var maxNodeDepth = -1;

    while (zeroIndegrees.length) {
      for (var idx = 0; idx < zeroIndegrees.length; idx++) {
        var node = zeroIndegrees[idx];
        var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
        var isItemDepth = item.depth != null && item.depth >= 0;

        if (isItemDepth && item.depth > maxNodeDepth) {
          maxNodeDepth = item.depth;
        }

        node.setLayout({
          depth: isItemDepth ? item.depth : x
        }, true);
        orient === 'vertical' ? node.setLayout({
          dy: nodeWidth
        }, true) : node.setLayout({
          dx: nodeWidth
        }, true);

        for (var edgeIdx = 0; edgeIdx < node.outEdges.length; edgeIdx++) {
          var edge = node.outEdges[edgeIdx];
          var indexEdge = edges.indexOf(edge);
          remainEdges[indexEdge] = 0;
          var targetNode = edge.node2;
          var nodeIndex = nodes.indexOf(targetNode);

          if (--indegreeArr[nodeIndex] === 0 && nextTargetNode.indexOf(targetNode) < 0) {
            nextTargetNode.push(targetNode);
          }
        }
      }

      ++x;
      zeroIndegrees = nextTargetNode;
      nextTargetNode = [];
    }

    for (var i = 0; i < remainEdges.length; i++) {
      if (remainEdges[i] === 1) {
        throw new Error('Sankey is a DAG, the original data has cycle!');
      }
    }

    var maxDepth = maxNodeDepth > x - 1 ? maxNodeDepth : x - 1;

    if (nodeAlign && nodeAlign !== 'left') {
      adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth);
    }

    var kx = orient === 'vertical' ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth;
    scaleNodeBreadths(nodes, kx, orient);
  }

  function isNodeDepth(node) {
    var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
    return item.depth != null && item.depth >= 0;
  }

  function adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth) {
    if (nodeAlign === 'right') {
      var nextSourceNode = [];
      var remainNodes = nodes;
      var nodeHeight = 0;

      while (remainNodes.length) {
        for (var i = 0; i < remainNodes.length; i++) {
          var node = remainNodes[i];
          node.setLayout({
            skNodeHeight: nodeHeight
          }, true);

          for (var j = 0; j < node.inEdges.length; j++) {
            var edge = node.inEdges[j];

            if (nextSourceNode.indexOf(edge.node1) < 0) {
              nextSourceNode.push(edge.node1);
            }
          }
        }

        remainNodes = nextSourceNode;
        nextSourceNode = [];
        ++nodeHeight;
      }

      each(nodes, function (node) {
        if (!isNodeDepth(node)) {
          node.setLayout({
            depth: Math.max(0, maxDepth - node.getLayout().skNodeHeight)
          }, true);
        }
      });
    } else if (nodeAlign === 'justify') {
      moveSinksRight(nodes, maxDepth);
    }
  }

  function moveSinksRight(nodes, maxDepth) {
    each(nodes, function (node) {
      if (!isNodeDepth(node) && !node.outEdges.length) {
        node.setLayout({
          depth: maxDepth
        }, true);
      }
    });
  }

  function scaleNodeBreadths(nodes, kx, orient) {
    each(nodes, function (node) {
      var nodeDepth = node.getLayout().depth * kx;
      orient === 'vertical' ? node.setLayout({
        y: nodeDepth
      }, true) : node.setLayout({
        x: nodeDepth
      }, true);
    });
  }

  function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) {
    var nodesByBreadth = prepareNodesByBreadth(nodes, orient);
    initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient);
    resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);

    for (var alpha = 1; iterations > 0; iterations--) {
      alpha *= 0.99;
      relaxRightToLeft(nodesByBreadth, alpha, orient);
      resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
      relaxLeftToRight(nodesByBreadth, alpha, orient);
      resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
    }
  }

  function prepareNodesByBreadth(nodes, orient) {
    var nodesByBreadth = [];
    var keyAttr = orient === 'vertical' ? 'y' : 'x';
    var groupResult = groupData(nodes, function (node) {
      return node.getLayout()[keyAttr];
    });
    groupResult.keys.sort(function (a, b) {
      return a - b;
    });
    each(groupResult.keys, function (key) {
      nodesByBreadth.push(groupResult.buckets.get(key));
    });
    return nodesByBreadth;
  }

  function initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient) {
    var minKy = Infinity;
    each(nodesByBreadth, function (nodes) {
      var n = nodes.length;
      var sum = 0;
      each(nodes, function (node) {
        sum += node.getLayout().value;
      });
      var ky = orient === 'vertical' ? (width - (n - 1) * nodeGap) / sum : (height - (n - 1) * nodeGap) / sum;

      if (ky < minKy) {
        minKy = ky;
      }
    });
    each(nodesByBreadth, function (nodes) {
      each(nodes, function (node, i) {
        var nodeDy = node.getLayout().value * minKy;

        if (orient === 'vertical') {
          node.setLayout({
            x: i
          }, true);
          node.setLayout({
            dx: nodeDy
          }, true);
        } else {
          node.setLayout({
            y: i
          }, true);
          node.setLayout({
            dy: nodeDy
          }, true);
        }
      });
    });
    each(edges, function (edge) {
      var edgeDy = +edge.getValue() * minKy;
      edge.setLayout({
        dy: edgeDy
      }, true);
    });
  }

  function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) {
    var keyAttr = orient === 'vertical' ? 'x' : 'y';
    each(nodesByBreadth, function (nodes) {
      nodes.sort(function (a, b) {
        return a.getLayout()[keyAttr] - b.getLayout()[keyAttr];
      });
      var nodeX;
      var node;
      var dy;
      var y0 = 0;
      var n = nodes.length;
      var nodeDyAttr = orient === 'vertical' ? 'dx' : 'dy';

      for (var i = 0; i < n; i++) {
        node = nodes[i];
        dy = y0 - node.getLayout()[keyAttr];

        if (dy > 0) {
          nodeX = node.getLayout()[keyAttr] + dy;
          orient === 'vertical' ? node.setLayout({
            x: nodeX
          }, true) : node.setLayout({
            y: nodeX
          }, true);
        }

        y0 = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap;
      }

      var viewWidth = orient === 'vertical' ? width : height;
      dy = y0 - nodeGap - viewWidth;

      if (dy > 0) {
        nodeX = node.getLayout()[keyAttr] - dy;
        orient === 'vertical' ? node.setLayout({
          x: nodeX
        }, true) : node.setLayout({
          y: nodeX
        }, true);
        y0 = nodeX;

        for (var i = n - 2; i >= 0; --i) {
          node = nodes[i];
          dy = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap - y0;

          if (dy > 0) {
            nodeX = node.getLayout()[keyAttr] - dy;
            orient === 'vertical' ? node.setLayout({
              x: nodeX
            }, true) : node.setLayout({
              y: nodeX
            }, true);
          }

          y0 = node.getLayout()[keyAttr];
        }
      }
    });
  }

  function relaxRightToLeft(nodesByBreadth, alpha, orient) {
    each(nodesByBreadth.slice().reverse(), function (nodes) {
      each(nodes, function (node) {
        if (node.outEdges.length) {
          var y = sum(node.outEdges, weightedTarget, orient) / sum(node.outEdges, getEdgeValue);

          if (isNaN(y)) {
            var len = node.outEdges.length;
            y = len ? sum(node.outEdges, centerTarget, orient) / len : 0;
          }

          if (orient === 'vertical') {
            var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha;
            node.setLayout({
              x: nodeX
            }, true);
          } else {
            var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha;
            node.setLayout({
              y: nodeY
            }, true);
          }
        }
      });
    });
  }

  function weightedTarget(edge, orient) {
    return center$1(edge.node2, orient) * edge.getValue();
  }

  function centerTarget(edge, orient) {
    return center$1(edge.node2, orient);
  }

  function weightedSource(edge, orient) {
    return center$1(edge.node1, orient) * edge.getValue();
  }

  function centerSource(edge, orient) {
    return center$1(edge.node1, orient);
  }

  function center$1(node, orient) {
    return orient === 'vertical' ? node.getLayout().x + node.getLayout().dx / 2 : node.getLayout().y + node.getLayout().dy / 2;
  }

  function getEdgeValue(edge) {
    return edge.getValue();
  }

  function sum(array, cb, orient) {
    var sum = 0;
    var len = array.length;
    var i = -1;

    while (++i < len) {
      var value = +cb(array[i], orient);

      if (!isNaN(value)) {
        sum += value;
      }
    }

    return sum;
  }

  function relaxLeftToRight(nodesByBreadth, alpha, orient) {
    each(nodesByBreadth, function (nodes) {
      each(nodes, function (node) {
        if (node.inEdges.length) {
          var y = sum(node.inEdges, weightedSource, orient) / sum(node.inEdges, getEdgeValue);

          if (isNaN(y)) {
            var len = node.inEdges.length;
            y = len ? sum(node.inEdges, centerSource, orient) / len : 0;
          }

          if (orient === 'vertical') {
            var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha;
            node.setLayout({
              x: nodeX
            }, true);
          } else {
            var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha;
            node.setLayout({
              y: nodeY
            }, true);
          }
        }
      });
    });
  }

  function computeEdgeDepths(nodes, orient) {
    var keyAttr = orient === 'vertical' ? 'x' : 'y';
    each(nodes, function (node) {
      node.outEdges.sort(function (a, b) {
        return a.node2.getLayout()[keyAttr] - b.node2.getLayout()[keyAttr];
      });
      node.inEdges.sort(function (a, b) {
        return a.node1.getLayout()[keyAttr] - b.node1.getLayout()[keyAttr];
      });
    });
    each(nodes, function (node) {
      var sy = 0;
      var ty = 0;
      each(node.outEdges, function (edge) {
        edge.setLayout({
          sy: sy
        }, true);
        sy += edge.getLayout().dy;
      });
      each(node.inEdges, function (edge) {
        edge.setLayout({
          ty: ty
        }, true);
        ty += edge.getLayout().dy;
      });
    });
  }

  function sankeyVisual(ecModel) {
    ecModel.eachSeriesByType('sankey', function (seriesModel) {
      var graph = seriesModel.getGraph();
      var nodes = graph.nodes;

      if (nodes.length) {
        var minValue_1 = Infinity;
        var maxValue_1 = -Infinity;
        each(nodes, function (node) {
          var nodeValue = node.getLayout().value;

          if (nodeValue < minValue_1) {
            minValue_1 = nodeValue;
          }

          if (nodeValue > maxValue_1) {
            maxValue_1 = nodeValue;
          }
        });
        each(nodes, function (node) {
          var mapping = new VisualMapping({
            type: 'color',
            mappingMethod: 'linear',
            dataExtent: [minValue_1, maxValue_1],
            visual: seriesModel.get('color')
          });
          var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value);
          var customColor = node.getModel().get(['itemStyle', 'color']);

          if (customColor != null) {
            node.setVisual('color', customColor);
            node.setVisual('style', {
              fill: customColor
            });
          } else {
            node.setVisual('color', mapValueToColor);
            node.setVisual('style', {
              fill: mapValueToColor
            });
          }
        });
      }
    });
  }

  registerLayout(sankeyLayout);
  registerVisual(sankeyVisual);

  var WhiskerBoxCommonMixin = function () {
    function WhiskerBoxCommonMixin() {}

    WhiskerBoxCommonMixin.prototype.getInitialData = function (option, ecModel) {
      var ordinalMeta;
      var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex'));
      var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex'));
      var xAxisType = xAxisModel.get('type');
      var yAxisType = yAxisModel.get('type');
      var addOrdinal;

      if (xAxisType === 'category') {
        option.layout = 'horizontal';
        ordinalMeta = xAxisModel.getOrdinalMeta();
        addOrdinal = true;
      } else if (yAxisType === 'category') {
        option.layout = 'vertical';
        ordinalMeta = yAxisModel.getOrdinalMeta();
        addOrdinal = true;
      } else {
        option.layout = option.layout || 'horizontal';
      }

      var coordDims = ['x', 'y'];
      var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1;
      var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex];
      var otherAxisDim = coordDims[1 - baseAxisDimIndex];
      var axisModels = [xAxisModel, yAxisModel];
      var baseAxisType = axisModels[baseAxisDimIndex].get('type');
      var otherAxisType = axisModels[1 - baseAxisDimIndex].get('type');
      var data = option.data;

      if (data && addOrdinal) {
        var newOptionData_1 = [];
        each(data, function (item, index) {
          var newItem;

          if (isArray(item)) {
            newItem = item.slice();
            item.unshift(index);
          } else if (isArray(item.value)) {
            newItem = item.value.slice();
            item.value.unshift(index);
          } else {
            newItem = item;
          }

          newOptionData_1.push(newItem);
        });
        option.data = newOptionData_1;
      }

      var defaultValueDimensions = this.defaultValueDimensions;
      var coordDimensions = [{
        name: baseAxisDim,
        type: getDimensionTypeByAxis(baseAxisType),
        ordinalMeta: ordinalMeta,
        otherDims: {
          tooltip: false,
          itemName: 0
        },
        dimsDef: ['base']
      }, {
        name: otherAxisDim,
        type: getDimensionTypeByAxis(otherAxisType),
        dimsDef: defaultValueDimensions.slice()
      }];
      return createListSimply(this, {
        coordDimensions: coordDimensions,
        dimensionsCount: defaultValueDimensions.length + 1,
        encodeDefaulter: curry(makeSeriesEncodeForAxisCoordSys, coordDimensions, this)
      });
    };

    WhiskerBoxCommonMixin.prototype.getBaseAxis = function () {
      var dim = this._baseAxisDim;
      return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis;
    };

    return WhiskerBoxCommonMixin;
  }();

  var BoxplotSeriesModel = function (_super) {
    __extends(BoxplotSeriesModel, _super);

    function BoxplotSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BoxplotSeriesModel.type;
      _this.defaultValueDimensions = [{
        name: 'min',
        defaultTooltip: true
      }, {
        name: 'Q1',
        defaultTooltip: true
      }, {
        name: 'median',
        defaultTooltip: true
      }, {
        name: 'Q3',
        defaultTooltip: true
      }, {
        name: 'max',
        defaultTooltip: true
      }];
      _this.visualDrawType = 'stroke';
      return _this;
    }

    BoxplotSeriesModel.type = 'series.boxplot';
    BoxplotSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid'];
    BoxplotSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'cartesian2d',
      legendHoverLink: true,
      layout: null,
      boxWidth: [7, 50],
      itemStyle: {
        color: '#fff',
        borderWidth: 1
      },
      emphasis: {
        scale: true,
        itemStyle: {
          borderWidth: 2,
          shadowBlur: 5,
          shadowOffsetX: 1,
          shadowOffsetY: 1,
          shadowColor: 'rgba(0,0,0,0.2)'
        }
      },
      animationDuration: 800
    };
    return BoxplotSeriesModel;
  }(SeriesModel);

  mixin(BoxplotSeriesModel, WhiskerBoxCommonMixin, true);
  SeriesModel.registerClass(BoxplotSeriesModel);

  var BoxplotView = function (_super) {
    __extends(BoxplotView, _super);

    function BoxplotView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BoxplotView.type;
      return _this;
    }

    BoxplotView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var group = this.group;
      var oldData = this._data;

      if (!this._data) {
        group.removeAll();
      }

      var constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0;
      data.diff(oldData).add(function (newIdx) {
        if (data.hasValue(newIdx)) {
          var itemLayout = data.getItemLayout(newIdx);
          var symbolEl = createNormalBox(itemLayout, data, newIdx, constDim, true);
          data.setItemGraphicEl(newIdx, symbolEl);
          group.add(symbolEl);
        }
      }).update(function (newIdx, oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);

        if (!data.hasValue(newIdx)) {
          group.remove(symbolEl);
          return;
        }

        var itemLayout = data.getItemLayout(newIdx);

        if (!symbolEl) {
          symbolEl = createNormalBox(itemLayout, data, newIdx, constDim);
        } else {
          updateNormalBoxData(itemLayout, symbolEl, data, newIdx);
        }

        group.add(symbolEl);
        data.setItemGraphicEl(newIdx, symbolEl);
      }).remove(function (oldIdx) {
        var el = oldData.getItemGraphicEl(oldIdx);
        el && group.remove(el);
      }).execute();
      this._data = data;
    };

    BoxplotView.prototype.remove = function (ecModel) {
      var group = this.group;
      var data = this._data;
      this._data = null;
      data && data.eachItemGraphicEl(function (el) {
        el && group.remove(el);
      });
    };

    BoxplotView.type = 'boxplot';
    return BoxplotView;
  }(ChartView);

  var BoxPathShape = function () {
    function BoxPathShape() {}

    return BoxPathShape;
  }();

  var BoxPath = function (_super) {
    __extends(BoxPath, _super);

    function BoxPath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'boxplotBoxPath';
      return _this;
    }

    BoxPath.prototype.getDefaultShape = function () {
      return new BoxPathShape();
    };

    BoxPath.prototype.buildPath = function (ctx, shape) {
      var ends = shape.points;
      var i = 0;
      ctx.moveTo(ends[i][0], ends[i][1]);
      i++;

      for (; i < 4; i++) {
        ctx.lineTo(ends[i][0], ends[i][1]);
      }

      ctx.closePath();

      for (; i < ends.length; i++) {
        ctx.moveTo(ends[i][0], ends[i][1]);
        i++;
        ctx.lineTo(ends[i][0], ends[i][1]);
      }
    };

    return BoxPath;
  }(Path);

  function createNormalBox(itemLayout, data, dataIndex, constDim, isInit) {
    var ends = itemLayout.ends;
    var el = new BoxPath({
      shape: {
        points: isInit ? transInit(ends, constDim, itemLayout) : ends
      }
    });
    updateNormalBoxData(itemLayout, el, data, dataIndex, isInit);
    return el;
  }

  function updateNormalBoxData(itemLayout, el, data, dataIndex, isInit) {
    var seriesModel = data.hostModel;
    var updateMethod = graphic[isInit ? 'initProps' : 'updateProps'];
    updateMethod(el, {
      shape: {
        points: itemLayout.ends
      }
    }, seriesModel, dataIndex);
    el.useStyle(data.getItemVisual(dataIndex, 'style'));
    el.style.strokeNoScale = true;
    el.z2 = 100;
    var itemModel = data.getItemModel(dataIndex);
    setStatesStylesFromModel(el, itemModel);
    enableHoverEmphasis(el, itemModel.get(['emphasis', 'focus']), itemModel.get(['emphasis', 'blurScope']));
  }

  function transInit(points, dim, itemLayout) {
    return map(points, function (point) {
      point = point.slice();
      point[dim] = itemLayout.initBaseline;
      return point;
    });
  }

  ChartView.registerClass(BoxplotView);

  function boxplotVisual(ecModel, api) {
    ecModel.eachRawSeriesByType('boxplot', function (seriesModel) {
      seriesModel.getData().setVisual('legendSymbol', 'roundRect');
    });
  }

  var each$7 = each;

  function boxplotLayout(ecModel) {
    var groupResult = groupSeriesByAxis(ecModel);
    each$7(groupResult, function (groupItem) {
      var seriesModels = groupItem.seriesModels;

      if (!seriesModels.length) {
        return;
      }

      calculateBase(groupItem);
      each$7(seriesModels, function (seriesModel, idx) {
        layoutSingleSeries(seriesModel, groupItem.boxOffsetList[idx], groupItem.boxWidthList[idx]);
      });
    });
  }

  function groupSeriesByAxis(ecModel) {
    var result = [];
    var axisList = [];
    ecModel.eachSeriesByType('boxplot', function (seriesModel) {
      var baseAxis = seriesModel.getBaseAxis();
      var idx = indexOf(axisList, baseAxis);

      if (idx < 0) {
        idx = axisList.length;
        axisList[idx] = baseAxis;
        result[idx] = {
          axis: baseAxis,
          seriesModels: []
        };
      }

      result[idx].seriesModels.push(seriesModel);
    });
    return result;
  }

  function calculateBase(groupItem) {
    var extent;
    var baseAxis = groupItem.axis;
    var seriesModels = groupItem.seriesModels;
    var seriesCount = seriesModels.length;
    var boxWidthList = groupItem.boxWidthList = [];
    var boxOffsetList = groupItem.boxOffsetList = [];
    var boundList = [];
    var bandWidth;

    if (baseAxis.type === 'category') {
      bandWidth = baseAxis.getBandWidth();
    } else {
      var maxDataCount_1 = 0;
      each$7(seriesModels, function (seriesModel) {
        maxDataCount_1 = Math.max(maxDataCount_1, seriesModel.getData().count());
      });
      extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / maxDataCount_1;
    }

    each$7(seriesModels, function (seriesModel) {
      var boxWidthBound = seriesModel.get('boxWidth');

      if (!isArray(boxWidthBound)) {
        boxWidthBound = [boxWidthBound, boxWidthBound];
      }

      boundList.push([parsePercent$2(boxWidthBound[0], bandWidth) || 0, parsePercent$2(boxWidthBound[1], bandWidth) || 0]);
    });
    var availableWidth = bandWidth * 0.8 - 2;
    var boxGap = availableWidth / seriesCount * 0.3;
    var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount;
    var base = boxWidth / 2 - availableWidth / 2;
    each$7(seriesModels, function (seriesModel, idx) {
      boxOffsetList.push(base);
      base += boxGap + boxWidth;
      boxWidthList.push(Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1]));
    });
  }

  function layoutSingleSeries(seriesModel, offset, boxWidth) {
    var coordSys = seriesModel.coordinateSystem;
    var data = seriesModel.getData();
    var halfWidth = boxWidth / 2;
    var cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1;
    var vDimIdx = 1 - cDimIdx;
    var coordDims = ['x', 'y'];
    var cDim = data.mapDimension(coordDims[cDimIdx]);
    var vDims = data.mapDimensionsAll(coordDims[vDimIdx]);

    if (cDim == null || vDims.length < 5) {
      return;
    }

    for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) {
      var axisDimVal = data.get(cDim, dataIndex);
      var median = getPoint(axisDimVal, vDims[2], dataIndex);
      var end1 = getPoint(axisDimVal, vDims[0], dataIndex);
      var end2 = getPoint(axisDimVal, vDims[1], dataIndex);
      var end4 = getPoint(axisDimVal, vDims[3], dataIndex);
      var end5 = getPoint(axisDimVal, vDims[4], dataIndex);
      var ends = [];
      addBodyEnd(ends, end2, false);
      addBodyEnd(ends, end4, true);
      ends.push(end1, end2, end5, end4);
      layEndLine(ends, end1);
      layEndLine(ends, end5);
      layEndLine(ends, median);
      data.setItemLayout(dataIndex, {
        initBaseline: median[vDimIdx],
        ends: ends
      });
    }

    function getPoint(axisDimVal, dim, dataIndex) {
      var val = data.get(dim, dataIndex);
      var p = [];
      p[cDimIdx] = axisDimVal;
      p[vDimIdx] = val;
      var point;

      if (isNaN(axisDimVal) || isNaN(val)) {
        point = [NaN, NaN];
      } else {
        point = coordSys.dataToPoint(p);
        point[cDimIdx] += offset;
      }

      return point;
    }

    function addBodyEnd(ends, point, start) {
      var point1 = point.slice();
      var point2 = point.slice();
      point1[cDimIdx] += halfWidth;
      point2[cDimIdx] -= halfWidth;
      start ? ends.push(point1, point2) : ends.push(point2, point1);
    }

    function layEndLine(ends, endCenter) {
      var from = endCenter.slice();
      var to = endCenter.slice();
      from[cDimIdx] -= halfWidth;
      to[cDimIdx] += halfWidth;
      ends.push(from, to);
    }
  }

  function prepareBoxplotData(rawData, opt) {
    opt = opt || {};
    var boxData = [];
    var outliers = [];
    var boundIQR = opt.boundIQR;
    var useExtreme = boundIQR === 'none' || boundIQR === 0;

    for (var i = 0; i < rawData.length; i++) {
      var ascList = asc(rawData[i].slice());
      var Q1 = quantile(ascList, 0.25);
      var Q2 = quantile(ascList, 0.5);
      var Q3 = quantile(ascList, 0.75);
      var min = ascList[0];
      var max = ascList[ascList.length - 1];
      var bound = (boundIQR == null ? 1.5 : boundIQR) * (Q3 - Q1);
      var low = useExtreme ? min : Math.max(min, Q1 - bound);
      var high = useExtreme ? max : Math.min(max, Q3 + bound);
      var itemNameFormatter = opt.itemNameFormatter;
      var itemName = isFunction(itemNameFormatter) ? itemNameFormatter({
        value: i
      }) : isString(itemNameFormatter) ? itemNameFormatter.replace('{value}', i + '') : i + '';
      boxData.push([itemName, low, Q1, Q2, Q3, high]);

      for (var j = 0; j < ascList.length; j++) {
        var dataItem = ascList[j];

        if (dataItem < low || dataItem > high) {
          var outlier = [itemName, dataItem];
          outliers.push(outlier);
        }
      }
    }

    return {
      boxData: boxData,
      outliers: outliers
    };
  }

  var boxplotTransform = {
    type: 'echarts:boxplot',
    transform: function transform(params) {
      var upstream = params.upstream;

      if (upstream.sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS) {
        var errMsg = '';

        if (true) {
          errMsg = makePrintable('source data is not applicable for this boxplot transform. Expect number[][].');
        }

        throwError(errMsg);
      }

      var result = prepareBoxplotData(upstream.getRawData(), params.config);
      return [{
        dimensions: ['ItemName', 'Low', 'Q1', 'Q2', 'Q3', 'High'],
        data: result.boxData
      }, {
        data: result.outliers
      }];
    }
  };
  registerVisual(boxplotVisual);
  registerLayout(boxplotLayout);
  registerTransform(boxplotTransform);

  var CandlestickSeriesModel = function (_super) {
    __extends(CandlestickSeriesModel, _super);

    function CandlestickSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CandlestickSeriesModel.type;
      _this.defaultValueDimensions = [{
        name: 'open',
        defaultTooltip: true
      }, {
        name: 'close',
        defaultTooltip: true
      }, {
        name: 'lowest',
        defaultTooltip: true
      }, {
        name: 'highest',
        defaultTooltip: true
      }];
      return _this;
    }

    CandlestickSeriesModel.prototype.getShadowDim = function () {
      return 'open';
    };

    CandlestickSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) {
      var itemLayout = data.getItemLayout(dataIndex);
      return itemLayout && selectors.rect(itemLayout.brushRect);
    };

    CandlestickSeriesModel.type = 'series.candlestick';
    CandlestickSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid'];
    CandlestickSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'cartesian2d',
      legendHoverLink: true,
      layout: null,
      clip: true,
      itemStyle: {
        color: '#c23531',
        color0: '#314656',
        borderWidth: 1,
        borderColor: '#c23531',
        borderColor0: '#314656'
      },
      emphasis: {
        scale: true,
        itemStyle: {
          borderWidth: 2
        }
      },
      barMaxWidth: null,
      barMinWidth: null,
      barWidth: null,
      large: true,
      largeThreshold: 600,
      progressive: 3e3,
      progressiveThreshold: 1e4,
      progressiveChunkMode: 'mod',
      animationEasing: 'linear',
      animationDuration: 300
    };
    return CandlestickSeriesModel;
  }(SeriesModel);

  mixin(CandlestickSeriesModel, WhiskerBoxCommonMixin, true);
  SeriesModel.registerClass(CandlestickSeriesModel);
  var SKIP_PROPS = ['color', 'borderColor'];

  var CandlestickView = function (_super) {
    __extends(CandlestickView, _super);

    function CandlestickView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CandlestickView.type;
      return _this;
    }

    CandlestickView.prototype.render = function (seriesModel, ecModel, api) {
      this.group.removeClipPath();

      this._updateDrawMode(seriesModel);

      this._isLargeDraw ? this._renderLarge(seriesModel) : this._renderNormal(seriesModel);
    };

    CandlestickView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
      this._clear();

      this._updateDrawMode(seriesModel);
    };

    CandlestickView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) {
      this._isLargeDraw ? this._incrementalRenderLarge(params, seriesModel) : this._incrementalRenderNormal(params, seriesModel);
    };

    CandlestickView.prototype._updateDrawMode = function (seriesModel) {
      var isLargeDraw = seriesModel.pipelineContext.large;

      if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) {
        this._isLargeDraw = isLargeDraw;

        this._clear();
      }
    };

    CandlestickView.prototype._renderNormal = function (seriesModel) {
      var data = seriesModel.getData();
      var oldData = this._data;
      var group = this.group;
      var isSimpleBox = data.getLayout('isSimpleBox');
      var needsClip = seriesModel.get('clip', true);
      var coord = seriesModel.coordinateSystem;
      var clipArea = coord.getArea && coord.getArea();

      if (!this._data) {
        group.removeAll();
      }

      data.diff(oldData).add(function (newIdx) {
        if (data.hasValue(newIdx)) {
          var itemLayout = data.getItemLayout(newIdx);

          if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
            return;
          }

          var el = createNormalBox$1(itemLayout, newIdx, true);
          initProps(el, {
            shape: {
              points: itemLayout.ends
            }
          }, seriesModel, newIdx);
          setBoxCommon(el, data, newIdx, isSimpleBox);
          group.add(el);
          data.setItemGraphicEl(newIdx, el);
        }
      }).update(function (newIdx, oldIdx) {
        var el = oldData.getItemGraphicEl(oldIdx);

        if (!data.hasValue(newIdx)) {
          group.remove(el);
          return;
        }

        var itemLayout = data.getItemLayout(newIdx);

        if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
          group.remove(el);
          return;
        }

        if (!el) {
          el = createNormalBox$1(itemLayout);
        } else {
          updateProps(el, {
            shape: {
              points: itemLayout.ends
            }
          }, seriesModel, newIdx);
        }

        setBoxCommon(el, data, newIdx, isSimpleBox);
        group.add(el);
        data.setItemGraphicEl(newIdx, el);
      }).remove(function (oldIdx) {
        var el = oldData.getItemGraphicEl(oldIdx);
        el && group.remove(el);
      }).execute();
      this._data = data;
    };

    CandlestickView.prototype._renderLarge = function (seriesModel) {
      this._clear();

      createLarge$1(seriesModel, this.group);
      var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null;

      if (clipPath) {
        this.group.setClipPath(clipPath);
      } else {
        this.group.removeClipPath();
      }
    };

    CandlestickView.prototype._incrementalRenderNormal = function (params, seriesModel) {
      var data = seriesModel.getData();
      var isSimpleBox = data.getLayout('isSimpleBox');
      var dataIndex;

      while ((dataIndex = params.next()) != null) {
        var itemLayout = data.getItemLayout(dataIndex);
        var el = createNormalBox$1(itemLayout);
        setBoxCommon(el, data, dataIndex, isSimpleBox);
        el.incremental = true;
        this.group.add(el);
      }
    };

    CandlestickView.prototype._incrementalRenderLarge = function (params, seriesModel) {
      createLarge$1(seriesModel, this.group, true);
    };

    CandlestickView.prototype.remove = function (ecModel) {
      this._clear();
    };

    CandlestickView.prototype._clear = function () {
      this.group.removeAll();
      this._data = null;
    };

    CandlestickView.type = 'candlestick';
    return CandlestickView;
  }(ChartView);

  ChartView.registerClass(CandlestickView);

  var NormalBoxPathShape = function () {
    function NormalBoxPathShape() {}

    return NormalBoxPathShape;
  }();

  var NormalBoxPath = function (_super) {
    __extends(NormalBoxPath, _super);

    function NormalBoxPath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'normalCandlestickBox';
      return _this;
    }

    NormalBoxPath.prototype.getDefaultShape = function () {
      return new NormalBoxPathShape();
    };

    NormalBoxPath.prototype.buildPath = function (ctx, shape) {
      var ends = shape.points;

      if (this.__simpleBox) {
        ctx.moveTo(ends[4][0], ends[4][1]);
        ctx.lineTo(ends[6][0], ends[6][1]);
      } else {
        ctx.moveTo(ends[0][0], ends[0][1]);
        ctx.lineTo(ends[1][0], ends[1][1]);
        ctx.lineTo(ends[2][0], ends[2][1]);
        ctx.lineTo(ends[3][0], ends[3][1]);
        ctx.closePath();
        ctx.moveTo(ends[4][0], ends[4][1]);
        ctx.lineTo(ends[5][0], ends[5][1]);
        ctx.moveTo(ends[6][0], ends[6][1]);
        ctx.lineTo(ends[7][0], ends[7][1]);
      }
    };

    return NormalBoxPath;
  }(Path);

  function createNormalBox$1(itemLayout, dataIndex, isInit) {
    var ends = itemLayout.ends;
    return new NormalBoxPath({
      shape: {
        points: isInit ? transInit$1(ends, itemLayout) : ends
      },
      z2: 100
    });
  }

  function isNormalBoxClipped(clipArea, itemLayout) {
    var clipped = true;

    for (var i = 0; i < itemLayout.ends.length; i++) {
      if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) {
        clipped = false;
        break;
      }
    }

    return clipped;
  }

  function setBoxCommon(el, data, dataIndex, isSimpleBox) {
    var itemModel = data.getItemModel(dataIndex);
    el.useStyle(data.getItemVisual(dataIndex, 'style'));
    el.style.strokeNoScale = true;
    el.__simpleBox = isSimpleBox;
    setStatesStylesFromModel(el, itemModel);
  }

  function transInit$1(points, itemLayout) {
    return map(points, function (point) {
      point = point.slice();
      point[1] = itemLayout.initBaseline;
      return point;
    });
  }

  var LargeBoxPathShape = function () {
    function LargeBoxPathShape() {}

    return LargeBoxPathShape;
  }();

  var LargeBoxPath = function (_super) {
    __extends(LargeBoxPath, _super);

    function LargeBoxPath(opts) {
      var _this = _super.call(this, opts) || this;

      _this.type = 'largeCandlestickBox';
      return _this;
    }

    LargeBoxPath.prototype.getDefaultShape = function () {
      return new LargeBoxPathShape();
    };

    LargeBoxPath.prototype.buildPath = function (ctx, shape) {
      var points = shape.points;

      for (var i = 0; i < points.length;) {
        if (this.__sign === points[i++]) {
          var x = points[i++];
          ctx.moveTo(x, points[i++]);
          ctx.lineTo(x, points[i++]);
        } else {
          i += 3;
        }
      }
    };

    return LargeBoxPath;
  }(Path);

  function createLarge$1(seriesModel, group, incremental) {
    var data = seriesModel.getData();
    var largePoints = data.getLayout('largePoints');
    var elP = new LargeBoxPath({
      shape: {
        points: largePoints
      },
      __sign: 1
    });
    group.add(elP);
    var elN = new LargeBoxPath({
      shape: {
        points: largePoints
      },
      __sign: -1
    });
    group.add(elN);
    setLargeStyle$1(1, elP, seriesModel);
    setLargeStyle$1(-1, elN, seriesModel);

    if (incremental) {
      elP.incremental = true;
      elN.incremental = true;
    }
  }

  function setLargeStyle$1(sign, el, seriesModel, data) {
    var borderColor = seriesModel.get(['itemStyle', sign > 0 ? 'borderColor' : 'borderColor0']) || seriesModel.get(['itemStyle', sign > 0 ? 'color' : 'color0']);
    var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(SKIP_PROPS);
    el.useStyle(itemStyle);
    el.style.fill = null;
    el.style.stroke = borderColor;
  }

  function candlestickPreprocessor(option) {
    if (!option || !isArray(option.series)) {
      return;
    }

    each(option.series, function (seriesItem) {
      if (isObject(seriesItem) && seriesItem.type === 'k') {
        seriesItem.type = 'candlestick';
      }
    });
  }

  var positiveBorderColorQuery = ['itemStyle', 'borderColor'];
  var negativeBorderColorQuery = ['itemStyle', 'borderColor0'];
  var positiveColorQuery = ['itemStyle', 'color'];
  var negativeColorQuery = ['itemStyle', 'color0'];
  var candlestickVisual = {
    seriesType: 'candlestick',
    plan: createRenderPlanner(),
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
      function getColor(sign, model) {
        return model.get(sign > 0 ? positiveColorQuery : negativeColorQuery);
      }

      function getBorderColor(sign, model) {
        return model.get(sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery);
      }

      var data = seriesModel.getData();
      data.setVisual('legendSymbol', 'roundRect');

      if (ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      var isLargeRender = seriesModel.pipelineContext.large;
      return !isLargeRender && {
        progress: function (params, data) {
          var dataIndex;

          while ((dataIndex = params.next()) != null) {
            var itemModel = data.getItemModel(dataIndex);
            var sign = data.getItemLayout(dataIndex).sign;
            var style = itemModel.getItemStyle();
            style.fill = getColor(sign, itemModel);
            style.stroke = getBorderColor(sign, itemModel) || style.fill;
            var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style');
            extend(existsStyle, style);
          }
        }
      };
    }
  };
  var LargeArr$1 = typeof Float32Array !== 'undefined' ? Float32Array : Array;
  var candlestickLayout = {
    seriesType: 'candlestick',
    plan: createRenderPlanner(),
    reset: function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var data = seriesModel.getData();
      var candleWidth = calculateCandleWidth(seriesModel, data);
      var cDimIdx = 0;
      var vDimIdx = 1;
      var coordDims = ['x', 'y'];
      var cDim = data.mapDimension(coordDims[cDimIdx]);
      var vDims = data.mapDimensionsAll(coordDims[vDimIdx]);
      var openDim = vDims[0];
      var closeDim = vDims[1];
      var lowestDim = vDims[2];
      var highestDim = vDims[3];
      data.setLayout({
        candleWidth: candleWidth,
        isSimpleBox: candleWidth <= 1.3
      });

      if (cDim == null || vDims.length < 4) {
        return;
      }

      return {
        progress: seriesModel.pipelineContext.large ? largeProgress : normalProgress
      };

      function normalProgress(params, data) {
        var dataIndex;

        while ((dataIndex = params.next()) != null) {
          var axisDimVal = data.get(cDim, dataIndex);
          var openVal = data.get(openDim, dataIndex);
          var closeVal = data.get(closeDim, dataIndex);
          var lowestVal = data.get(lowestDim, dataIndex);
          var highestVal = data.get(highestDim, dataIndex);
          var ocLow = Math.min(openVal, closeVal);
          var ocHigh = Math.max(openVal, closeVal);
          var ocLowPoint = getPoint(ocLow, axisDimVal);
          var ocHighPoint = getPoint(ocHigh, axisDimVal);
          var lowestPoint = getPoint(lowestVal, axisDimVal);
          var highestPoint = getPoint(highestVal, axisDimVal);
          var ends = [];
          addBodyEnd(ends, ocHighPoint, 0);
          addBodyEnd(ends, ocLowPoint, 1);
          ends.push(subPixelOptimizePoint(highestPoint), subPixelOptimizePoint(ocHighPoint), subPixelOptimizePoint(lowestPoint), subPixelOptimizePoint(ocLowPoint));
          data.setItemLayout(dataIndex, {
            sign: getSign(data, dataIndex, openVal, closeVal, closeDim),
            initBaseline: openVal > closeVal ? ocHighPoint[vDimIdx] : ocLowPoint[vDimIdx],
            ends: ends,
            brushRect: makeBrushRect(lowestVal, highestVal, axisDimVal)
          });
        }

        function getPoint(val, axisDimVal) {
          var p = [];
          p[cDimIdx] = axisDimVal;
          p[vDimIdx] = val;
          return isNaN(axisDimVal) || isNaN(val) ? [NaN, NaN] : coordSys.dataToPoint(p);
        }

        function addBodyEnd(ends, point, start) {
          var point1 = point.slice();
          var point2 = point.slice();
          point1[cDimIdx] = subPixelOptimize$1(point1[cDimIdx] + candleWidth / 2, 1, false);
          point2[cDimIdx] = subPixelOptimize$1(point2[cDimIdx] - candleWidth / 2, 1, true);
          start ? ends.push(point1, point2) : ends.push(point2, point1);
        }

        function makeBrushRect(lowestVal, highestVal, axisDimVal) {
          var pmin = getPoint(lowestVal, axisDimVal);
          var pmax = getPoint(highestVal, axisDimVal);
          pmin[cDimIdx] -= candleWidth / 2;
          pmax[cDimIdx] -= candleWidth / 2;
          return {
            x: pmin[0],
            y: pmin[1],
            width: candleWidth,
            height: pmax[1] - pmin[1]
          };
        }

        function subPixelOptimizePoint(point) {
          point[cDimIdx] = subPixelOptimize$1(point[cDimIdx], 1);
          return point;
        }
      }

      function largeProgress(params, data) {
        var points = new LargeArr$1(params.count * 4);
        var offset = 0;
        var point;
        var tmpIn = [];
        var tmpOut = [];
        var dataIndex;

        while ((dataIndex = params.next()) != null) {
          var axisDimVal = data.get(cDim, dataIndex);
          var openVal = data.get(openDim, dataIndex);
          var closeVal = data.get(closeDim, dataIndex);
          var lowestVal = data.get(lowestDim, dataIndex);
          var highestVal = data.get(highestDim, dataIndex);

          if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) {
            points[offset++] = NaN;
            offset += 3;
            continue;
          }

          points[offset++] = getSign(data, dataIndex, openVal, closeVal, closeDim);
          tmpIn[cDimIdx] = axisDimVal;
          tmpIn[vDimIdx] = lowestVal;
          point = coordSys.dataToPoint(tmpIn, null, tmpOut);
          points[offset++] = point ? point[0] : NaN;
          points[offset++] = point ? point[1] : NaN;
          tmpIn[vDimIdx] = highestVal;
          point = coordSys.dataToPoint(tmpIn, null, tmpOut);
          points[offset++] = point ? point[1] : NaN;
        }

        data.setLayout('largePoints', points);
      }
    }
  };

  function getSign(data, dataIndex, openVal, closeVal, closeDim) {
    var sign;

    if (openVal > closeVal) {
      sign = -1;
    } else if (openVal < closeVal) {
      sign = 1;
    } else {
      sign = dataIndex > 0 ? data.get(closeDim, dataIndex - 1) <= closeVal ? 1 : -1 : 1;
    }

    return sign;
  }

  function calculateCandleWidth(seriesModel, data) {
    var baseAxis = seriesModel.getBaseAxis();
    var extent;
    var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : (extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / data.count());
    var barMaxWidth = parsePercent$2(retrieve2(seriesModel.get('barMaxWidth'), bandWidth), bandWidth);
    var barMinWidth = parsePercent$2(retrieve2(seriesModel.get('barMinWidth'), 1), bandWidth);
    var barWidth = seriesModel.get('barWidth');
    return barWidth != null ? parsePercent$2(barWidth, bandWidth) : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
  }

  registerPreprocessor(candlestickPreprocessor);
  registerVisual(candlestickVisual);
  registerLayout(candlestickLayout);

  var EffectScatterSeriesModel = function (_super) {
    __extends(EffectScatterSeriesModel, _super);

    function EffectScatterSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = EffectScatterSeriesModel.type;
      _this.hasSymbolVisual = true;
      return _this;
    }

    EffectScatterSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this, {
        useEncodeDefaulter: true
      });
    };

    EffectScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) {
      return selectors.point(data.getItemLayout(dataIndex));
    };

    EffectScatterSeriesModel.type = 'series.effectScatter';
    EffectScatterSeriesModel.dependencies = ['grid', 'polar'];
    EffectScatterSeriesModel.defaultOption = {
      coordinateSystem: 'cartesian2d',
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      effectType: 'ripple',
      progressive: 0,
      showEffectOn: 'render',
      rippleEffect: {
        period: 4,
        scale: 2.5,
        brushType: 'fill'
      },
      symbolSize: 10
    };
    return EffectScatterSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(EffectScatterSeriesModel);
  var EFFECT_RIPPLE_NUMBER = 3;

  function normalizeSymbolSize$1(symbolSize) {
    if (!isArray(symbolSize)) {
      symbolSize = [+symbolSize, +symbolSize];
    }

    return symbolSize;
  }

  function updateRipplePath(rippleGroup, effectCfg) {
    var color = effectCfg.rippleEffectColor || effectCfg.color;
    rippleGroup.eachChild(function (ripplePath) {
      ripplePath.attr({
        z: effectCfg.z,
        zlevel: effectCfg.zlevel,
        style: {
          stroke: effectCfg.brushType === 'stroke' ? color : null,
          fill: effectCfg.brushType === 'fill' ? color : null
        }
      });
    });
  }

  var EffectSymbol = function (_super) {
    __extends(EffectSymbol, _super);

    function EffectSymbol(data, idx) {
      var _this = _super.call(this) || this;

      var symbol = new Symbol(data, idx);
      var rippleGroup = new Group();

      _this.add(symbol);

      _this.add(rippleGroup);

      _this.updateData(data, idx);

      return _this;
    }

    EffectSymbol.prototype.stopEffectAnimation = function () {
      this.childAt(1).removeAll();
    };

    EffectSymbol.prototype.startEffectAnimation = function (effectCfg) {
      var symbolType = effectCfg.symbolType;
      var color = effectCfg.color;
      var rippleGroup = this.childAt(1);

      for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) {
        var ripplePath = createSymbol(symbolType, -1, -1, 2, 2, color);
        ripplePath.attr({
          style: {
            strokeNoScale: true
          },
          z2: 99,
          silent: true,
          scaleX: 0.5,
          scaleY: 0.5
        });
        var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset;
        ripplePath.animate('', true).when(effectCfg.period, {
          scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2]
        }).delay(delay).start();
        ripplePath.animateStyle(true).when(effectCfg.period, {
          opacity: 0
        }).delay(delay).start();
        rippleGroup.add(ripplePath);
      }

      updateRipplePath(rippleGroup, effectCfg);
    };

    EffectSymbol.prototype.updateEffectAnimation = function (effectCfg) {
      var oldEffectCfg = this._effectCfg;
      var rippleGroup = this.childAt(1);
      var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale'];

      for (var i = 0; i < DIFFICULT_PROPS.length; i++) {
        var propName = DIFFICULT_PROPS[i];

        if (oldEffectCfg[propName] !== effectCfg[propName]) {
          this.stopEffectAnimation();
          this.startEffectAnimation(effectCfg);
          return;
        }
      }

      updateRipplePath(rippleGroup, effectCfg);
    };

    EffectSymbol.prototype.highlight = function () {
      enterEmphasis(this);
    };

    EffectSymbol.prototype.downplay = function () {
      leaveEmphasis(this);
    };

    EffectSymbol.prototype.updateData = function (data, idx) {
      var _this = this;

      var seriesModel = data.hostModel;
      this.childAt(0).updateData(data, idx);
      var rippleGroup = this.childAt(1);
      var itemModel = data.getItemModel(idx);
      var symbolType = data.getItemVisual(idx, 'symbol');
      var symbolSize = normalizeSymbolSize$1(data.getItemVisual(idx, 'symbolSize'));
      var symbolStyle = data.getItemVisual(idx, 'style');
      var color = symbolStyle && symbolStyle.fill;
      rippleGroup.setScale(symbolSize);
      rippleGroup.traverse(function (ripplePath) {
        ripplePath.setStyle('fill', color);
      });
      var symbolOffset = itemModel.getShallow('symbolOffset');

      if (symbolOffset) {
        rippleGroup.x = parsePercent$2(symbolOffset[0], symbolSize[0]);
        rippleGroup.y = parsePercent$2(symbolOffset[1], symbolSize[1]);
      }

      var symbolRotate = data.getItemVisual(idx, 'symbolRotate');
      rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
      var effectCfg = {};
      effectCfg.showEffectOn = seriesModel.get('showEffectOn');
      effectCfg.rippleScale = itemModel.get(['rippleEffect', 'scale']);
      effectCfg.brushType = itemModel.get(['rippleEffect', 'brushType']);
      effectCfg.period = itemModel.get(['rippleEffect', 'period']) * 1000;
      effectCfg.effectOffset = idx / data.count();
      effectCfg.z = seriesModel.getShallow('z') || 0;
      effectCfg.zlevel = seriesModel.getShallow('zlevel') || 0;
      effectCfg.symbolType = symbolType;
      effectCfg.color = color;
      effectCfg.rippleEffectColor = itemModel.get(['rippleEffect', 'color']);
      this.off('mouseover').off('mouseout').off('emphasis').off('normal');

      if (effectCfg.showEffectOn === 'render') {
        this._effectCfg ? this.updateEffectAnimation(effectCfg) : this.startEffectAnimation(effectCfg);
        this._effectCfg = effectCfg;
      } else {
        this._effectCfg = null;
        this.stopEffectAnimation();

        this.onHoverStateChange = function (toState) {
          if (toState === 'emphasis') {
            if (effectCfg.showEffectOn !== 'render') {
              _this.startEffectAnimation(effectCfg);
            }
          } else if (toState === 'normal') {
            if (effectCfg.showEffectOn !== 'render') {
              _this.stopEffectAnimation();
            }
          }
        };
      }

      this._effectCfg = effectCfg;
      enableHoverEmphasis(this);
    };

    EffectSymbol.prototype.fadeOut = function (cb) {
      this.off('mouseover').off('mouseout');
      cb && cb();
    };

    return EffectSymbol;
  }(Group);

  inherits(EffectSymbol, Group);

  var EffectScatterView = function (_super) {
    __extends(EffectScatterView, _super);

    function EffectScatterView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = EffectScatterView.type;
      return _this;
    }

    EffectScatterView.prototype.init = function () {
      this._symbolDraw = new SymbolDraw(EffectSymbol);
    };

    EffectScatterView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var effectSymbolDraw = this._symbolDraw;
      effectSymbolDraw.updateData(data);
      this.group.add(effectSymbolDraw.group);
    };

    EffectScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      this.group.dirty();
      var res = pointsLayout('').reset(seriesModel, ecModel, api);

      if (res.progress) {
        res.progress({
          start: 0,
          end: data.count(),
          count: data.count()
        }, data);
      }

      this._symbolDraw.updateLayout();
    };

    EffectScatterView.prototype._updateGroupTransform = function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys && coordSys.getRoamTransform) {
        this.group.transform = clone$2(coordSys.getRoamTransform());
        this.group.decomposeTransform();
      }
    };

    EffectScatterView.prototype.remove = function (ecModel, api) {
      this._symbolDraw && this._symbolDraw.remove(true);
    };

    EffectScatterView.type = 'effectScatter';
    return EffectScatterView;
  }(ChartView);

  ChartView.registerClass(EffectScatterView);
  registerLayout(pointsLayout('effectScatter'));
  var Uint32Arr = typeof Uint32Array === 'undefined' ? Array : Uint32Array;
  var Float64Arr = typeof Float64Array === 'undefined' ? Array : Float64Array;

  function compatEc2(seriesOpt) {
    var data = seriesOpt.data;

    if (data && data[0] && data[0][0] && data[0][0].coord) {
      if (true) {
        console.warn('Lines data configuration has been changed to' + ' { coords:[[1,2],[2,3]] }');
      }

      seriesOpt.data = map(data, function (itemOpt) {
        var coords = [itemOpt[0].coord, itemOpt[1].coord];
        var target = {
          coords: coords
        };

        if (itemOpt[0].name) {
          target.fromName = itemOpt[0].name;
        }

        if (itemOpt[1].name) {
          target.toName = itemOpt[1].name;
        }

        return mergeAll([target, itemOpt[0], itemOpt[1]]);
      });
    }
  }

  var LinesSeriesModel = function (_super) {
    __extends(LinesSeriesModel, _super);

    function LinesSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = LinesSeriesModel.type;
      _this.visualStyleAccessPath = 'lineStyle';
      _this.visualDrawType = 'stroke';
      return _this;
    }

    LinesSeriesModel.prototype.init = function (option) {
      option.data = option.data || [];
      compatEc2(option);

      var result = this._processFlatCoordsArray(option.data);

      this._flatCoords = result.flatCoords;
      this._flatCoordsOffset = result.flatCoordsOffset;

      if (result.flatCoords) {
        option.data = new Float32Array(result.count);
      }

      _super.prototype.init.apply(this, arguments);
    };

    LinesSeriesModel.prototype.mergeOption = function (option) {
      compatEc2(option);

      if (option.data) {
        var result = this._processFlatCoordsArray(option.data);

        this._flatCoords = result.flatCoords;
        this._flatCoordsOffset = result.flatCoordsOffset;

        if (result.flatCoords) {
          option.data = new Float32Array(result.count);
        }
      }

      _super.prototype.mergeOption.apply(this, arguments);
    };

    LinesSeriesModel.prototype.appendData = function (params) {
      var result = this._processFlatCoordsArray(params.data);

      if (result.flatCoords) {
        if (!this._flatCoords) {
          this._flatCoords = result.flatCoords;
          this._flatCoordsOffset = result.flatCoordsOffset;
        } else {
          this._flatCoords = concatArray(this._flatCoords, result.flatCoords);
          this._flatCoordsOffset = concatArray(this._flatCoordsOffset, result.flatCoordsOffset);
        }

        params.data = new Float32Array(result.count);
      }

      this.getRawData().appendData(params.data);
    };

    LinesSeriesModel.prototype._getCoordsFromItemModel = function (idx) {
      var itemModel = this.getData().getItemModel(idx);
      var coords = itemModel.option instanceof Array ? itemModel.option : itemModel.getShallow('coords');

      if (true) {
        if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) {
          throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.');
        }
      }

      return coords;
    };

    LinesSeriesModel.prototype.getLineCoordsCount = function (idx) {
      if (this._flatCoordsOffset) {
        return this._flatCoordsOffset[idx * 2 + 1];
      } else {
        return this._getCoordsFromItemModel(idx).length;
      }
    };

    LinesSeriesModel.prototype.getLineCoords = function (idx, out) {
      if (this._flatCoordsOffset) {
        var offset = this._flatCoordsOffset[idx * 2];
        var len = this._flatCoordsOffset[idx * 2 + 1];

        for (var i = 0; i < len; i++) {
          out[i] = out[i] || [];
          out[i][0] = this._flatCoords[offset + i * 2];
          out[i][1] = this._flatCoords[offset + i * 2 + 1];
        }

        return len;
      } else {
        var coords = this._getCoordsFromItemModel(idx);

        for (var i = 0; i < coords.length; i++) {
          out[i] = out[i] || [];
          out[i][0] = coords[i][0];
          out[i][1] = coords[i][1];
        }

        return coords.length;
      }
    };

    LinesSeriesModel.prototype._processFlatCoordsArray = function (data) {
      var startOffset = 0;

      if (this._flatCoords) {
        startOffset = this._flatCoords.length;
      }

      if (typeof data[0] === 'number') {
        var len = data.length;
        var coordsOffsetAndLenStorage = new Uint32Arr(len);
        var coordsStorage = new Float64Arr(len);
        var coordsCursor = 0;
        var offsetCursor = 0;
        var dataCount = 0;

        for (var i = 0; i < len;) {
          dataCount++;
          var count = data[i++];
          coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset;
          coordsOffsetAndLenStorage[offsetCursor++] = count;

          for (var k = 0; k < count; k++) {
            var x = data[i++];
            var y = data[i++];
            coordsStorage[coordsCursor++] = x;
            coordsStorage[coordsCursor++] = y;

            if (i > len) {
              if (true) {
                throw new Error('Invalid data format.');
              }
            }
          }
        }

        return {
          flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor),
          flatCoords: coordsStorage,
          count: dataCount
        };
      }

      return {
        flatCoordsOffset: null,
        flatCoords: null,
        count: data.length
      };
    };

    LinesSeriesModel.prototype.getInitialData = function (option, ecModel) {
      if (true) {
        var CoordSys = CoordinateSystemManager.get(option.coordinateSystem);

        if (!CoordSys) {
          throw new Error('Unkown coordinate system ' + option.coordinateSystem);
        }
      }

      var lineData = new List(['value'], this);
      lineData.hasItemOption = false;
      lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) {
        if (dataItem instanceof Array) {
          return NaN;
        } else {
          lineData.hasItemOption = true;
          var value = dataItem.value;

          if (value != null) {
            return value instanceof Array ? value[dimIndex] : value;
          }
        }
      });
      return lineData;
    };

    LinesSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var itemModel = data.getItemModel(dataIndex);
      var name = itemModel.get('name');

      if (name) {
        return name;
      }

      var fromName = itemModel.get('fromName');
      var toName = itemModel.get('toName');
      var nameArr = [];
      fromName != null && nameArr.push(fromName);
      toName != null && nameArr.push(toName);
      return createTooltipMarkup('nameValue', {
        name: nameArr.join(' > ')
      });
    };

    LinesSeriesModel.prototype.preventIncremental = function () {
      return !!this.get(['effect', 'show']);
    };

    LinesSeriesModel.prototype.getProgressive = function () {
      var progressive = this.option.progressive;

      if (progressive == null) {
        return this.option.large ? 1e4 : this.get('progressive');
      }

      return progressive;
    };

    LinesSeriesModel.prototype.getProgressiveThreshold = function () {
      var progressiveThreshold = this.option.progressiveThreshold;

      if (progressiveThreshold == null) {
        return this.option.large ? 2e4 : this.get('progressiveThreshold');
      }

      return progressiveThreshold;
    };

    LinesSeriesModel.type = 'series.lines';
    LinesSeriesModel.dependencies = ['grid', 'polar', 'geo', 'calendar'];
    LinesSeriesModel.defaultOption = {
      coordinateSystem: 'geo',
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      xAxisIndex: 0,
      yAxisIndex: 0,
      symbol: ['none', 'none'],
      symbolSize: [10, 10],
      geoIndex: 0,
      effect: {
        show: false,
        period: 4,
        constantSpeed: 0,
        symbol: 'circle',
        symbolSize: 3,
        loop: true,
        trailLength: 0.2
      },
      large: false,
      largeThreshold: 2000,
      polyline: false,
      clip: true,
      label: {
        show: false,
        position: 'end'
      },
      lineStyle: {
        opacity: 0.5
      }
    };
    return LinesSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(LinesSeriesModel);

  var EffectLine = function (_super) {
    __extends(EffectLine, _super);

    function EffectLine(lineData, idx, seriesScope) {
      var _this = _super.call(this) || this;

      _this.add(_this.createLine(lineData, idx, seriesScope));

      _this._updateEffectSymbol(lineData, idx);

      return _this;
    }

    EffectLine.prototype.createLine = function (lineData, idx, seriesScope) {
      return new Line$1(lineData, idx, seriesScope);
    };

    EffectLine.prototype._updateEffectSymbol = function (lineData, idx) {
      var itemModel = lineData.getItemModel(idx);
      var effectModel = itemModel.getModel('effect');
      var size = effectModel.get('symbolSize');
      var symbolType = effectModel.get('symbol');

      if (!isArray(size)) {
        size = [size, size];
      }

      var lineStyle = lineData.getItemVisual(idx, 'style');
      var color = effectModel.get('color') || lineStyle && lineStyle.stroke;
      var symbol = this.childAt(1);

      if (this._symbolType !== symbolType) {
        this.remove(symbol);
        symbol = createSymbol(symbolType, -0.5, -0.5, 1, 1, color);
        symbol.z2 = 100;
        symbol.culling = true;
        this.add(symbol);
      }

      if (!symbol) {
        return;
      }

      symbol.setStyle('shadowColor', color);
      symbol.setStyle(effectModel.getItemStyle(['color']));
      symbol.scaleX = size[0];
      symbol.scaleY = size[1];
      symbol.setColor(color);
      this._symbolType = symbolType;
      this._symbolScale = size;

      this._updateEffectAnimation(lineData, effectModel, idx);
    };

    EffectLine.prototype._updateEffectAnimation = function (lineData, effectModel, idx) {
      var symbol = this.childAt(1);

      if (!symbol) {
        return;
      }

      var self = this;
      var points = lineData.getItemLayout(idx);
      var period = effectModel.get('period') * 1000;
      var loop = effectModel.get('loop');
      var constantSpeed = effectModel.get('constantSpeed');
      var delayExpr = retrieve(effectModel.get('delay'), function (idx) {
        return idx / lineData.count() * period / 3;
      });
      symbol.ignore = true;

      this._updateAnimationPoints(symbol, points);

      if (constantSpeed > 0) {
        period = this._getLineLength(symbol) / constantSpeed * 1000;
      }

      if (period !== this._period || loop !== this._loop) {
        symbol.stopAnimation();

        if (period > 0) {
          var delayNum = void 0;

          if (typeof delayExpr === 'function') {
            delayNum = delayExpr(idx);
          } else {
            delayNum = delayExpr;
          }

          if (symbol.__t > 0) {
            delayNum = -period * symbol.__t;
          }

          symbol.__t = 0;
          var animator = symbol.animate('', loop).when(period, {
            __t: 1
          }).delay(delayNum).during(function () {
            self._updateSymbolPosition(symbol);
          });

          if (!loop) {
            animator.done(function () {
              self.remove(symbol);
            });
          }

          animator.start();
        }
      }

      this._period = period;
      this._loop = loop;
    };

    EffectLine.prototype._getLineLength = function (symbol) {
      return dist(symbol.__p1, symbol.__cp1) + dist(symbol.__cp1, symbol.__p2);
    };

    EffectLine.prototype._updateAnimationPoints = function (symbol, points) {
      symbol.__p1 = points[0];
      symbol.__p2 = points[1];
      symbol.__cp1 = points[2] || [(points[0][0] + points[1][0]) / 2, (points[0][1] + points[1][1]) / 2];
    };

    EffectLine.prototype.updateData = function (lineData, idx, seriesScope) {
      this.childAt(0).updateData(lineData, idx, seriesScope);

      this._updateEffectSymbol(lineData, idx);
    };

    EffectLine.prototype._updateSymbolPosition = function (symbol) {
      var p1 = symbol.__p1;
      var p2 = symbol.__p2;
      var cp1 = symbol.__cp1;
      var t = symbol.__t;
      var pos = [symbol.x, symbol.y];
      var lastPos = pos.slice();
      var quadraticAt$1 = quadraticAt;
      var quadraticDerivativeAt$1 = quadraticDerivativeAt;
      pos[0] = quadraticAt$1(p1[0], cp1[0], p2[0], t);
      pos[1] = quadraticAt$1(p1[1], cp1[1], p2[1], t);
      var tx = quadraticDerivativeAt$1(p1[0], cp1[0], p2[0], t);
      var ty = quadraticDerivativeAt$1(p1[1], cp1[1], p2[1], t);
      symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;

      if (this._symbolType === 'line' || this._symbolType === 'rect' || this._symbolType === 'roundRect') {
        if (symbol.__lastT !== undefined && symbol.__lastT < symbol.__t) {
          symbol.scaleY = dist(lastPos, pos) * 1.05;

          if (t === 1) {
            pos[0] = lastPos[0] + (pos[0] - lastPos[0]) / 2;
            pos[1] = lastPos[1] + (pos[1] - lastPos[1]) / 2;
          }
        } else if (symbol.__lastT === 1) {
          symbol.scaleY = 2 * dist(p1, pos);
        } else {
          symbol.scaleY = this._symbolScale[1];
        }
      }

      symbol.__lastT = symbol.__t;
      symbol.ignore = false;
      symbol.x = pos[0];
      symbol.y = pos[1];
    };

    EffectLine.prototype.updateLayout = function (lineData, idx) {
      this.childAt(0).updateLayout(lineData, idx);
      var effectModel = lineData.getItemModel(idx).getModel('effect');

      this._updateEffectAnimation(lineData, effectModel, idx);
    };

    return EffectLine;
  }(Group);

  var Polyline$1 = function (_super) {
    __extends(Polyline$1, _super);

    function Polyline$1(lineData, idx, seriesScope) {
      var _this = _super.call(this) || this;

      _this._createPolyline(lineData, idx, seriesScope);

      return _this;
    }

    Polyline$1.prototype._createPolyline = function (lineData, idx, seriesScope) {
      var points = lineData.getItemLayout(idx);
      var line = new Polyline({
        shape: {
          points: points
        }
      });
      this.add(line);

      this._updateCommonStl(lineData, idx, seriesScope);
    };

    Polyline$1.prototype.updateData = function (lineData, idx, seriesScope) {
      var seriesModel = lineData.hostModel;
      var line = this.childAt(0);
      var target = {
        shape: {
          points: lineData.getItemLayout(idx)
        }
      };
      updateProps(line, target, seriesModel, idx);

      this._updateCommonStl(lineData, idx, seriesScope);
    };

    Polyline$1.prototype._updateCommonStl = function (lineData, idx, seriesScope) {
      var line = this.childAt(0);
      var itemModel = lineData.getItemModel(idx);
      var hoverLineStyle = seriesScope && seriesScope.emphasisLineStyle;

      if (!seriesScope || lineData.hasItemOption) {
        hoverLineStyle = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle();
      }

      line.useStyle(lineData.getItemVisual(idx, 'style'));
      line.style.fill = null;
      line.style.strokeNoScale = true;
      var lineEmphasisState = line.ensureState('emphasis');
      lineEmphasisState.style = hoverLineStyle;
      enableHoverEmphasis(this);
    };

    Polyline$1.prototype.updateLayout = function (lineData, idx) {
      var polyline = this.childAt(0);
      polyline.setShape('points', lineData.getItemLayout(idx));
    };

    return Polyline$1;
  }(Group);

  var EffectPolyline = function (_super) {
    __extends(EffectPolyline, _super);

    function EffectPolyline() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this._lastFrame = 0;
      _this._lastFramePercent = 0;
      return _this;
    }

    EffectPolyline.prototype.createLine = function (lineData, idx, seriesScope) {
      return new Polyline$1(lineData, idx, seriesScope);
    };

    EffectPolyline.prototype._updateAnimationPoints = function (symbol, points) {
      this._points = points;
      var accLenArr = [0];
      var len = 0;

      for (var i = 1; i < points.length; i++) {
        var p1 = points[i - 1];
        var p2 = points[i];
        len += dist(p1, p2);
        accLenArr.push(len);
      }

      if (len === 0) {
        this._length = 0;
        return;
      }

      for (var i = 0; i < accLenArr.length; i++) {
        accLenArr[i] /= len;
      }

      this._offsets = accLenArr;
      this._length = len;
    };

    EffectPolyline.prototype._getLineLength = function () {
      return this._length;
    };

    EffectPolyline.prototype._updateSymbolPosition = function (symbol) {
      var t = symbol.__t;
      var points = this._points;
      var offsets = this._offsets;
      var len = points.length;

      if (!offsets) {
        return;
      }

      var lastFrame = this._lastFrame;
      var frame;

      if (t < this._lastFramePercent) {
        var start = Math.min(lastFrame + 1, len - 1);

        for (frame = start; frame >= 0; frame--) {
          if (offsets[frame] <= t) {
            break;
          }
        }

        frame = Math.min(frame, len - 2);
      } else {
        for (frame = lastFrame; frame < len; frame++) {
          if (offsets[frame] > t) {
            break;
          }
        }

        frame = Math.min(frame - 1, len - 2);
      }

      var p = (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame]);
      var p0 = points[frame];
      var p1 = points[frame + 1];
      symbol.x = p0[0] * (1 - p) + p * p1[0];
      symbol.y = p0[1] * (1 - p) + p * p1[1];
      var tx = p1[0] - p0[0];
      var ty = p1[1] - p0[1];
      symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
      this._lastFrame = frame;
      this._lastFramePercent = t;
      symbol.ignore = false;
    };

    return EffectPolyline;
  }(EffectLine);

  var LargeLinesPathShape = function () {
    function LargeLinesPathShape() {
      this.polyline = false;
      this.curveness = 0;
      this.segs = [];
    }

    return LargeLinesPathShape;
  }();

  var LargeLinesPath = function (_super) {
    __extends(LargeLinesPath, _super);

    function LargeLinesPath(opts) {
      return _super.call(this, opts) || this;
    }

    LargeLinesPath.prototype.getDefaultStyle = function () {
      return {
        stroke: '#000',
        fill: null
      };
    };

    LargeLinesPath.prototype.getDefaultShape = function () {
      return new LargeLinesPathShape();
    };

    LargeLinesPath.prototype.buildPath = function (ctx, shape) {
      var segs = shape.segs;
      var curveness = shape.curveness;

      if (shape.polyline) {
        for (var i = 0; i < segs.length;) {
          var count = segs[i++];

          if (count > 0) {
            ctx.moveTo(segs[i++], segs[i++]);

            for (var k = 1; k < count; k++) {
              ctx.lineTo(segs[i++], segs[i++]);
            }
          }
        }
      } else {
        for (var i = 0; i < segs.length;) {
          var x0 = segs[i++];
          var y0 = segs[i++];
          var x1 = segs[i++];
          var y1 = segs[i++];
          ctx.moveTo(x0, y0);

          if (curveness > 0) {
            var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
            var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;
            ctx.quadraticCurveTo(x2, y2, x1, y1);
          } else {
            ctx.lineTo(x1, y1);
          }
        }
      }
    };

    LargeLinesPath.prototype.findDataIndex = function (x, y) {
      var shape = this.shape;
      var segs = shape.segs;
      var curveness = shape.curveness;
      var lineWidth = this.style.lineWidth;

      if (shape.polyline) {
        var dataIndex = 0;

        for (var i = 0; i < segs.length;) {
          var count = segs[i++];

          if (count > 0) {
            var x0 = segs[i++];
            var y0 = segs[i++];

            for (var k = 1; k < count; k++) {
              var x1 = segs[i++];
              var y1 = segs[i++];

              if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) {
                return dataIndex;
              }
            }
          }

          dataIndex++;
        }
      } else {
        var dataIndex = 0;

        for (var i = 0; i < segs.length;) {
          var x0 = segs[i++];
          var y0 = segs[i++];
          var x1 = segs[i++];
          var y1 = segs[i++];

          if (curveness > 0) {
            var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
            var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;

            if (containStroke$2(x0, y0, x2, y2, x1, y1, lineWidth, x, y)) {
              return dataIndex;
            }
          } else {
            if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) {
              return dataIndex;
            }
          }

          dataIndex++;
        }
      }

      return -1;
    };

    return LargeLinesPath;
  }(Path);

  var LargeLineDraw = function () {
    function LargeLineDraw() {
      this.group = new Group();
    }

    LargeLineDraw.prototype.isPersistent = function () {
      return !this._incremental;
    };

    LargeLineDraw.prototype.updateData = function (data) {
      this.group.removeAll();
      var lineEl = new LargeLinesPath({
        rectHover: true,
        cursor: 'default'
      });
      lineEl.setShape({
        segs: data.getLayout('linesPoints')
      });

      this._setCommon(lineEl, data);

      this.group.add(lineEl);
      this._incremental = null;
    };

    LargeLineDraw.prototype.incrementalPrepareUpdate = function (data) {
      this.group.removeAll();

      this._clearIncremental();

      if (data.count() > 5e5) {
        if (!this._incremental) {
          this._incremental = new IncrementalDisplayble({
            silent: true
          });
        }

        this.group.add(this._incremental);
      } else {
        this._incremental = null;
      }
    };

    LargeLineDraw.prototype.incrementalUpdate = function (taskParams, data) {
      var lineEl = new LargeLinesPath();
      lineEl.setShape({
        segs: data.getLayout('linesPoints')
      });

      this._setCommon(lineEl, data, !!this._incremental);

      if (!this._incremental) {
        lineEl.rectHover = true;
        lineEl.cursor = 'default';
        lineEl.__startIndex = taskParams.start;
        this.group.add(lineEl);
      } else {
        this._incremental.addDisplayable(lineEl, true);
      }
    };

    LargeLineDraw.prototype.remove = function () {
      this._clearIncremental();

      this._incremental = null;
      this.group.removeAll();
    };

    LargeLineDraw.prototype._setCommon = function (lineEl, data, isIncremental) {
      var hostModel = data.hostModel;
      lineEl.setShape({
        polyline: hostModel.get('polyline'),
        curveness: hostModel.get(['lineStyle', 'curveness'])
      });
      lineEl.useStyle(hostModel.getModel('lineStyle').getLineStyle());
      lineEl.style.strokeNoScale = true;
      var style = data.getVisual('style');

      if (style && style.stroke) {
        lineEl.setStyle('stroke', style.stroke);
      }

      lineEl.setStyle('fill', null);

      if (!isIncremental) {
        var ecData_1 = getECData(lineEl);
        ecData_1.seriesIndex = hostModel.seriesIndex;
        lineEl.on('mousemove', function (e) {
          ecData_1.dataIndex = null;
          var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY);

          if (dataIndex > 0) {
            ecData_1.dataIndex = dataIndex + lineEl.__startIndex;
          }
        });
      }
    };

    LargeLineDraw.prototype._clearIncremental = function () {
      var incremental = this._incremental;

      if (incremental) {
        incremental.clearDisplaybles();
      }
    };

    return LargeLineDraw;
  }();

  var linesLayout = {
    seriesType: 'lines',
    plan: createRenderPlanner(),
    reset: function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      var isPolyline = seriesModel.get('polyline');
      var isLarge = seriesModel.pipelineContext.large;
      return {
        progress: function (params, lineData) {
          var lineCoords = [];

          if (isLarge) {
            var points = void 0;
            var segCount = params.end - params.start;

            if (isPolyline) {
              var totalCoordsCount = 0;

              for (var i = params.start; i < params.end; i++) {
                totalCoordsCount += seriesModel.getLineCoordsCount(i);
              }

              points = new Float32Array(segCount + totalCoordsCount * 2);
            } else {
              points = new Float32Array(segCount * 4);
            }

            var offset = 0;
            var pt = [];

            for (var i = params.start; i < params.end; i++) {
              var len = seriesModel.getLineCoords(i, lineCoords);

              if (isPolyline) {
                points[offset++] = len;
              }

              for (var k = 0; k < len; k++) {
                pt = coordSys.dataToPoint(lineCoords[k], false, pt);
                points[offset++] = pt[0];
                points[offset++] = pt[1];
              }
            }

            lineData.setLayout('linesPoints', points);
          } else {
            for (var i = params.start; i < params.end; i++) {
              var itemModel = lineData.getItemModel(i);
              var len = seriesModel.getLineCoords(i, lineCoords);
              var pts = [];

              if (isPolyline) {
                for (var j = 0; j < len; j++) {
                  pts.push(coordSys.dataToPoint(lineCoords[j]));
                }
              } else {
                pts[0] = coordSys.dataToPoint(lineCoords[0]);
                pts[1] = coordSys.dataToPoint(lineCoords[1]);
                var curveness = itemModel.get(['lineStyle', 'curveness']);

                if (+curveness) {
                  pts[2] = [(pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness, (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness];
                }
              }

              lineData.setItemLayout(i, pts);
            }
          }
        }
      };
    }
  };

  var LinesView = function (_super) {
    __extends(LinesView, _super);

    function LinesView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = LinesView.type;
      return _this;
    }

    LinesView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();

      var lineDraw = this._updateLineDraw(data, seriesModel);

      var zlevel = seriesModel.get('zlevel');
      var trailLength = seriesModel.get(['effect', 'trailLength']);
      var zr = api.getZr();
      var isSvg = zr.painter.getType() === 'svg';

      if (!isSvg) {
        zr.painter.getLayer(zlevel).clear(true);
      }

      if (this._lastZlevel != null && !isSvg) {
        zr.configLayer(this._lastZlevel, {
          motionBlur: false
        });
      }

      if (this._showEffect(seriesModel) && trailLength) {
        if (true) {
          var notInIndividual_1 = false;
          ecModel.eachSeries(function (otherSeriesModel) {
            if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) {
              notInIndividual_1 = true;
            }
          });
          notInIndividual_1 && console.warn('Lines with trail effect should have an individual zlevel');
        }

        if (!isSvg) {
          zr.configLayer(zlevel, {
            motionBlur: true,
            lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0)
          });
        }
      }

      lineDraw.updateData(data);
      var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel);

      if (clipPath) {
        this.group.setClipPath(clipPath);
      } else {
        this.group.removeClipPath();
      }

      this._lastZlevel = zlevel;
      this._finished = true;
    };

    LinesView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();

      var lineDraw = this._updateLineDraw(data, seriesModel);

      lineDraw.incrementalPrepareUpdate(data);

      this._clearLayer(api);

      this._finished = false;
    };

    LinesView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) {
      this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData());

      this._finished = taskParams.end === seriesModel.getData().count();
    };

    LinesView.prototype.updateTransform = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var pipelineContext = seriesModel.pipelineContext;

      if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) {
        return {
          update: true
        };
      } else {
        var res = linesLayout.reset(seriesModel, ecModel, api);

        if (res.progress) {
          res.progress({
            start: 0,
            end: data.count(),
            count: data.count()
          }, data);
        }

        this._lineDraw.updateLayout();

        this._clearLayer(api);
      }
    };

    LinesView.prototype._updateLineDraw = function (data, seriesModel) {
      var lineDraw = this._lineDraw;

      var hasEffect = this._showEffect(seriesModel);

      var isPolyline = !!seriesModel.get('polyline');
      var pipelineContext = seriesModel.pipelineContext;
      var isLargeDraw = pipelineContext.large;

      if (true) {
        if (hasEffect && isLargeDraw) {
          console.warn('Large lines not support effect');
        }
      }

      if (!lineDraw || hasEffect !== this._hasEffet || isPolyline !== this._isPolyline || isLargeDraw !== this._isLargeDraw) {
        if (lineDraw) {
          lineDraw.remove();
        }

        lineDraw = this._lineDraw = isLargeDraw ? new LargeLineDraw() : new LineDraw(isPolyline ? hasEffect ? EffectPolyline : Polyline$1 : hasEffect ? EffectLine : Line$1);
        this._hasEffet = hasEffect;
        this._isPolyline = isPolyline;
        this._isLargeDraw = isLargeDraw;
        this.group.removeAll();
      }

      this.group.add(lineDraw.group);
      return lineDraw;
    };

    LinesView.prototype._showEffect = function (seriesModel) {
      return !!seriesModel.get(['effect', 'show']);
    };

    LinesView.prototype._clearLayer = function (api) {
      var zr = api.getZr();
      var isSvg = zr.painter.getType() === 'svg';

      if (!isSvg && this._lastZlevel != null) {
        zr.painter.getLayer(this._lastZlevel).clear(true);
      }
    };

    LinesView.prototype.remove = function (ecModel, api) {
      this._lineDraw && this._lineDraw.remove();
      this._lineDraw = null;

      this._clearLayer(api);
    };

    LinesView.type = 'lines';
    return LinesView;
  }(ChartView);

  ChartView.registerClass(LinesView);

  function normalize$3(a) {
    if (!(a instanceof Array)) {
      a = [a, a];
    }

    return a;
  }

  var linesVisual = {
    seriesType: 'lines',
    reset: function (seriesModel) {
      var symbolType = normalize$3(seriesModel.get('symbol'));
      var symbolSize = normalize$3(seriesModel.get('symbolSize'));
      var data = seriesModel.getData();
      data.setVisual('fromSymbol', symbolType && symbolType[0]);
      data.setVisual('toSymbol', symbolType && symbolType[1]);
      data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
      data.setVisual('toSymbolSize', symbolSize && symbolSize[1]);

      function dataEach(data, idx) {
        var itemModel = data.getItemModel(idx);
        var symbolType = normalize$3(itemModel.getShallow('symbol', true));
        var symbolSize = normalize$3(itemModel.getShallow('symbolSize', true));
        symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]);
        symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]);
        symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]);
        symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]);
      }

      return {
        dataEach: data.hasItemOption ? dataEach : null
      };
    }
  };
  registerLayout(linesLayout);
  registerVisual(linesVisual);

  var HeatmapSeriesModel = function (_super) {
    __extends(HeatmapSeriesModel, _super);

    function HeatmapSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = HeatmapSeriesModel.type;
      return _this;
    }

    HeatmapSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this, {
        generateCoord: 'value'
      });
    };

    HeatmapSeriesModel.prototype.preventIncremental = function () {
      var coordSysCreator = CoordinateSystemManager.get(this.get('coordinateSystem'));

      if (coordSysCreator && coordSysCreator.dimensions) {
        return coordSysCreator.dimensions[0] === 'lng' && coordSysCreator.dimensions[1] === 'lat';
      }
    };

    HeatmapSeriesModel.type = 'series.heatmap';
    HeatmapSeriesModel.defaultOption = {
      coordinateSystem: 'cartesian2d',
      zlevel: 0,
      z: 2,
      geoIndex: 0,
      blurSize: 30,
      pointSize: 20,
      maxOpacity: 1,
      minOpacity: 0,
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      }
    };
    return HeatmapSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(HeatmapSeriesModel);
  var GRADIENT_LEVELS = 256;

  var HeatmapLayer = function () {
    function HeatmapLayer() {
      this.blurSize = 30;
      this.pointSize = 20;
      this.maxOpacity = 1;
      this.minOpacity = 0;
      this._gradientPixels = {
        inRange: null,
        outOfRange: null
      };
      var canvas = createCanvas();
      this.canvas = canvas;
    }

    HeatmapLayer.prototype.update = function (data, width, height, normalize, colorFunc, isInRange) {
      var brush = this._getBrush();

      var gradientInRange = this._getGradient(colorFunc, 'inRange');

      var gradientOutOfRange = this._getGradient(colorFunc, 'outOfRange');

      var r = this.pointSize + this.blurSize;
      var canvas = this.canvas;
      var ctx = canvas.getContext('2d');
      var len = data.length;
      canvas.width = width;
      canvas.height = height;

      for (var i = 0; i < len; ++i) {
        var p = data[i];
        var x = p[0];
        var y = p[1];
        var value = p[2];
        var alpha = normalize(value);
        ctx.globalAlpha = alpha;
        ctx.drawImage(brush, x - r, y - r);
      }

      if (!canvas.width || !canvas.height) {
        return canvas;
      }

      var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      var pixels = imageData.data;
      var offset = 0;
      var pixelLen = pixels.length;
      var minOpacity = this.minOpacity;
      var maxOpacity = this.maxOpacity;
      var diffOpacity = maxOpacity - minOpacity;

      while (offset < pixelLen) {
        var alpha = pixels[offset + 3] / 256;
        var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4;

        if (alpha > 0) {
          var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange;
          alpha > 0 && (alpha = alpha * diffOpacity + minOpacity);
          pixels[offset++] = gradient[gradientOffset];
          pixels[offset++] = gradient[gradientOffset + 1];
          pixels[offset++] = gradient[gradientOffset + 2];
          pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256;
        } else {
          offset += 4;
        }
      }

      ctx.putImageData(imageData, 0, 0);
      return canvas;
    };

    HeatmapLayer.prototype._getBrush = function () {
      var brushCanvas = this._brushCanvas || (this._brushCanvas = createCanvas());
      var r = this.pointSize + this.blurSize;
      var d = r * 2;
      brushCanvas.width = d;
      brushCanvas.height = d;
      var ctx = brushCanvas.getContext('2d');
      ctx.clearRect(0, 0, d, d);
      ctx.shadowOffsetX = d;
      ctx.shadowBlur = this.blurSize;
      ctx.shadowColor = '#000';
      ctx.beginPath();
      ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.fill();
      return brushCanvas;
    };

    HeatmapLayer.prototype._getGradient = function (colorFunc, state) {
      var gradientPixels = this._gradientPixels;
      var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4));
      var color = [0, 0, 0, 0];
      var off = 0;

      for (var i = 0; i < 256; i++) {
        colorFunc[state](i / 255, true, color);
        pixelsSingleState[off++] = color[0];
        pixelsSingleState[off++] = color[1];
        pixelsSingleState[off++] = color[2];
        pixelsSingleState[off++] = color[3];
      }

      return pixelsSingleState;
    };

    return HeatmapLayer;
  }();

  function getIsInPiecewiseRange(dataExtent, pieceList, selected) {
    var dataSpan = dataExtent[1] - dataExtent[0];
    pieceList = map(pieceList, function (piece) {
      return {
        interval: [(piece.interval[0] - dataExtent[0]) / dataSpan, (piece.interval[1] - dataExtent[0]) / dataSpan]
      };
    });
    var len = pieceList.length;
    var lastIndex = 0;
    return function (val) {
      var i;

      for (i = lastIndex; i < len; i++) {
        var interval = pieceList[i].interval;

        if (interval[0] <= val && val <= interval[1]) {
          lastIndex = i;
          break;
        }
      }

      if (i === len) {
        for (i = lastIndex - 1; i >= 0; i--) {
          var interval = pieceList[i].interval;

          if (interval[0] <= val && val <= interval[1]) {
            lastIndex = i;
            break;
          }
        }
      }

      return i >= 0 && i < len && selected[i];
    };
  }

  function getIsInContinuousRange(dataExtent, range) {
    var dataSpan = dataExtent[1] - dataExtent[0];
    range = [(range[0] - dataExtent[0]) / dataSpan, (range[1] - dataExtent[0]) / dataSpan];
    return function (val) {
      return val >= range[0] && val <= range[1];
    };
  }

  function isGeoCoordSys(coordSys) {
    var dimensions = coordSys.dimensions;
    return dimensions[0] === 'lng' && dimensions[1] === 'lat';
  }

  var HeatmapView = function (_super) {
    __extends(HeatmapView, _super);

    function HeatmapView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = HeatmapView.type;
      return _this;
    }

    HeatmapView.prototype.render = function (seriesModel, ecModel, api) {
      var visualMapOfThisSeries;
      ecModel.eachComponent('visualMap', function (visualMap) {
        visualMap.eachTargetSeries(function (targetSeries) {
          if (targetSeries === seriesModel) {
            visualMapOfThisSeries = visualMap;
          }
        });
      });

      if (true) {
        if (!visualMapOfThisSeries) {
          throw new Error('Heatmap must use with visualMap');
        }
      }

      this.group.removeAll();
      this._incrementalDisplayable = null;
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') {
        this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count());
      } else if (isGeoCoordSys(coordSys)) {
        this._renderOnGeo(coordSys, seriesModel, visualMapOfThisSeries, api);
      }
    };

    HeatmapView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
      this.group.removeAll();
    };

    HeatmapView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) {
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys) {
        this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true);
      }
    };

    HeatmapView.prototype._renderOnCartesianAndCalendar = function (seriesModel, api, start, end, incremental) {
      var coordSys = seriesModel.coordinateSystem;
      var width;
      var height;
      var xAxisExtent;
      var yAxisExtent;

      if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
        var xAxis = coordSys.getAxis('x');
        var yAxis = coordSys.getAxis('y');

        if (true) {
          if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
            throw new Error('Heatmap on cartesian must have two category axes');
          }

          if (!(xAxis.onBand && yAxis.onBand)) {
            throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
          }
        }

        width = xAxis.getBandWidth();
        height = yAxis.getBandWidth();
        xAxisExtent = xAxis.scale.getExtent();
        yAxisExtent = yAxis.scale.getExtent();
      }

      var group = this.group;
      var data = seriesModel.getData();
      var emphasisStyle = seriesModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
      var blurStyle = seriesModel.getModel(['blur', 'itemStyle']).getItemStyle();
      var selectStyle = seriesModel.getModel(['select', 'itemStyle']).getItemStyle();
      var labelStatesModels = getLabelStatesModels(seriesModel);
      var focus = seriesModel.get(['emphasis', 'focus']);
      var blurScope = seriesModel.get(['emphasis', 'blurScope']);
      var dataDims = isCoordinateSystemType(coordSys, 'cartesian2d') ? [data.mapDimension('x'), data.mapDimension('y'), data.mapDimension('value')] : [data.mapDimension('time'), data.mapDimension('value')];

      for (var idx = start; idx < end; idx++) {
        var rect = void 0;
        var style = data.getItemVisual(idx, 'style');

        if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
          var dataDimX = data.get(dataDims[0], idx);
          var dataDimY = data.get(dataDims[1], idx);

          if (isNaN(data.get(dataDims[2], idx)) || dataDimX < xAxisExtent[0] || dataDimX > xAxisExtent[1] || dataDimY < yAxisExtent[0] || dataDimY > yAxisExtent[1]) {
            continue;
          }

          var point = coordSys.dataToPoint([dataDimX, dataDimY]);
          rect = new Rect({
            shape: {
              x: Math.floor(Math.round(point[0]) - width / 2),
              y: Math.floor(Math.round(point[1]) - height / 2),
              width: Math.ceil(width),
              height: Math.ceil(height)
            },
            style: style
          });
        } else {
          if (isNaN(data.get(dataDims[1], idx))) {
            continue;
          }

          rect = new Rect({
            z2: 1,
            shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape,
            style: style
          });
        }

        var itemModel = data.getItemModel(idx);

        if (data.hasItemOption) {
          var emphasisModel = itemModel.getModel('emphasis');
          emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle();
          blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
          selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle();
          focus = emphasisModel.get('focus');
          blurScope = emphasisModel.get('blurScope');
          labelStatesModels = getLabelStatesModels(itemModel);
        }

        var rawValue = seriesModel.getRawValue(idx);
        var defaultText = '-';

        if (rawValue && rawValue[2] != null) {
          defaultText = rawValue[2] + '';
        }

        setLabelStyle(rect, labelStatesModels, {
          labelFetcher: seriesModel,
          labelDataIndex: idx,
          defaultOpacity: style.opacity,
          defaultText: defaultText
        });
        rect.ensureState('emphasis').style = emphasisStyle;
        rect.ensureState('blur').style = blurStyle;
        rect.ensureState('select').style = selectStyle;
        enableHoverEmphasis(rect, focus, blurScope);
        rect.incremental = incremental;

        if (incremental) {
          rect.states.emphasis.hoverLayer = true;
        }

        group.add(rect);
        data.setItemGraphicEl(idx, rect);
      }
    };

    HeatmapView.prototype._renderOnGeo = function (geo, seriesModel, visualMapModel, api) {
      var inRangeVisuals = visualMapModel.targetVisuals.inRange;
      var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange;
      var data = seriesModel.getData();
      var hmLayer = this._hmLayer || this._hmLayer || new HeatmapLayer();
      hmLayer.blurSize = seriesModel.get('blurSize');
      hmLayer.pointSize = seriesModel.get('pointSize');
      hmLayer.minOpacity = seriesModel.get('minOpacity');
      hmLayer.maxOpacity = seriesModel.get('maxOpacity');
      var rect = geo.getViewRect().clone();
      var roamTransform = geo.getRoamTransform();
      rect.applyTransform(roamTransform);
      var x = Math.max(rect.x, 0);
      var y = Math.max(rect.y, 0);
      var x2 = Math.min(rect.width + rect.x, api.getWidth());
      var y2 = Math.min(rect.height + rect.y, api.getHeight());
      var width = x2 - x;
      var height = y2 - y;
      var dims = [data.mapDimension('lng'), data.mapDimension('lat'), data.mapDimension('value')];
      var points = data.mapArray(dims, function (lng, lat, value) {
        var pt = geo.dataToPoint([lng, lat]);
        pt[0] -= x;
        pt[1] -= y;
        pt.push(value);
        return pt;
      });
      var dataExtent = visualMapModel.getExtent();
      var isInRange = visualMapModel.type === 'visualMap.continuous' ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) : getIsInPiecewiseRange(dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected);
      hmLayer.update(points, width, height, inRangeVisuals.color.getNormalizer(), {
        inRange: inRangeVisuals.color.getColorMapper(),
        outOfRange: outOfRangeVisuals.color.getColorMapper()
      }, isInRange);
      var img = new ZRImage({
        style: {
          width: width,
          height: height,
          x: x,
          y: y,
          image: hmLayer.canvas
        },
        silent: true
      });
      this.group.add(img);
    };

    HeatmapView.type = 'heatmap';
    return HeatmapView;
  }(ChartView);

  ChartView.registerClass(HeatmapView);

  var PictorialBarSeriesModel = function (_super) {
    __extends(PictorialBarSeriesModel, _super);

    function PictorialBarSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = PictorialBarSeriesModel.type;
      _this.hasSymbolVisual = true;
      _this.defaultSymbol = 'roundRect';
      return _this;
    }

    PictorialBarSeriesModel.prototype.getInitialData = function (option) {
      option.stack = null;
      return _super.prototype.getInitialData.apply(this, arguments);
    };

    PictorialBarSeriesModel.type = 'series.pictorialBar';
    PictorialBarSeriesModel.dependencies = ['grid'];
    PictorialBarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, {
      symbol: 'circle',
      symbolSize: null,
      symbolRotate: null,
      symbolPosition: null,
      symbolOffset: null,
      symbolMargin: null,
      symbolRepeat: false,
      symbolRepeatDirection: 'end',
      symbolClip: false,
      symbolBoundingData: null,
      symbolPatternSize: 400,
      barGap: '-100%',
      progressive: 0,
      emphasis: {
        scale: false
      },
      select: {
        itemStyle: {
          borderColor: '#212121'
        }
      }
    });
    return PictorialBarSeriesModel;
  }(BaseBarSeriesModel);

  SeriesModel.registerClass(PictorialBarSeriesModel);
  var BAR_BORDER_WIDTH_QUERY$1 = ['itemStyle', 'borderWidth'];
  var LAYOUT_ATTRS = [{
    xy: 'x',
    wh: 'width',
    index: 0,
    posDesc: ['left', 'right']
  }, {
    xy: 'y',
    wh: 'height',
    index: 1,
    posDesc: ['top', 'bottom']
  }];
  var pathForLineWidth = new Circle();

  var PictorialBarView = function (_super) {
    __extends(PictorialBarView, _super);

    function PictorialBarView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = PictorialBarView.type;
      return _this;
    }

    PictorialBarView.prototype.render = function (seriesModel, ecModel, api) {
      var group = this.group;
      var data = seriesModel.getData();
      var oldData = this._data;
      var cartesian = seriesModel.coordinateSystem;
      var baseAxis = cartesian.getBaseAxis();
      var isHorizontal = baseAxis.isHorizontal();
      var coordSysRect = cartesian.master.getRect();
      var opt = {
        ecSize: {
          width: api.getWidth(),
          height: api.getHeight()
        },
        seriesModel: seriesModel,
        coordSys: cartesian,
        coordSysExtent: [[coordSysRect.x, coordSysRect.x + coordSysRect.width], [coordSysRect.y, coordSysRect.y + coordSysRect.height]],
        isHorizontal: isHorizontal,
        valueDim: LAYOUT_ATTRS[+isHorizontal],
        categoryDim: LAYOUT_ATTRS[1 - +isHorizontal]
      };
      data.diff(oldData).add(function (dataIndex) {
        if (!data.hasValue(dataIndex)) {
          return;
        }

        var itemModel = getItemModel(data, dataIndex);
        var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt);
        var bar = createBar(data, opt, symbolMeta);
        data.setItemGraphicEl(dataIndex, bar);
        group.add(bar);
        updateCommon$1(bar, opt, symbolMeta);
      }).update(function (newIndex, oldIndex) {
        var bar = oldData.getItemGraphicEl(oldIndex);

        if (!data.hasValue(newIndex)) {
          group.remove(bar);
          return;
        }

        var itemModel = getItemModel(data, newIndex);
        var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt);
        var pictorialShapeStr = getShapeStr(data, symbolMeta);

        if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) {
          group.remove(bar);
          data.setItemGraphicEl(newIndex, null);
          bar = null;
        }

        if (bar) {
          updateBar(bar, opt, symbolMeta);
        } else {
          bar = createBar(data, opt, symbolMeta, true);
        }

        data.setItemGraphicEl(newIndex, bar);
        bar.__pictorialSymbolMeta = symbolMeta;
        group.add(bar);
        updateCommon$1(bar, opt, symbolMeta);
      }).remove(function (dataIndex) {
        var bar = oldData.getItemGraphicEl(dataIndex);
        bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar);
      }).execute();
      this._data = data;
      return this.group;
    };

    PictorialBarView.prototype.remove = function (ecModel, api) {
      var group = this.group;
      var data = this._data;

      if (ecModel.get('animation')) {
        if (data) {
          data.eachItemGraphicEl(function (bar) {
            removeBar(data, getECData(bar).dataIndex, ecModel, bar);
          });
        }
      } else {
        group.removeAll();
      }
    };

    PictorialBarView.type = 'pictorialBar';
    return PictorialBarView;
  }(ChartView);

  function getSymbolMeta(data, dataIndex, itemModel, opt) {
    var layout = data.getItemLayout(dataIndex);
    var symbolRepeat = itemModel.get('symbolRepeat');
    var symbolClip = itemModel.get('symbolClip');
    var symbolPosition = itemModel.get('symbolPosition') || 'start';
    var symbolRotate = itemModel.get('symbolRotate');
    var rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
    var symbolPatternSize = itemModel.get('symbolPatternSize') || 2;
    var isAnimationEnabled = itemModel.isAnimationEnabled();
    var symbolMeta = {
      dataIndex: dataIndex,
      layout: layout,
      itemModel: itemModel,
      symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle',
      style: data.getItemVisual(dataIndex, 'style'),
      symbolClip: symbolClip,
      symbolRepeat: symbolRepeat,
      symbolRepeatDirection: itemModel.get('symbolRepeatDirection'),
      symbolPatternSize: symbolPatternSize,
      rotation: rotation,
      animationModel: isAnimationEnabled ? itemModel : null,
      hoverScale: isAnimationEnabled && itemModel.get(['emphasis', 'scale']),
      z2: itemModel.getShallow('z', true) || 0
    };
    prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta);
    prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength, symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta);
    prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta);
    var symbolSize = symbolMeta.symbolSize;
    var symbolOffset = itemModel.get('symbolOffset');

    if (isArray(symbolOffset)) {
      symbolOffset = [parsePercent$2(symbolOffset[0], symbolSize[0]), parsePercent$2(symbolOffset[1], symbolSize[1])];
    }

    prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, opt, symbolMeta);
    return symbolMeta;
  }

  function prepareBarLength(itemModel, symbolRepeat, layout, opt, outputSymbolMeta) {
    var valueDim = opt.valueDim;
    var symbolBoundingData = itemModel.get('symbolBoundingData');
    var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis());
    var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0));
    var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0);
    var boundingLength;

    if (isArray(symbolBoundingData)) {
      var symbolBoundingExtent = [convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx, convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx];
      symbolBoundingExtent[1] < symbolBoundingExtent[0] && symbolBoundingExtent.reverse();
      boundingLength = symbolBoundingExtent[pxSignIdx];
    } else if (symbolBoundingData != null) {
      boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx;
    } else if (symbolRepeat) {
      boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx;
    } else {
      boundingLength = layout[valueDim.wh];
    }

    outputSymbolMeta.boundingLength = boundingLength;

    if (symbolRepeat) {
      outputSymbolMeta.repeatCutLength = layout[valueDim.wh];
    }

    outputSymbolMeta.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0;
  }

  function convertToCoordOnAxis(axis, value) {
    return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value)));
  }

  function prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength, pxSign, symbolPatternSize, opt, outputSymbolMeta) {
    var valueDim = opt.valueDim;
    var categoryDim = opt.categoryDim;
    var categorySize = Math.abs(layout[categoryDim.wh]);
    var symbolSize = data.getItemVisual(dataIndex, 'symbolSize');
    var parsedSymbolSize;

    if (isArray(symbolSize)) {
      parsedSymbolSize = symbolSize.slice();
    } else {
      if (symbolSize == null) {
        parsedSymbolSize = ['100%', '100%'];
      } else {
        parsedSymbolSize = [symbolSize, symbolSize];
      }
    }

    parsedSymbolSize[categoryDim.index] = parsePercent$2(parsedSymbolSize[categoryDim.index], categorySize);
    parsedSymbolSize[valueDim.index] = parsePercent$2(parsedSymbolSize[valueDim.index], symbolRepeat ? categorySize : Math.abs(boundingLength));
    outputSymbolMeta.symbolSize = parsedSymbolSize;
    var symbolScale = outputSymbolMeta.symbolScale = [parsedSymbolSize[0] / symbolPatternSize, parsedSymbolSize[1] / symbolPatternSize];
    symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign;
  }

  function prepareLineWidth(itemModel, symbolScale, rotation, opt, outputSymbolMeta) {
    var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY$1) || 0;

    if (valueLineWidth) {
      pathForLineWidth.attr({
        scaleX: symbolScale[0],
        scaleY: symbolScale[1],
        rotation: rotation
      });
      pathForLineWidth.updateTransform();
      valueLineWidth /= pathForLineWidth.getLineScale();
      valueLineWidth *= symbolScale[opt.valueDim.index];
    }

    outputSymbolMeta.valueLineWidth = valueLineWidth;
  }

  function prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, outputSymbolMeta) {
    var categoryDim = opt.categoryDim;
    var valueDim = opt.valueDim;
    var pxSign = outputSymbolMeta.pxSign;
    var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0);
    var pathLen = unitLength;

    if (symbolRepeat) {
      var absBoundingLength = Math.abs(boundingLength);
      var symbolMargin = retrieve(itemModel.get('symbolMargin'), '15%') + '';
      var hasEndGap = false;

      if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) {
        hasEndGap = true;
        symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1);
      }

      var symbolMarginNumeric = parsePercent$2(symbolMargin, symbolSize[valueDim.index]);
      var uLenWithMargin = Math.max(unitLength + symbolMarginNumeric * 2, 0);
      var endFix = hasEndGap ? 0 : symbolMarginNumeric * 2;
      var repeatSpecified = isNumeric(symbolRepeat);
      var repeatTimes = repeatSpecified ? symbolRepeat : toIntTimes((absBoundingLength + endFix) / uLenWithMargin);
      var mDiff = absBoundingLength - repeatTimes * unitLength;
      symbolMarginNumeric = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1);
      uLenWithMargin = unitLength + symbolMarginNumeric * 2;
      endFix = hasEndGap ? 0 : symbolMarginNumeric * 2;

      if (!repeatSpecified && symbolRepeat !== 'fixed') {
        repeatTimes = repeatCutLength ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin) : 0;
      }

      pathLen = repeatTimes * uLenWithMargin - endFix;
      outputSymbolMeta.repeatTimes = repeatTimes;
      outputSymbolMeta.symbolMargin = symbolMarginNumeric;
    }

    var sizeFix = pxSign * (pathLen / 2);
    var pathPosition = outputSymbolMeta.pathPosition = [];
    pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2;
    pathPosition[valueDim.index] = symbolPosition === 'start' ? sizeFix : symbolPosition === 'end' ? boundingLength - sizeFix : boundingLength / 2;

    if (symbolOffset) {
      pathPosition[0] += symbolOffset[0];
      pathPosition[1] += symbolOffset[1];
    }

    var bundlePosition = outputSymbolMeta.bundlePosition = [];
    bundlePosition[categoryDim.index] = layout[categoryDim.xy];
    bundlePosition[valueDim.index] = layout[valueDim.xy];
    var barRectShape = outputSymbolMeta.barRectShape = extend({}, layout);
    barRectShape[valueDim.wh] = pxSign * Math.max(Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix));
    barRectShape[categoryDim.wh] = layout[categoryDim.wh];
    var clipShape = outputSymbolMeta.clipShape = {};
    clipShape[categoryDim.xy] = -layout[categoryDim.xy];
    clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh];
    clipShape[valueDim.xy] = 0;
    clipShape[valueDim.wh] = layout[valueDim.wh];
  }

  function createPath(symbolMeta) {
    var symbolPatternSize = symbolMeta.symbolPatternSize;
    var path = createSymbol(symbolMeta.symbolType, -symbolPatternSize / 2, -symbolPatternSize / 2, symbolPatternSize, symbolPatternSize);
    path.attr({
      culling: true
    });
    path.type !== 'image' && path.setStyle({
      strokeNoScale: true
    });
    return path;
  }

  function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) {
    var bundle = bar.__pictorialBundle;
    var symbolSize = symbolMeta.symbolSize;
    var valueLineWidth = symbolMeta.valueLineWidth;
    var pathPosition = symbolMeta.pathPosition;
    var valueDim = opt.valueDim;
    var repeatTimes = symbolMeta.repeatTimes || 0;
    var index = 0;
    var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2;
    eachPath(bar, function (path) {
      path.__pictorialAnimationIndex = index;
      path.__pictorialRepeatTimes = repeatTimes;

      if (index < repeatTimes) {
        updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate);
      } else {
        updateAttr(path, null, {
          scaleX: 0,
          scaleY: 0
        }, symbolMeta, isUpdate, function () {
          bundle.remove(path);
        });
      }

      index++;
    });

    for (; index < repeatTimes; index++) {
      var path = createPath(symbolMeta);
      path.__pictorialAnimationIndex = index;
      path.__pictorialRepeatTimes = repeatTimes;
      bundle.add(path);
      var target = makeTarget(index);
      updateAttr(path, {
        x: target.x,
        y: target.y,
        scaleX: 0,
        scaleY: 0
      }, {
        scaleX: target.scaleX,
        scaleY: target.scaleY,
        rotation: target.rotation
      }, symbolMeta, isUpdate);
    }

    function makeTarget(index) {
      var position = pathPosition.slice();
      var pxSign = symbolMeta.pxSign;
      var i = index;

      if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) {
        i = repeatTimes - 1 - index;
      }

      position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index];
      return {
        x: position[0],
        y: position[1],
        scaleX: symbolMeta.symbolScale[0],
        scaleY: symbolMeta.symbolScale[1],
        rotation: symbolMeta.rotation
      };
    }
  }

  function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) {
    var bundle = bar.__pictorialBundle;
    var mainPath = bar.__pictorialMainPath;

    if (!mainPath) {
      mainPath = bar.__pictorialMainPath = createPath(symbolMeta);
      bundle.add(mainPath);
      updateAttr(mainPath, {
        x: symbolMeta.pathPosition[0],
        y: symbolMeta.pathPosition[1],
        scaleX: 0,
        scaleY: 0,
        rotation: symbolMeta.rotation
      }, {
        scaleX: symbolMeta.symbolScale[0],
        scaleY: symbolMeta.symbolScale[1]
      }, symbolMeta, isUpdate);
    } else {
      updateAttr(mainPath, null, {
        x: symbolMeta.pathPosition[0],
        y: symbolMeta.pathPosition[1],
        scaleX: symbolMeta.symbolScale[0],
        scaleY: symbolMeta.symbolScale[1],
        rotation: symbolMeta.rotation
      }, symbolMeta, isUpdate);
    }
  }

  function createOrUpdateBarRect(bar, symbolMeta, isUpdate) {
    var rectShape = extend({}, symbolMeta.barRectShape);
    var barRect = bar.__pictorialBarRect;

    if (!barRect) {
      barRect = bar.__pictorialBarRect = new Rect({
        z2: 2,
        shape: rectShape,
        silent: true,
        style: {
          stroke: 'transparent',
          fill: 'transparent',
          lineWidth: 0
        }
      });
      bar.add(barRect);
    } else {
      updateAttr(barRect, null, {
        shape: rectShape
      }, symbolMeta, isUpdate);
    }
  }

  function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) {
    if (symbolMeta.symbolClip) {
      var clipPath = bar.__pictorialClipPath;
      var clipShape = extend({}, symbolMeta.clipShape);
      var valueDim = opt.valueDim;
      var animationModel = symbolMeta.animationModel;
      var dataIndex = symbolMeta.dataIndex;

      if (clipPath) {
        updateProps(clipPath, {
          shape: clipShape
        }, animationModel, dataIndex);
      } else {
        clipShape[valueDim.wh] = 0;
        clipPath = new Rect({
          shape: clipShape
        });

        bar.__pictorialBundle.setClipPath(clipPath);

        bar.__pictorialClipPath = clipPath;
        var target = {};
        target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh];
        graphic[isUpdate ? 'updateProps' : 'initProps'](clipPath, {
          shape: target
        }, animationModel, dataIndex);
      }
    }
  }

  function getItemModel(data, dataIndex) {
    var itemModel = data.getItemModel(dataIndex);
    itemModel.getAnimationDelayParams = getAnimationDelayParams;
    itemModel.isAnimationEnabled = isAnimationEnabled;
    return itemModel;
  }

  function getAnimationDelayParams(path) {
    return {
      index: path.__pictorialAnimationIndex,
      count: path.__pictorialRepeatTimes
    };
  }

  function isAnimationEnabled() {
    return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation');
  }

  function createBar(data, opt, symbolMeta, isUpdate) {
    var bar = new Group();
    var bundle = new Group();
    bar.add(bundle);
    bar.__pictorialBundle = bundle;
    bundle.x = symbolMeta.bundlePosition[0];
    bundle.y = symbolMeta.bundlePosition[1];

    if (symbolMeta.symbolRepeat) {
      createOrUpdateRepeatSymbols(bar, opt, symbolMeta);
    } else {
      createOrUpdateSingleSymbol(bar, opt, symbolMeta);
    }

    createOrUpdateBarRect(bar, symbolMeta, isUpdate);
    createOrUpdateClip(bar, opt, symbolMeta, isUpdate);
    bar.__pictorialShapeStr = getShapeStr(data, symbolMeta);
    bar.__pictorialSymbolMeta = symbolMeta;
    return bar;
  }

  function updateBar(bar, opt, symbolMeta) {
    var animationModel = symbolMeta.animationModel;
    var dataIndex = symbolMeta.dataIndex;
    var bundle = bar.__pictorialBundle;
    updateProps(bundle, {
      x: symbolMeta.bundlePosition[0],
      y: symbolMeta.bundlePosition[1]
    }, animationModel, dataIndex);

    if (symbolMeta.symbolRepeat) {
      createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true);
    } else {
      createOrUpdateSingleSymbol(bar, opt, symbolMeta, true);
    }

    createOrUpdateBarRect(bar, symbolMeta, true);
    createOrUpdateClip(bar, opt, symbolMeta, true);
  }

  function removeBar(data, dataIndex, animationModel, bar) {
    var labelRect = bar.__pictorialBarRect;
    labelRect && labelRect.removeTextContent();
    var pathes = [];
    eachPath(bar, function (path) {
      pathes.push(path);
    });
    bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath);
    bar.__pictorialClipPath && (animationModel = null);
    each(pathes, function (path) {
      removeElement(path, {
        scaleX: 0,
        scaleY: 0
      }, animationModel, dataIndex, function () {
        bar.parent && bar.parent.remove(bar);
      });
    });
    data.setItemGraphicEl(dataIndex, null);
  }

  function getShapeStr(data, symbolMeta) {
    return [data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none', !!symbolMeta.symbolRepeat, !!symbolMeta.symbolClip].join(':');
  }

  function eachPath(bar, cb, context) {
    each(bar.__pictorialBundle.children(), function (el) {
      el !== bar.__pictorialBarRect && cb.call(context, el);
    });
  }

  function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) {
    immediateAttrs && el.attr(immediateAttrs);

    if (symbolMeta.symbolClip && !isUpdate) {
      animationAttrs && el.attr(animationAttrs);
    } else {
      animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb);
    }
  }

  function updateCommon$1(bar, opt, symbolMeta) {
    var dataIndex = symbolMeta.dataIndex;
    var itemModel = symbolMeta.itemModel;
    var emphasisModel = itemModel.getModel('emphasis');
    var emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle();
    var blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
    var selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle();
    var cursorStyle = itemModel.getShallow('cursor');
    var focus = emphasisModel.get('focus');
    var blurScope = emphasisModel.get('blurScope');
    var hoverScale = emphasisModel.get('scale');
    eachPath(bar, function (path) {
      if (path instanceof ZRImage) {
        var pathStyle = path.style;
        path.useStyle(extend({
          image: pathStyle.image,
          x: pathStyle.x,
          y: pathStyle.y,
          width: pathStyle.width,
          height: pathStyle.height
        }, symbolMeta.style));
      } else {
        path.useStyle(symbolMeta.style);
      }

      var emphasisState = path.ensureState('emphasis');
      emphasisState.style = emphasisStyle;

      if (hoverScale) {
        emphasisState.scaleX = path.scaleX * 1.1;
        emphasisState.scaleY = path.scaleY * 1.1;
      }

      path.ensureState('blur').style = blurStyle;
      path.ensureState('select').style = selectStyle;
      cursorStyle && (path.cursor = cursorStyle);
      path.z2 = symbolMeta.z2;
    });
    var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)];
    var barRect = bar.__pictorialBarRect;
    setLabelStyle(barRect, getLabelStatesModels(itemModel), {
      labelFetcher: opt.seriesModel,
      labelDataIndex: dataIndex,
      defaultText: getDefaultLabel(opt.seriesModel.getData(), dataIndex),
      inheritColor: symbolMeta.style.fill,
      defaultOpacity: symbolMeta.style.opacity,
      defaultOutsidePosition: barPositionOutside
    });
    enableHoverEmphasis(bar, focus, blurScope);
  }

  function toIntTimes(times) {
    var roundedTimes = Math.round(times);
    return Math.abs(times - roundedTimes) < 1e-4 ? roundedTimes : Math.ceil(times);
  }

  ChartView.registerClass(PictorialBarView);
  registerLayout(curry(layout, 'pictorialBar'));

  var SingleAxis = function (_super) {
    __extends(SingleAxis, _super);

    function SingleAxis(dim, scale, coordExtent, axisType, position) {
      var _this = _super.call(this, dim, scale, coordExtent) || this;

      _this.type = axisType || 'value';
      _this.position = position || 'bottom';
      return _this;
    }

    SingleAxis.prototype.isHorizontal = function () {
      var position = this.position;
      return position === 'top' || position === 'bottom';
    };

    SingleAxis.prototype.pointToData = function (point, clamp) {
      return this.coordinateSystem.pointToData(point)[0];
    };

    return SingleAxis;
  }(Axis);

  var Single = function () {
    function Single(axisModel, ecModel, api) {
      this.type = 'single';
      this.dimension = 'single';
      this.dimensions = ['single'];
      this.axisPointerEnabled = true;
      this.model = axisModel;

      this._init(axisModel, ecModel, api);
    }

    Single.prototype._init = function (axisModel, ecModel, api) {
      var dim = this.dimension;
      var axis = new SingleAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisModel.get('position'));
      var isCategory = axis.type === 'category';
      axis.onBand = isCategory && axisModel.get('boundaryGap');
      axis.inverse = axisModel.get('inverse');
      axis.orient = axisModel.get('orient');
      axisModel.axis = axis;
      axis.model = axisModel;
      axis.coordinateSystem = this;
      this._axis = axis;
    };

    Single.prototype.update = function (ecModel, api) {
      ecModel.eachSeries(function (seriesModel) {
        if (seriesModel.coordinateSystem === this) {
          var data_1 = seriesModel.getData();
          each(data_1.mapDimensionsAll(this.dimension), function (dim) {
            this._axis.scale.unionExtentFromData(data_1, dim);
          }, this);
          niceScaleExtent(this._axis.scale, this._axis.model);
        }
      }, this);
    };

    Single.prototype.resize = function (axisModel, api) {
      this._rect = getLayoutRect({
        left: axisModel.get('left'),
        top: axisModel.get('top'),
        right: axisModel.get('right'),
        bottom: axisModel.get('bottom'),
        width: axisModel.get('width'),
        height: axisModel.get('height')
      }, {
        width: api.getWidth(),
        height: api.getHeight()
      });

      this._adjustAxis();
    };

    Single.prototype.getRect = function () {
      return this._rect;
    };

    Single.prototype._adjustAxis = function () {
      var rect = this._rect;
      var axis = this._axis;
      var isHorizontal = axis.isHorizontal();
      var extent = isHorizontal ? [0, rect.width] : [0, rect.height];
      var idx = axis.reverse ? 1 : 0;
      axis.setExtent(extent[idx], extent[1 - idx]);

      this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y);
    };

    Single.prototype._updateAxisTransform = function (axis, coordBase) {
      var axisExtent = axis.getExtent();
      var extentSum = axisExtent[0] + axisExtent[1];
      var isHorizontal = axis.isHorizontal();
      axis.toGlobalCoord = isHorizontal ? function (coord) {
        return coord + coordBase;
      } : function (coord) {
        return extentSum - coord + coordBase;
      };
      axis.toLocalCoord = isHorizontal ? function (coord) {
        return coord - coordBase;
      } : function (coord) {
        return extentSum - coord + coordBase;
      };
    };

    Single.prototype.getAxis = function () {
      return this._axis;
    };

    Single.prototype.getBaseAxis = function () {
      return this._axis;
    };

    Single.prototype.getAxes = function () {
      return [this._axis];
    };

    Single.prototype.getTooltipAxes = function () {
      return {
        baseAxes: [this.getAxis()],
        otherAxes: []
      };
    };

    Single.prototype.containPoint = function (point) {
      var rect = this.getRect();
      var axis = this.getAxis();
      var orient = axis.orient;

      if (orient === 'horizontal') {
        return axis.contain(axis.toLocalCoord(point[0])) && point[1] >= rect.y && point[1] <= rect.y + rect.height;
      } else {
        return axis.contain(axis.toLocalCoord(point[1])) && point[0] >= rect.y && point[0] <= rect.y + rect.height;
      }
    };

    Single.prototype.pointToData = function (point) {
      var axis = this.getAxis();
      return [axis.coordToData(axis.toLocalCoord(point[axis.orient === 'horizontal' ? 0 : 1]))];
    };

    Single.prototype.dataToPoint = function (val) {
      var axis = this.getAxis();
      var rect = this.getRect();
      var pt = [];
      var idx = axis.orient === 'horizontal' ? 0 : 1;

      if (val instanceof Array) {
        val = val[0];
      }

      pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val));
      pt[1 - idx] = idx === 0 ? rect.y + rect.height / 2 : rect.x + rect.width / 2;
      return pt;
    };

    Single.prototype.convertToPixel = function (ecModel, finder, value) {
      var coordSys = getCoordSys$2(finder);
      return coordSys === this ? this.dataToPoint(value) : null;
    };

    Single.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      var coordSys = getCoordSys$2(finder);
      return coordSys === this ? this.pointToData(pixel) : null;
    };

    return Single;
  }();

  function getCoordSys$2(finder) {
    var seriesModel = finder.seriesModel;
    var singleModel = finder.singleAxisModel;
    return singleModel && singleModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem;
  }

  function create$3(ecModel, api) {
    var singles = [];
    ecModel.eachComponent('singleAxis', function (axisModel, idx) {
      var single = new Single(axisModel, ecModel, api);
      single.name = 'single_' + idx;
      single.resize(axisModel, api);
      axisModel.coordinateSystem = single;
      singles.push(single);
    });
    ecModel.eachSeries(function (seriesModel) {
      if (seriesModel.get('coordinateSystem') === 'singleAxis') {
        var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0];
        seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem;
      }
    });
    return singles;
  }

  CoordinateSystemManager.register('single', {
    create: create$3,
    dimensions: Single.prototype.dimensions
  });

  function layout$2(axisModel, opt) {
    opt = opt || {};
    var single = axisModel.coordinateSystem;
    var axis = axisModel.axis;
    var layout = {};
    var axisPosition = axis.position;
    var orient = axis.orient;
    var rect = single.getRect();
    var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
    var positionMap = {
      horizontal: {
        top: rectBound[2],
        bottom: rectBound[3]
      },
      vertical: {
        left: rectBound[0],
        right: rectBound[1]
      }
    };
    layout.position = [orient === 'vertical' ? positionMap.vertical[axisPosition] : rectBound[0], orient === 'horizontal' ? positionMap.horizontal[axisPosition] : rectBound[3]];
    var r = {
      horizontal: 0,
      vertical: 1
    };
    layout.rotation = Math.PI / 2 * r[orient];
    var directionMap = {
      top: -1,
      bottom: 1,
      right: 1,
      left: -1
    };
    layout.labelDirection = layout.tickDirection = layout.nameDirection = directionMap[axisPosition];

    if (axisModel.get(['axisTick', 'inside'])) {
      layout.tickDirection = -layout.tickDirection;
    }

    if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) {
      layout.labelDirection = -layout.labelDirection;
    }

    var labelRotation = opt.rotate;
    labelRotation == null && (labelRotation = axisModel.get(['axisLabel', 'rotate']));
    layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation;
    layout.z2 = 1;
    return layout;
  }

  var axisBuilderAttrs$2 = ['axisLine', 'axisTickLabel', 'axisName'];
  var selfBuilderAttrs$1 = ['splitArea', 'splitLine'];

  var SingleAxisView = function (_super) {
    __extends(SingleAxisView, _super);

    function SingleAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SingleAxisView.type;
      _this.axisPointerClass = 'SingleAxisPointer';
      return _this;
    }

    SingleAxisView.prototype.render = function (axisModel, ecModel, api, payload) {
      var group = this.group;
      group.removeAll();
      var oldAxisGroup = this._axisGroup;
      this._axisGroup = new Group();
      var layout = layout$2(axisModel);
      var axisBuilder = new AxisBuilder(axisModel, layout);
      each(axisBuilderAttrs$2, axisBuilder.add, axisBuilder);
      group.add(this._axisGroup);
      group.add(axisBuilder.getGroup());
      each(selfBuilderAttrs$1, function (name) {
        if (axisModel.get([name, 'show'])) {
          axisElementBuilders$1[name](this, this.group, this._axisGroup, axisModel);
        }
      }, this);
      groupTransition(oldAxisGroup, this._axisGroup, axisModel);

      _super.prototype.render.call(this, axisModel, ecModel, api, payload);
    };

    SingleAxisView.prototype.remove = function () {
      rectCoordAxisHandleRemove(this);
    };

    SingleAxisView.type = 'singleAxis';
    return SingleAxisView;
  }(AxisView);

  var axisElementBuilders$1 = {
    splitLine: function (axisView, group, axisGroup, axisModel) {
      var axis = axisModel.axis;

      if (axis.scale.isBlank()) {
        return;
      }

      var splitLineModel = axisModel.getModel('splitLine');
      var lineStyleModel = splitLineModel.getModel('lineStyle');
      var lineColors = lineStyleModel.get('color');
      lineColors = lineColors instanceof Array ? lineColors : [lineColors];
      var gridRect = axisModel.coordinateSystem.getRect();
      var isHorizontal = axis.isHorizontal();
      var splitLines = [];
      var lineCount = 0;
      var ticksCoords = axis.getTicksCoords({
        tickModel: splitLineModel
      });
      var p1 = [];
      var p2 = [];

      for (var i = 0; i < ticksCoords.length; ++i) {
        var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);

        if (isHorizontal) {
          p1[0] = tickCoord;
          p1[1] = gridRect.y;
          p2[0] = tickCoord;
          p2[1] = gridRect.y + gridRect.height;
        } else {
          p1[0] = gridRect.x;
          p1[1] = tickCoord;
          p2[0] = gridRect.x + gridRect.width;
          p2[1] = tickCoord;
        }

        var colorIndex = lineCount++ % lineColors.length;
        splitLines[colorIndex] = splitLines[colorIndex] || [];
        splitLines[colorIndex].push(new Line({
          subPixelOptimize: true,
          shape: {
            x1: p1[0],
            y1: p1[1],
            x2: p2[0],
            y2: p2[1]
          },
          silent: true
        }));
      }

      var lineStyle = lineStyleModel.getLineStyle(['color']);

      for (var i = 0; i < splitLines.length; ++i) {
        group.add(mergePath$1(splitLines[i], {
          style: defaults({
            stroke: lineColors[i % lineColors.length]
          }, lineStyle),
          silent: true
        }));
      }
    },
    splitArea: function (axisView, group, axisGroup, axisModel) {
      rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, axisModel);
    }
  };
  ComponentView.registerClass(SingleAxisView);

  var SingleAxisModel = function (_super) {
    __extends(SingleAxisModel, _super);

    function SingleAxisModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SingleAxisModel.type;
      return _this;
    }

    SingleAxisModel.prototype.getCoordSysModel = function () {
      return this;
    };

    SingleAxisModel.type = 'singleAxis';
    SingleAxisModel.layoutMode = 'box';
    SingleAxisModel.defaultOption = {
      left: '5%',
      top: '5%',
      right: '5%',
      bottom: '5%',
      type: 'value',
      position: 'bottom',
      orient: 'horizontal',
      axisLine: {
        show: true,
        lineStyle: {
          width: 1,
          type: 'solid'
        }
      },
      tooltip: {
        show: true
      },
      axisTick: {
        show: true,
        length: 6,
        lineStyle: {
          width: 1
        }
      },
      axisLabel: {
        show: true,
        interval: 'auto'
      },
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed',
          opacity: 0.2
        }
      }
    };
    return SingleAxisModel;
  }(ComponentModel);

  ComponentModel.registerClass(SingleAxisModel);
  mixin(SingleAxisModel, AxisModelCommonMixin.prototype);
  axisModelCreator('single', SingleAxisModel, SingleAxisModel.defaultOption);

  function findPointFromSeries(finder, ecModel) {
    var point = [];
    var seriesIndex = finder.seriesIndex;
    var seriesModel;

    if (seriesIndex == null || !(seriesModel = ecModel.getSeriesByIndex(seriesIndex))) {
      return {
        point: []
      };
    }

    var data = seriesModel.getData();
    var dataIndex = queryDataIndex(data, finder);

    if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) {
      return {
        point: []
      };
    }

    var el = data.getItemGraphicEl(dataIndex);
    var coordSys = seriesModel.coordinateSystem;

    if (seriesModel.getTooltipPosition) {
      point = seriesModel.getTooltipPosition(dataIndex) || [];
    } else if (coordSys && coordSys.dataToPoint) {
      if (finder.isStacked) {
        var baseAxis = coordSys.getBaseAxis();
        var valueAxis = coordSys.getOtherAxis(baseAxis);
        var valueAxisDim = valueAxis.dim;
        var baseAxisDim = baseAxis.dim;
        var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0;
        var baseDim = data.mapDimension(baseAxisDim);
        var stackedData = [];
        stackedData[baseDataOffset] = data.get(baseDim, dataIndex);
        stackedData[1 - baseDataOffset] = data.get(data.getCalculationInfo('stackResultDimension'), dataIndex);
        point = coordSys.dataToPoint(stackedData) || [];
      } else {
        point = coordSys.dataToPoint(data.getValues(map(coordSys.dimensions, function (dim) {
          return data.mapDimension(dim);
        }), dataIndex)) || [];
      }
    } else if (el) {
      var rect = el.getBoundingRect().clone();
      rect.applyTransform(el.transform);
      point = [rect.x + rect.width / 2, rect.y + rect.height / 2];
    }

    return {
      point: point,
      el: el
    };
  }

  var inner$b = makeInner();

  function axisTrigger(payload, ecModel, api) {
    var currTrigger = payload.currTrigger;
    var point = [payload.x, payload.y];
    var finder = payload;
    var dispatchAction = payload.dispatchAction || bind(api.dispatchAction, api);
    var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

    if (!coordSysAxesInfo) {
      return;
    }

    if (illegalPoint(point)) {
      point = findPointFromSeries({
        seriesIndex: finder.seriesIndex,
        dataIndex: finder.dataIndex
      }, ecModel).point;
    }

    var isIllegalPoint = illegalPoint(point);
    var inputAxesInfo = finder.axesInfo;
    var axesInfo = coordSysAxesInfo.axesInfo;
    var shouldHide = currTrigger === 'leave' || illegalPoint(point);
    var outputPayload = {};
    var showValueMap = {};
    var dataByCoordSys = {
      list: [],
      map: {}
    };
    var updaters = {
      showPointer: curry(showPointer, showValueMap),
      showTooltip: curry(showTooltip, dataByCoordSys)
    };
    each(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) {
      var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point);
      each(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) {
        var axis = axisInfo.axis;
        var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo);

        if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) {
          var val = inputAxisInfo && inputAxisInfo.value;

          if (val == null && !isIllegalPoint) {
            val = axis.pointToData(point);
          }

          val != null && processOnAxis(axisInfo, val, updaters, false, outputPayload);
        }
      });
    });
    var linkTriggers = {};
    each(axesInfo, function (tarAxisInfo, tarKey) {
      var linkGroup = tarAxisInfo.linkGroup;

      if (linkGroup && !showValueMap[tarKey]) {
        each(linkGroup.axesInfo, function (srcAxisInfo, srcKey) {
          var srcValItem = showValueMap[srcKey];

          if (srcAxisInfo !== tarAxisInfo && srcValItem) {
            var val = srcValItem.value;
            linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo))));
            linkTriggers[tarAxisInfo.key] = val;
          }
        });
      }
    });
    each(linkTriggers, function (val, tarKey) {
      processOnAxis(axesInfo[tarKey], val, updaters, true, outputPayload);
    });
    updateModelActually(showValueMap, axesInfo, outputPayload);
    dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction);
    dispatchHighDownActually(axesInfo, dispatchAction, api);
    return outputPayload;
  }

  function processOnAxis(axisInfo, newValue, updaters, noSnap, outputFinder) {
    var axis = axisInfo.axis;

    if (axis.scale.isBlank() || !axis.containData(newValue)) {
      return;
    }

    if (!axisInfo.involveSeries) {
      updaters.showPointer(axisInfo, newValue);
      return;
    }

    var payloadInfo = buildPayloadsBySeries(newValue, axisInfo);
    var payloadBatch = payloadInfo.payloadBatch;
    var snapToValue = payloadInfo.snapToValue;

    if (payloadBatch[0] && outputFinder.seriesIndex == null) {
      extend(outputFinder, payloadBatch[0]);
    }

    if (!noSnap && axisInfo.snap) {
      if (axis.containData(snapToValue) && snapToValue != null) {
        newValue = snapToValue;
      }
    }

    updaters.showPointer(axisInfo, newValue, payloadBatch);
    updaters.showTooltip(axisInfo, payloadInfo, snapToValue);
  }

  function buildPayloadsBySeries(value, axisInfo) {
    var axis = axisInfo.axis;
    var dim = axis.dim;
    var snapToValue = value;
    var payloadBatch = [];
    var minDist = Number.MAX_VALUE;
    var minDiff = -1;
    each(axisInfo.seriesModels, function (series, idx) {
      var dataDim = series.getData().mapDimensionsAll(dim);
      var seriesNestestValue;
      var dataIndices;

      if (series.getAxisTooltipData) {
        var result = series.getAxisTooltipData(dataDim, value, axis);
        dataIndices = result.dataIndices;
        seriesNestestValue = result.nestestValue;
      } else {
        dataIndices = series.getData().indicesOfNearest(dataDim[0], value, axis.type === 'category' ? 0.5 : null);

        if (!dataIndices.length) {
          return;
        }

        seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]);
      }

      if (seriesNestestValue == null || !isFinite(seriesNestestValue)) {
        return;
      }

      var diff = value - seriesNestestValue;
      var dist = Math.abs(diff);

      if (dist <= minDist) {
        if (dist < minDist || diff >= 0 && minDiff < 0) {
          minDist = dist;
          minDiff = diff;
          snapToValue = seriesNestestValue;
          payloadBatch.length = 0;
        }

        each(dataIndices, function (dataIndex) {
          payloadBatch.push({
            seriesIndex: series.seriesIndex,
            dataIndexInside: dataIndex,
            dataIndex: series.getData().getRawIndex(dataIndex)
          });
        });
      }
    });
    return {
      payloadBatch: payloadBatch,
      snapToValue: snapToValue
    };
  }

  function showPointer(showValueMap, axisInfo, value, payloadBatch) {
    showValueMap[axisInfo.key] = {
      value: value,
      payloadBatch: payloadBatch
    };
  }

  function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) {
    var payloadBatch = payloadInfo.payloadBatch;
    var axis = axisInfo.axis;
    var axisModel = axis.model;
    var axisPointerModel = axisInfo.axisPointerModel;

    if (!axisInfo.triggerTooltip || !payloadBatch.length) {
      return;
    }

    var coordSysModel = axisInfo.coordSys.model;
    var coordSysKey = makeKey(coordSysModel);
    var coordSysItem = dataByCoordSys.map[coordSysKey];

    if (!coordSysItem) {
      coordSysItem = dataByCoordSys.map[coordSysKey] = {
        coordSysId: coordSysModel.id,
        coordSysIndex: coordSysModel.componentIndex,
        coordSysType: coordSysModel.type,
        coordSysMainType: coordSysModel.mainType,
        dataByAxis: []
      };
      dataByCoordSys.list.push(coordSysItem);
    }

    coordSysItem.dataByAxis.push({
      axisDim: axis.dim,
      axisIndex: axisModel.componentIndex,
      axisType: axisModel.type,
      axisId: axisModel.id,
      value: value,
      valueLabelOpt: {
        precision: axisPointerModel.get(['label', 'precision']),
        formatter: axisPointerModel.get(['label', 'formatter'])
      },
      seriesDataIndices: payloadBatch.slice()
    });
  }

  function updateModelActually(showValueMap, axesInfo, outputPayload) {
    var outputAxesInfo = outputPayload.axesInfo = [];
    each(axesInfo, function (axisInfo, key) {
      var option = axisInfo.axisPointerModel.option;
      var valItem = showValueMap[key];

      if (valItem) {
        !axisInfo.useHandle && (option.status = 'show');
        option.value = valItem.value;
        option.seriesDataIndices = (valItem.payloadBatch || []).slice();
      } else {
        !axisInfo.useHandle && (option.status = 'hide');
      }

      option.status === 'show' && outputAxesInfo.push({
        axisDim: axisInfo.axis.dim,
        axisIndex: axisInfo.axis.model.componentIndex,
        value: option.value
      });
    });
  }

  function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) {
    if (illegalPoint(point) || !dataByCoordSys.list.length) {
      dispatchAction({
        type: 'hideTip'
      });
      return;
    }

    var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {};
    dispatchAction({
      type: 'showTip',
      escapeConnect: true,
      x: point[0],
      y: point[1],
      tooltipOption: payload.tooltipOption,
      position: payload.position,
      dataIndexInside: sampleItem.dataIndexInside,
      dataIndex: sampleItem.dataIndex,
      seriesIndex: sampleItem.seriesIndex,
      dataByCoordSys: dataByCoordSys.list
    });
  }

  function dispatchHighDownActually(axesInfo, dispatchAction, api) {
    var zr = api.getZr();
    var highDownKey = 'axisPointerLastHighlights';
    var lastHighlights = inner$b(zr)[highDownKey] || {};
    var newHighlights = inner$b(zr)[highDownKey] = {};
    each(axesInfo, function (axisInfo, key) {
      var option = axisInfo.axisPointerModel.option;
      option.status === 'show' && each(option.seriesDataIndices, function (batchItem) {
        var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex;
        newHighlights[key] = batchItem;
      });
    });
    var toHighlight = [];
    var toDownplay = [];
    each(lastHighlights, function (batchItem, key) {
      !newHighlights[key] && toDownplay.push(batchItem);
    });
    each(newHighlights, function (batchItem, key) {
      !lastHighlights[key] && toHighlight.push(batchItem);
    });
    toDownplay.length && api.dispatchAction({
      type: 'downplay',
      escapeConnect: true,
      notBlur: true,
      batch: toDownplay
    });
    toHighlight.length && api.dispatchAction({
      type: 'highlight',
      escapeConnect: true,
      notBlur: true,
      batch: toHighlight
    });
  }

  function findInputAxisInfo(inputAxesInfo, axisInfo) {
    for (var i = 0; i < (inputAxesInfo || []).length; i++) {
      var inputAxisInfo = inputAxesInfo[i];

      if (axisInfo.axis.dim === inputAxisInfo.axisDim && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex) {
        return inputAxisInfo;
      }
    }
  }

  function makeMapperParam(axisInfo) {
    var axisModel = axisInfo.axis.model;
    var item = {};
    var dim = item.axisDim = axisInfo.axis.dim;
    item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex;
    item.axisName = item[dim + 'AxisName'] = axisModel.name;
    item.axisId = item[dim + 'AxisId'] = axisModel.id;
    return item;
  }

  function illegalPoint(point) {
    return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]);
  }

  var inner$c = makeInner();
  var each$8 = each;

  function register(key, api, handler) {
    if (env.node) {
      return;
    }

    var zr = api.getZr();
    inner$c(zr).records || (inner$c(zr).records = {});
    initGlobalListeners(zr, api);
    var record = inner$c(zr).records[key] || (inner$c(zr).records[key] = {});
    record.handler = handler;
  }

  function initGlobalListeners(zr, api) {
    if (inner$c(zr).initialized) {
      return;
    }

    inner$c(zr).initialized = true;
    useHandler('click', curry(doEnter, 'click'));
    useHandler('mousemove', curry(doEnter, 'mousemove'));
    useHandler('globalout', onLeave);

    function useHandler(eventType, cb) {
      zr.on(eventType, function (e) {
        var dis = makeDispatchAction(api);
        each$8(inner$c(zr).records, function (record) {
          record && cb(record, e, dis.dispatchAction);
        });
        dispatchTooltipFinally(dis.pendings, api);
      });
    }
  }

  function dispatchTooltipFinally(pendings, api) {
    var showLen = pendings.showTip.length;
    var hideLen = pendings.hideTip.length;
    var actuallyPayload;

    if (showLen) {
      actuallyPayload = pendings.showTip[showLen - 1];
    } else if (hideLen) {
      actuallyPayload = pendings.hideTip[hideLen - 1];
    }

    if (actuallyPayload) {
      actuallyPayload.dispatchAction = null;
      api.dispatchAction(actuallyPayload);
    }
  }

  function onLeave(record, e, dispatchAction) {
    record.handler('leave', null, dispatchAction);
  }

  function doEnter(currTrigger, record, e, dispatchAction) {
    record.handler(currTrigger, e, dispatchAction);
  }

  function makeDispatchAction(api) {
    var pendings = {
      showTip: [],
      hideTip: []
    };

    var dispatchAction = function (payload) {
      var pendingList = pendings[payload.type];

      if (pendingList) {
        pendingList.push(payload);
      } else {
        payload.dispatchAction = dispatchAction;
        api.dispatchAction(payload);
      }
    };

    return {
      dispatchAction: dispatchAction,
      pendings: pendings
    };
  }

  function unregister(key, api) {
    if (env.node) {
      return;
    }

    var zr = api.getZr();
    var record = (inner$c(zr).records || {})[key];

    if (record) {
      inner$c(zr).records[key] = null;
    }
  }

  var AxisPointerView = function (_super) {
    __extends(AxisPointerView, _super);

    function AxisPointerView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = AxisPointerView.type;
      return _this;
    }

    AxisPointerView.prototype.render = function (globalAxisPointerModel, ecModel, api) {
      var globalTooltipModel = ecModel.getComponent('tooltip');
      var triggerOn = globalAxisPointerModel.get('triggerOn') || globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click';
      register('axisPointer', api, function (currTrigger, e, dispatchAction) {
        if (triggerOn !== 'none' && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)) {
          dispatchAction({
            type: 'updateAxisPointer',
            currTrigger: currTrigger,
            x: e && e.offsetX,
            y: e && e.offsetY
          });
        }
      });
    };

    AxisPointerView.prototype.remove = function (ecModel, api) {
      unregister('axisPointer', api);
    };

    AxisPointerView.prototype.dispose = function (ecModel, api) {
      unregister('axisPointer', api);
    };

    AxisPointerView.type = 'axisPointer';
    return AxisPointerView;
  }(ComponentView);

  ComponentView.registerClass(AxisPointerView);
  var inner$d = makeInner();
  var clone$3 = clone;
  var bind$1 = bind;

  var BaseAxisPointer = function () {
    function BaseAxisPointer() {
      this._dragging = false;
      this.animationThreshold = 15;
    }

    BaseAxisPointer.prototype.render = function (axisModel, axisPointerModel, api, forceRender) {
      var value = axisPointerModel.get('value');
      var status = axisPointerModel.get('status');
      this._axisModel = axisModel;
      this._axisPointerModel = axisPointerModel;
      this._api = api;

      if (!forceRender && this._lastValue === value && this._lastStatus === status) {
        return;
      }

      this._lastValue = value;
      this._lastStatus = status;
      var group = this._group;
      var handle = this._handle;

      if (!status || status === 'hide') {
        group && group.hide();
        handle && handle.hide();
        return;
      }

      group && group.show();
      handle && handle.show();
      var elOption = {};
      this.makeElOption(elOption, value, axisModel, axisPointerModel, api);
      var graphicKey = elOption.graphicKey;

      if (graphicKey !== this._lastGraphicKey) {
        this.clear(api);
      }

      this._lastGraphicKey = graphicKey;
      var moveAnimation = this._moveAnimation = this.determineAnimation(axisModel, axisPointerModel);

      if (!group) {
        group = this._group = new Group();
        this.createPointerEl(group, elOption, axisModel, axisPointerModel);
        this.createLabelEl(group, elOption, axisModel, axisPointerModel);
        api.getZr().add(group);
      } else {
        var doUpdateProps = curry(updateProps$1, axisPointerModel, moveAnimation);
        this.updatePointerEl(group, elOption, doUpdateProps);
        this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel);
      }

      updateMandatoryProps(group, axisPointerModel, true);

      this._renderHandle(value);
    };

    BaseAxisPointer.prototype.remove = function (api) {
      this.clear(api);
    };

    BaseAxisPointer.prototype.dispose = function (api) {
      this.clear(api);
    };

    BaseAxisPointer.prototype.determineAnimation = function (axisModel, axisPointerModel) {
      var animation = axisPointerModel.get('animation');
      var axis = axisModel.axis;
      var isCategoryAxis = axis.type === 'category';
      var useSnap = axisPointerModel.get('snap');

      if (!useSnap && !isCategoryAxis) {
        return false;
      }

      if (animation === 'auto' || animation == null) {
        var animationThreshold = this.animationThreshold;

        if (isCategoryAxis && axis.getBandWidth() > animationThreshold) {
          return true;
        }

        if (useSnap) {
          var seriesDataCount = getAxisInfo(axisModel).seriesDataCount;
          var axisExtent = axis.getExtent();
          return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold;
        }

        return false;
      }

      return animation === true;
    };

    BaseAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {};

    BaseAxisPointer.prototype.createPointerEl = function (group, elOption, axisModel, axisPointerModel) {
      var pointerOption = elOption.pointer;

      if (pointerOption) {
        var pointerEl = inner$d(group).pointerEl = new graphic[pointerOption.type](clone$3(elOption.pointer));
        group.add(pointerEl);
      }
    };

    BaseAxisPointer.prototype.createLabelEl = function (group, elOption, axisModel, axisPointerModel) {
      if (elOption.label) {
        var labelEl = inner$d(group).labelEl = new ZRText(clone$3(elOption.label));
        group.add(labelEl);
        updateLabelShowHide(labelEl, axisPointerModel);
      }
    };

    BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) {
      var pointerEl = inner$d(group).pointerEl;

      if (pointerEl && elOption.pointer) {
        pointerEl.setStyle(elOption.pointer.style);
        updateProps(pointerEl, {
          shape: elOption.pointer.shape
        });
      }
    };

    BaseAxisPointer.prototype.updateLabelEl = function (group, elOption, updateProps, axisPointerModel) {
      var labelEl = inner$d(group).labelEl;

      if (labelEl) {
        labelEl.setStyle(elOption.label.style);
        updateProps(labelEl, {
          x: elOption.label.x,
          y: elOption.label.y
        });
        updateLabelShowHide(labelEl, axisPointerModel);
      }
    };

    BaseAxisPointer.prototype._renderHandle = function (value) {
      if (this._dragging || !this.updateHandleTransform) {
        return;
      }

      var axisPointerModel = this._axisPointerModel;

      var zr = this._api.getZr();

      var handle = this._handle;
      var handleModel = axisPointerModel.getModel('handle');
      var status = axisPointerModel.get('status');

      if (!handleModel.get('show') || !status || status === 'hide') {
        handle && zr.remove(handle);
        this._handle = null;
        return;
      }

      var isInit;

      if (!this._handle) {
        isInit = true;
        handle = this._handle = createIcon(handleModel.get('icon'), {
          cursor: 'move',
          draggable: true,
          onmousemove: function (e) {
            stop(e.event);
          },
          onmousedown: bind$1(this._onHandleDragMove, this, 0, 0),
          drift: bind$1(this._onHandleDragMove, this),
          ondragend: bind$1(this._onHandleDragEnd, this)
        });
        zr.add(handle);
      }

      updateMandatoryProps(handle, axisPointerModel, false);
      handle.setStyle(handleModel.getItemStyle(null, ['color', 'borderColor', 'borderWidth', 'opacity', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY']));
      var handleSize = handleModel.get('size');

      if (!isArray(handleSize)) {
        handleSize = [handleSize, handleSize];
      }

      handle.scaleX = handleSize[0] / 2;
      handle.scaleY = handleSize[1] / 2;
      createOrUpdate(this, '_doDispatchAxisPointer', handleModel.get('throttle') || 0, 'fixRate');

      this._moveHandleToValue(value, isInit);
    };

    BaseAxisPointer.prototype._moveHandleToValue = function (value, isInit) {
      updateProps$1(this._axisPointerModel, !isInit && this._moveAnimation, this._handle, getHandleTransProps(this.getHandleTransform(value, this._axisModel, this._axisPointerModel)));
    };

    BaseAxisPointer.prototype._onHandleDragMove = function (dx, dy) {
      var handle = this._handle;

      if (!handle) {
        return;
      }

      this._dragging = true;
      var trans = this.updateHandleTransform(getHandleTransProps(handle), [dx, dy], this._axisModel, this._axisPointerModel);
      this._payloadInfo = trans;
      handle.stopAnimation();
      handle.attr(getHandleTransProps(trans));
      inner$d(handle).lastProp = null;

      this._doDispatchAxisPointer();
    };

    BaseAxisPointer.prototype._doDispatchAxisPointer = function () {
      var handle = this._handle;

      if (!handle) {
        return;
      }

      var payloadInfo = this._payloadInfo;
      var axisModel = this._axisModel;

      this._api.dispatchAction({
        type: 'updateAxisPointer',
        x: payloadInfo.cursorPoint[0],
        y: payloadInfo.cursorPoint[1],
        tooltipOption: payloadInfo.tooltipOption,
        axesInfo: [{
          axisDim: axisModel.axis.dim,
          axisIndex: axisModel.componentIndex
        }]
      });
    };

    BaseAxisPointer.prototype._onHandleDragEnd = function () {
      this._dragging = false;
      var handle = this._handle;

      if (!handle) {
        return;
      }

      var value = this._axisPointerModel.get('value');

      this._moveHandleToValue(value);

      this._api.dispatchAction({
        type: 'hideTip'
      });
    };

    BaseAxisPointer.prototype.clear = function (api) {
      this._lastValue = null;
      this._lastStatus = null;
      var zr = api.getZr();
      var group = this._group;
      var handle = this._handle;

      if (zr && group) {
        this._lastGraphicKey = null;
        group && zr.remove(group);
        handle && zr.remove(handle);
        this._group = null;
        this._handle = null;
        this._payloadInfo = null;
      }
    };

    BaseAxisPointer.prototype.doClear = function () {};

    BaseAxisPointer.prototype.buildLabel = function (xy, wh, xDimIndex) {
      xDimIndex = xDimIndex || 0;
      return {
        x: xy[xDimIndex],
        y: xy[1 - xDimIndex],
        width: wh[xDimIndex],
        height: wh[1 - xDimIndex]
      };
    };

    return BaseAxisPointer;
  }();

  function updateProps$1(animationModel, moveAnimation, el, props) {
    if (!propsEqual(inner$d(el).lastProp, props)) {
      inner$d(el).lastProp = props;
      moveAnimation ? updateProps(el, props, animationModel) : (el.stopAnimation(), el.attr(props));
    }
  }

  function propsEqual(lastProps, newProps) {
    if (isObject(lastProps) && isObject(newProps)) {
      var equals_1 = true;
      each(newProps, function (item, key) {
        equals_1 = equals_1 && propsEqual(lastProps[key], item);
      });
      return !!equals_1;
    } else {
      return lastProps === newProps;
    }
  }

  function updateLabelShowHide(labelEl, axisPointerModel) {
    labelEl[axisPointerModel.get(['label', 'show']) ? 'show' : 'hide']();
  }

  function getHandleTransProps(trans) {
    return {
      x: trans.x || 0,
      y: trans.y || 0,
      rotation: trans.rotation || 0
    };
  }

  function updateMandatoryProps(group, axisPointerModel, silent) {
    var z = axisPointerModel.get('z');
    var zlevel = axisPointerModel.get('zlevel');
    group && group.traverse(function (el) {
      if (el.type !== 'group') {
        z != null && (el.z = z);
        zlevel != null && (el.zlevel = zlevel);
        el.silent = silent;
      }
    });
  }

  function buildElStyle(axisPointerModel) {
    var axisPointerType = axisPointerModel.get('type');
    var styleModel = axisPointerModel.getModel(axisPointerType + 'Style');
    var style;

    if (axisPointerType === 'line') {
      style = styleModel.getLineStyle();
      style.fill = null;
    } else if (axisPointerType === 'shadow') {
      style = styleModel.getAreaStyle();
      style.stroke = null;
    }

    return style;
  }

  function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) {
    var value = axisPointerModel.get('value');
    var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), {
      precision: axisPointerModel.get(['label', 'precision']),
      formatter: axisPointerModel.get(['label', 'formatter'])
    });
    var labelModel = axisPointerModel.getModel('label');
    var paddings = normalizeCssArray$1(labelModel.get('padding') || 0);
    var font = labelModel.getFont();
    var textRect = getBoundingRect(text, font);
    var position = labelPos.position;
    var width = textRect.width + paddings[1] + paddings[3];
    var height = textRect.height + paddings[0] + paddings[2];
    var align = labelPos.align;
    align === 'right' && (position[0] -= width);
    align === 'center' && (position[0] -= width / 2);
    var verticalAlign = labelPos.verticalAlign;
    verticalAlign === 'bottom' && (position[1] -= height);
    verticalAlign === 'middle' && (position[1] -= height / 2);
    confineInContainer(position, width, height, api);
    var bgColor = labelModel.get('backgroundColor');

    if (!bgColor || bgColor === 'auto') {
      bgColor = axisModel.get(['axisLine', 'lineStyle', 'color']);
    }

    elOption.label = {
      x: position[0],
      y: position[1],
      style: createTextStyle(labelModel, {
        text: text,
        font: font,
        fill: labelModel.getTextColor(),
        padding: paddings,
        backgroundColor: bgColor
      }),
      z2: 10
    };
  }

  function confineInContainer(position, width, height, api) {
    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();
    position[0] = Math.min(position[0] + width, viewWidth) - width;
    position[1] = Math.min(position[1] + height, viewHeight) - height;
    position[0] = Math.max(position[0], 0);
    position[1] = Math.max(position[1], 0);
  }

  function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) {
    value = axis.scale.parse(value);
    var text = axis.scale.getLabel({
      value: value
    }, {
      precision: opt.precision
    });
    var formatter = opt.formatter;

    if (formatter) {
      var params_1 = {
        value: getAxisRawValue(axis, {
          value: value
        }),
        axisDimension: axis.dim,
        axisIndex: axis.index,
        seriesData: []
      };
      each(seriesDataIndices, function (idxItem) {
        var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
        var dataIndex = idxItem.dataIndexInside;
        var dataParams = series && series.getDataParams(dataIndex);
        dataParams && params_1.seriesData.push(dataParams);
      });

      if (isString(formatter)) {
        text = formatter.replace('{value}', text);
      } else if (isFunction(formatter)) {
        text = formatter(params_1);
      }
    }

    return text;
  }

  function getTransformedPosition(axis, value, layoutInfo) {
    var transform = create$1();
    rotate(transform, transform, layoutInfo.rotation);
    translate(transform, transform, layoutInfo.position);
    return applyTransform$1([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform);
  }

  function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) {
    var textLayout = AxisBuilder.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection);
    layoutInfo.labelMargin = axisPointerModel.get(['label', 'margin']);
    buildLabelElOption(elOption, axisModel, axisPointerModel, api, {
      position: getTransformedPosition(axisModel.axis, value, layoutInfo),
      align: textLayout.textAlign,
      verticalAlign: textLayout.textVerticalAlign
    });
  }

  function makeLineShape(p1, p2, xDimIndex) {
    xDimIndex = xDimIndex || 0;
    return {
      x1: p1[xDimIndex],
      y1: p1[1 - xDimIndex],
      x2: p2[xDimIndex],
      y2: p2[1 - xDimIndex]
    };
  }

  function makeRectShape(xy, wh, xDimIndex) {
    xDimIndex = xDimIndex || 0;
    return {
      x: xy[xDimIndex],
      y: xy[1 - xDimIndex],
      width: wh[xDimIndex],
      height: wh[1 - xDimIndex]
    };
  }

  function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) {
    return {
      cx: cx,
      cy: cy,
      r0: r0,
      r: r,
      startAngle: startAngle,
      endAngle: endAngle,
      clockwise: true
    };
  }

  var CartesianAxisPointer = function (_super) {
    __extends(CartesianAxisPointer, _super);

    function CartesianAxisPointer() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    CartesianAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {
      var axis = axisModel.axis;
      var grid = axis.grid;
      var axisPointerType = axisPointerModel.get('type');
      var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
      var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true));

      if (axisPointerType && axisPointerType !== 'none') {
        var elStyle = buildElStyle(axisPointerModel);
        var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent);
        pointerOption.style = elStyle;
        elOption.graphicKey = pointerOption.type;
        elOption.pointer = pointerOption;
      }

      var layoutInfo = layout$1(grid.model, axisModel);
      buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api);
    };

    CartesianAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) {
      var layoutInfo = layout$1(axisModel.axis.grid.model, axisModel, {
        labelInside: false
      });
      layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']);
      var pos = getTransformedPosition(axisModel.axis, value, layoutInfo);
      return {
        x: pos[0],
        y: pos[1],
        rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
      };
    };

    CartesianAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) {
      var axis = axisModel.axis;
      var grid = axis.grid;
      var axisExtent = axis.getGlobalExtent(true);
      var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
      var dimIndex = axis.dim === 'x' ? 0 : 1;
      var currPosition = [transform.x, transform.y];
      currPosition[dimIndex] += delta[dimIndex];
      currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
      currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
      var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
      var cursorPoint = [cursorOtherValue, cursorOtherValue];
      cursorPoint[dimIndex] = currPosition[dimIndex];
      var tooltipOptions = [{
        verticalAlign: 'middle'
      }, {
        align: 'center'
      }];
      return {
        x: currPosition[0],
        y: currPosition[1],
        rotation: transform.rotation,
        cursorPoint: cursorPoint,
        tooltipOption: tooltipOptions[dimIndex]
      };
    };

    return CartesianAxisPointer;
  }(BaseAxisPointer);

  function getCartesian(grid, axis) {
    var opt = {};
    opt[axis.dim + 'AxisIndex'] = axis.index;
    return grid.getCartesian(opt);
  }

  var pointerShapeBuilder = {
    line: function (axis, pixelValue, otherExtent) {
      var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis));
      return {
        type: 'Line',
        subPixelOptimize: true,
        shape: targetShape
      };
    },
    shadow: function (axis, pixelValue, otherExtent) {
      var bandWidth = Math.max(1, axis.getBandWidth());
      var span = otherExtent[1] - otherExtent[0];
      return {
        type: 'Rect',
        shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getAxisDimIndex(axis))
      };
    }
  };

  function getAxisDimIndex(axis) {
    return axis.dim === 'x' ? 0 : 1;
  }

  AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer);

  var AxisPointerModel = function (_super) {
    __extends(AxisPointerModel, _super);

    function AxisPointerModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = AxisPointerModel.type;
      return _this;
    }

    AxisPointerModel.type = 'axisPointer';
    AxisPointerModel.defaultOption = {
      show: 'auto',
      zlevel: 0,
      z: 50,
      type: 'line',
      snap: false,
      triggerTooltip: true,
      value: null,
      status: null,
      link: [],
      animation: null,
      animationDurationUpdate: 200,
      lineStyle: {
        color: '#B9BEC9',
        width: 1,
        type: 'dashed'
      },
      shadowStyle: {
        color: 'rgba(210,219,238,0.2)'
      },
      label: {
        show: true,
        formatter: null,
        precision: 'auto',
        margin: 3,
        color: '#fff',
        padding: [5, 7, 5, 7],
        backgroundColor: 'auto',
        borderColor: null,
        borderWidth: 0,
        borderRadius: 3
      },
      handle: {
        show: false,
        icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z',
        size: 45,
        margin: 50,
        color: '#333',
        shadowBlur: 3,
        shadowColor: '#aaa',
        shadowOffsetX: 0,
        shadowOffsetY: 2,
        throttle: 40
      }
    };
    return AxisPointerModel;
  }(ComponentModel);

  ComponentModel.registerClass(AxisPointerModel);
  registerPreprocessor(function (option) {
    if (option) {
      (!option.axisPointer || option.axisPointer.length === 0) && (option.axisPointer = {});
      var link = option.axisPointer.link;

      if (link && !isArray(link)) {
        option.axisPointer.link = [link];
      }
    }
  });
  registerProcessor(PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) {
    ecModel.getComponent('axisPointer').coordSysAxesInfo = collect(ecModel, api);
  });
  registerAction({
    type: 'updateAxisPointer',
    event: 'updateAxisPointer',
    update: ':updateAxisPointer'
  }, axisTrigger);
  var XY = ['x', 'y'];
  var WH = ['width', 'height'];

  var SingleAxisPointer = function (_super) {
    __extends(SingleAxisPointer, _super);

    function SingleAxisPointer() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    SingleAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {
      var axis = axisModel.axis;
      var coordSys = axis.coordinateSystem;
      var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis));
      var pixelValue = coordSys.dataToPoint(value)[0];
      var axisPointerType = axisPointerModel.get('type');

      if (axisPointerType && axisPointerType !== 'none') {
        var elStyle = buildElStyle(axisPointerModel);
        var pointerOption = pointerShapeBuilder$1[axisPointerType](axis, pixelValue, otherExtent);
        pointerOption.style = elStyle;
        elOption.graphicKey = pointerOption.type;
        elOption.pointer = pointerOption;
      }

      var layoutInfo = layout$2(axisModel);
      buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api);
    };

    SingleAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) {
      var layoutInfo = layout$2(axisModel, {
        labelInside: false
      });
      layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']);
      var position = getTransformedPosition(axisModel.axis, value, layoutInfo);
      return {
        x: position[0],
        y: position[1],
        rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
      };
    };

    SingleAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) {
      var axis = axisModel.axis;
      var coordSys = axis.coordinateSystem;
      var dimIndex = getPointDimIndex(axis);
      var axisExtent = getGlobalExtent(coordSys, dimIndex);
      var currPosition = [transform.x, transform.y];
      currPosition[dimIndex] += delta[dimIndex];
      currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
      currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
      var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex);
      var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
      var cursorPoint = [cursorOtherValue, cursorOtherValue];
      cursorPoint[dimIndex] = currPosition[dimIndex];
      return {
        x: currPosition[0],
        y: currPosition[1],
        rotation: transform.rotation,
        cursorPoint: cursorPoint,
        tooltipOption: {
          verticalAlign: 'middle'
        }
      };
    };

    return SingleAxisPointer;
  }(BaseAxisPointer);

  var pointerShapeBuilder$1 = {
    line: function (axis, pixelValue, otherExtent) {
      var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getPointDimIndex(axis));
      return {
        type: 'Line',
        subPixelOptimize: true,
        shape: targetShape
      };
    },
    shadow: function (axis, pixelValue, otherExtent) {
      var bandWidth = axis.getBandWidth();
      var span = otherExtent[1] - otherExtent[0];
      return {
        type: 'Rect',
        shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getPointDimIndex(axis))
      };
    }
  };

  function getPointDimIndex(axis) {
    return axis.isHorizontal() ? 0 : 1;
  }

  function getGlobalExtent(coordSys, dimIndex) {
    var rect = coordSys.getRect();
    return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]];
  }

  AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer);
  extendComponentView({
    type: 'single'
  });
  var DATA_NAME_INDEX = 2;

  var ThemeRiverSeriesModel = function (_super) {
    __extends(ThemeRiverSeriesModel, _super);

    function ThemeRiverSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ThemeRiverSeriesModel.type;
      _this.useColorPaletteOnData = true;
      return _this;
    }

    ThemeRiverSeriesModel.prototype.init = function (option) {
      _super.prototype.init.apply(this, arguments);

      this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this));
    };

    ThemeRiverSeriesModel.prototype.fixData = function (data) {
      var rawDataLength = data.length;
      var timeValueKeys = {};
      var groupResult = groupData(data, function (item) {
        if (!timeValueKeys.hasOwnProperty(item[0] + '')) {
          timeValueKeys[item[0] + ''] = -1;
        }

        return item[2];
      });
      var layerData = [];
      groupResult.buckets.each(function (items, key) {
        layerData.push({
          name: key,
          dataList: items
        });
      });
      var layerNum = layerData.length;

      for (var k = 0; k < layerNum; ++k) {
        var name_1 = layerData[k].name;

        for (var j = 0; j < layerData[k].dataList.length; ++j) {
          var timeValue = layerData[k].dataList[j][0] + '';
          timeValueKeys[timeValue] = k;
        }

        for (var timeValue in timeValueKeys) {
          if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) {
            timeValueKeys[timeValue] = k;
            data[rawDataLength] = [timeValue, 0, name_1];
            rawDataLength++;
          }
        }
      }

      return data;
    };

    ThemeRiverSeriesModel.prototype.getInitialData = function (option, ecModel) {
      var singleAxisModel = this.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0];
      var axisType = singleAxisModel.get('type');
      var filterData = filter(option.data, function (dataItem) {
        return dataItem[2] !== undefined;
      });
      var data = this.fixData(filterData || []);
      var nameList = [];
      var nameMap = this.nameMap = createHashMap();
      var count = 0;

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

        if (!nameMap.get(data[i][DATA_NAME_INDEX])) {
          nameMap.set(data[i][DATA_NAME_INDEX], count);
          count++;
        }
      }

      var dimensionsInfo = createDimensions(data, {
        coordDimensions: ['single'],
        dimensionsDefine: [{
          name: 'time',
          type: getDimensionTypeByAxis(axisType)
        }, {
          name: 'value',
          type: 'float'
        }, {
          name: 'name',
          type: 'ordinal'
        }],
        encodeDefine: {
          single: 0,
          value: 1,
          itemName: 2
        }
      });
      var list = new List(dimensionsInfo, this);
      list.initData(data);
      return list;
    };

    ThemeRiverSeriesModel.prototype.getLayerSeries = function () {
      var data = this.getData();
      var lenCount = data.count();
      var indexArr = [];

      for (var i = 0; i < lenCount; ++i) {
        indexArr[i] = i;
      }

      var timeDim = data.mapDimension('single');
      var groupResult = groupData(indexArr, function (index) {
        return data.get('name', index);
      });
      var layerSeries = [];
      groupResult.buckets.each(function (items, key) {
        items.sort(function (index1, index2) {
          return data.get(timeDim, index1) - data.get(timeDim, index2);
        });
        layerSeries.push({
          name: key,
          indices: items
        });
      });
      return layerSeries;
    };

    ThemeRiverSeriesModel.prototype.getAxisTooltipData = function (dim, value, baseAxis) {
      if (!isArray(dim)) {
        dim = dim ? [dim] : [];
      }

      var data = this.getData();
      var layerSeries = this.getLayerSeries();
      var indices = [];
      var layerNum = layerSeries.length;
      var nestestValue;

      for (var i = 0; i < layerNum; ++i) {
        var minDist = Number.MAX_VALUE;
        var nearestIdx = -1;
        var pointNum = layerSeries[i].indices.length;

        for (var j = 0; j < pointNum; ++j) {
          var theValue = data.get(dim[0], layerSeries[i].indices[j]);
          var dist = Math.abs(theValue - value);

          if (dist <= minDist) {
            nestestValue = theValue;
            minDist = dist;
            nearestIdx = layerSeries[i].indices[j];
          }
        }

        indices.push(nearestIdx);
      }

      return {
        dataIndices: indices,
        nestestValue: nestestValue
      };
    };

    ThemeRiverSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var name = data.getName(dataIndex);
      var value = data.get(data.mapDimension('value'), dataIndex);
      return createTooltipMarkup('nameValue', {
        name: name,
        value: value
      });
    };

    ThemeRiverSeriesModel.type = 'series.themeRiver';
    ThemeRiverSeriesModel.dependencies = ['singleAxis'];
    ThemeRiverSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      coordinateSystem: 'singleAxis',
      boundaryGap: ['10%', '10%'],
      singleAxisIndex: 0,
      animationEasing: 'linear',
      label: {
        margin: 4,
        show: true,
        position: 'left',
        fontSize: 11
      },
      emphasis: {
        label: {
          show: true
        }
      }
    };
    return ThemeRiverSeriesModel;
  }(SeriesModel);

  SeriesModel.registerClass(ThemeRiverSeriesModel);

  var ThemeRiverView = function (_super) {
    __extends(ThemeRiverView, _super);

    function ThemeRiverView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ThemeRiverView.type;
      _this._layers = [];
      return _this;
    }

    ThemeRiverView.prototype.render = function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var self = this;
      var group = this.group;
      var layersSeries = seriesModel.getLayerSeries();
      var layoutInfo = data.getLayout('layoutInfo');
      var rect = layoutInfo.rect;
      var boundaryGap = layoutInfo.boundaryGap;
      group.x = 0;
      group.y = rect.y + boundaryGap[0];

      function keyGetter(item) {
        return item.name;
      }

      var dataDiffer = new DataDiffer(this._layersSeries || [], layersSeries, keyGetter, keyGetter);
      var newLayersGroups = [];
      dataDiffer.add(bind(process, this, 'add')).update(bind(process, this, 'update')).remove(bind(process, this, 'remove')).execute();

      function process(status, idx, oldIdx) {
        var oldLayersGroups = self._layers;

        if (status === 'remove') {
          group.remove(oldLayersGroups[idx]);
          return;
        }

        var points0 = [];
        var points1 = [];
        var style;
        var indices = layersSeries[idx].indices;
        var j = 0;

        for (; j < indices.length; j++) {
          var layout = data.getItemLayout(indices[j]);
          var x = layout.x;
          var y0 = layout.y0;
          var y = layout.y;
          points0.push(x, y0);
          points1.push(x, y0 + y);
          style = data.getItemVisual(indices[j], 'style');
        }

        var polygon;
        var textLayout = data.getItemLayout(indices[0]);
        var labelModel = seriesModel.getModel('label');
        var margin = labelModel.get('margin');
        var emphasisModel = seriesModel.getModel('emphasis');

        if (status === 'add') {
          var layerGroup = newLayersGroups[idx] = new Group();
          polygon = new ECPolygon({
            shape: {
              points: points0,
              stackedOnPoints: points1,
              smooth: 0.4,
              stackedOnSmooth: 0.4,
              smoothConstraint: false
            },
            z2: 0
          });
          layerGroup.add(polygon);
          group.add(layerGroup);

          if (seriesModel.isAnimationEnabled()) {
            polygon.setClipPath(createGridClipShape$2(polygon.getBoundingRect(), seriesModel, function () {
              polygon.removeClipPath();
            }));
          }
        } else {
          var layerGroup = oldLayersGroups[oldIdx];
          polygon = layerGroup.childAt(0);
          group.add(layerGroup);
          newLayersGroups[idx] = layerGroup;
          updateProps(polygon, {
            shape: {
              points: points0,
              stackedOnPoints: points1
            }
          }, seriesModel);
        }

        setLabelStyle(polygon, getLabelStatesModels(seriesModel), {
          labelDataIndex: indices[j - 1],
          defaultText: data.getName(indices[j - 1]),
          inheritColor: style.fill
        }, {
          normal: {
            verticalAlign: 'middle'
          }
        });
        polygon.setTextConfig({
          position: null,
          local: true
        });
        var labelEl = polygon.getTextContent();

        if (labelEl) {
          labelEl.x = textLayout.x - margin;
          labelEl.y = textLayout.y0 + textLayout.y / 2;
        }

        polygon.useStyle(style);
        data.setItemGraphicEl(idx, polygon);
        setStatesStylesFromModel(polygon, seriesModel);
        enableHoverEmphasis(polygon, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
      }

      this._layersSeries = layersSeries;
      this._layers = newLayersGroups;
    };

    ThemeRiverView.type = 'themeRiver';
    return ThemeRiverView;
  }(ChartView);

  function createGridClipShape$2(rect, seriesModel, cb) {
    var rectEl = new Rect({
      shape: {
        x: rect.x - 10,
        y: rect.y - 10,
        width: 0,
        height: rect.height + 20
      }
    });
    initProps(rectEl, {
      shape: {
        x: rect.x - 50,
        width: rect.width + 100,
        height: rect.height + 20
      }
    }, seriesModel, cb);
    return rectEl;
  }

  ChartView.registerClass(ThemeRiverView);

  function themeRiverLayout(ecModel, api) {
    ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
      var data = seriesModel.getData();
      var single = seriesModel.coordinateSystem;
      var layoutInfo = {};
      var rect = single.getRect();
      layoutInfo.rect = rect;
      var boundaryGap = seriesModel.get('boundaryGap');
      var axis = single.getAxis();
      layoutInfo.boundaryGap = boundaryGap;

      if (axis.orient === 'horizontal') {
        boundaryGap[0] = parsePercent$2(boundaryGap[0], rect.height);
        boundaryGap[1] = parsePercent$2(boundaryGap[1], rect.height);
        var height = rect.height - boundaryGap[0] - boundaryGap[1];
        doThemeRiverLayout(data, seriesModel, height);
      } else {
        boundaryGap[0] = parsePercent$2(boundaryGap[0], rect.width);
        boundaryGap[1] = parsePercent$2(boundaryGap[1], rect.width);
        var width = rect.width - boundaryGap[0] - boundaryGap[1];
        doThemeRiverLayout(data, seriesModel, width);
      }

      data.setLayout('layoutInfo', layoutInfo);
    });
  }

  function doThemeRiverLayout(data, seriesModel, height) {
    if (!data.count()) {
      return;
    }

    var coordSys = seriesModel.coordinateSystem;
    var layerSeries = seriesModel.getLayerSeries();
    var timeDim = data.mapDimension('single');
    var valueDim = data.mapDimension('value');
    var layerPoints = map(layerSeries, function (singleLayer) {
      return map(singleLayer.indices, function (idx) {
        var pt = coordSys.dataToPoint(data.get(timeDim, idx));
        pt[1] = data.get(valueDim, idx);
        return pt;
      });
    });
    var base = computeBaseline(layerPoints);
    var baseLine = base.y0;
    var ky = height / base.max;
    var n = layerSeries.length;
    var m = layerSeries[0].indices.length;
    var baseY0;

    for (var j = 0; j < m; ++j) {
      baseY0 = baseLine[j] * ky;
      data.setItemLayout(layerSeries[0].indices[j], {
        layerIndex: 0,
        x: layerPoints[0][j][0],
        y0: baseY0,
        y: layerPoints[0][j][1] * ky
      });

      for (var i = 1; i < n; ++i) {
        baseY0 += layerPoints[i - 1][j][1] * ky;
        data.setItemLayout(layerSeries[i].indices[j], {
          layerIndex: i,
          x: layerPoints[i][j][0],
          y0: baseY0,
          y: layerPoints[i][j][1] * ky
        });
      }
    }
  }

  function computeBaseline(data) {
    var layerNum = data.length;
    var pointNum = data[0].length;
    var sums = [];
    var y0 = [];
    var max = 0;

    for (var i = 0; i < pointNum; ++i) {
      var temp = 0;

      for (var j = 0; j < layerNum; ++j) {
        temp += data[j][i][1];
      }

      if (temp > max) {
        max = temp;
      }

      sums.push(temp);
    }

    for (var k = 0; k < pointNum; ++k) {
      y0[k] = (max - sums[k]) / 2;
    }

    max = 0;

    for (var l = 0; l < pointNum; ++l) {
      var sum = sums[l] + y0[l];

      if (sum > max) {
        max = sum;
      }
    }

    return {
      y0: y0,
      max: max
    };
  }

  registerLayout(themeRiverLayout);
  registerProcessor(dataFilter('themeRiver'));

  var SunburstSeriesModel = function (_super) {
    __extends(SunburstSeriesModel, _super);

    function SunburstSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SunburstSeriesModel.type;
      _this.ignoreStyleOnData = true;
      return _this;
    }

    SunburstSeriesModel.prototype.getInitialData = function (option, ecModel) {
      var root = {
        name: option.name,
        children: option.data
      };
      completeTreeValue$1(root);
      var levelModels = map(option.levels || [], function (levelDefine) {
        return new Model(levelDefine, this, ecModel);
      }, this);
      var tree = Tree.createTree(root, this, beforeLink);

      function beforeLink(nodeData) {
        nodeData.wrapMethod('getItemModel', function (model, idx) {
          var node = tree.getNodeByDataIndex(idx);
          var levelModel = levelModels[node.depth];
          levelModel && (model.parentModel = levelModel);
          return model;
        });
      }

      return tree.data;
    };

    SunburstSeriesModel.prototype.optionUpdated = function () {
      this.resetViewRoot();
    };

    SunburstSeriesModel.prototype.getDataParams = function (dataIndex) {
      var params = _super.prototype.getDataParams.apply(this, arguments);

      var node = this.getData().tree.getNodeByDataIndex(dataIndex);
      params.treePathInfo = wrapTreePathInfo(node, this);
      return params;
    };

    SunburstSeriesModel.prototype.getViewRoot = function () {
      return this._viewRoot;
    };

    SunburstSeriesModel.prototype.resetViewRoot = function (viewRoot) {
      viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot;
      var root = this.getRawData().tree.root;

      if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) {
        this._viewRoot = root;
      }
    };

    SunburstSeriesModel.prototype.enableAriaDecal = function () {
      enableAriaDecalForTree(this);
    };

    SunburstSeriesModel.type = 'series.sunburst';
    SunburstSeriesModel.defaultOption = {
      zlevel: 0,
      z: 2,
      center: ['50%', '50%'],
      radius: [0, '75%'],
      clockwise: true,
      startAngle: 90,
      minAngle: 0,
      stillShowZeroSum: true,
      nodeClick: 'rootToNode',
      renderLabelForZeroData: false,
      label: {
        rotate: 'radial',
        show: true,
        opacity: 1,
        align: 'center',
        position: 'inside',
        distance: 5,
        silent: true
      },
      itemStyle: {
        borderWidth: 1,
        borderColor: 'white',
        borderType: 'solid',
        shadowBlur: 0,
        shadowColor: 'rgba(0, 0, 0, 0.2)',
        shadowOffsetX: 0,
        shadowOffsetY: 0,
        opacity: 1
      },
      emphasis: {
        focus: 'descendant'
      },
      blur: {
        itemStyle: {
          opacity: 0.2
        },
        label: {
          opacity: 0.1
        }
      },
      animationType: 'expansion',
      animationDuration: 1000,
      animationDurationUpdate: 500,
      data: [],
      levels: [],
      sort: 'desc'
    };
    return SunburstSeriesModel;
  }(SeriesModel);

  function completeTreeValue$1(dataNode) {
    var sum = 0;
    each(dataNode.children, function (child) {
      completeTreeValue$1(child);
      var childValue = child.value;
      isArray(childValue) && (childValue = childValue[0]);
      sum += childValue;
    });
    var thisValue = dataNode.value;

    if (isArray(thisValue)) {
      thisValue = thisValue[0];
    }

    if (thisValue == null || isNaN(thisValue)) {
      thisValue = sum;
    }

    if (thisValue < 0) {
      thisValue = 0;
    }

    isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue;
  }

  SeriesModel.registerClass(SunburstSeriesModel);
  var DEFAULT_SECTOR_Z = 2;
  var DEFAULT_TEXT_Z = 4;

  var SunburstPiece = function (_super) {
    __extends(SunburstPiece, _super);

    function SunburstPiece(node, seriesModel, ecModel, api) {
      var _this = _super.call(this) || this;

      _this.z2 = DEFAULT_SECTOR_Z;
      _this.textConfig = {
        inside: true
      };
      getECData(_this).seriesIndex = seriesModel.seriesIndex;
      var text = new ZRText({
        z2: DEFAULT_TEXT_Z,
        silent: node.getModel().get(['label', 'silent'])
      });

      _this.setTextContent(text);

      _this.updateData(true, node, seriesModel, ecModel, api);

      return _this;
    }

    SunburstPiece.prototype.updateData = function (firstCreate, node, seriesModel, ecModel, api) {
      this.node = node;
      node.piece = this;
      seriesModel = seriesModel || this._seriesModel;
      ecModel = ecModel || this._ecModel;
      var sector = this;
      getECData(sector).dataIndex = node.dataIndex;
      var itemModel = node.getModel();
      var emphasisModel = itemModel.getModel('emphasis');
      var layout = node.getLayout();
      var sectorShape = extend({}, layout);
      sectorShape.label = null;
      var normalStyle = node.getVisual('style');
      normalStyle.lineJoin = 'bevel';
      var decal = node.getVisual('decal');

      if (decal) {
        normalStyle.decal = createOrUpdatePatternFromDecal(decal, api);
      }

      var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape);
      extend(sectorShape, cornerRadius);
      each(SPECIAL_STATES, function (stateName) {
        var state = sector.ensureState(stateName);
        var itemStyleModel = itemModel.getModel([stateName, 'itemStyle']);
        state.style = itemStyleModel.getItemStyle();
        var cornerRadius = getSectorCornerRadius(itemStyleModel, sectorShape);

        if (cornerRadius) {
          state.shape = cornerRadius;
        }
      });

      if (firstCreate) {
        sector.setShape(sectorShape);
        sector.shape.r = layout.r0;
        updateProps(sector, {
          shape: {
            r: layout.r
          }
        }, seriesModel, node.dataIndex);
      } else {
        updateProps(sector, {
          shape: sectorShape
        }, seriesModel);
      }

      sector.useStyle(normalStyle);

      this._updateLabel(seriesModel);

      var cursorStyle = itemModel.getShallow('cursor');
      cursorStyle && sector.attr('cursor', cursorStyle);
      this._seriesModel = seriesModel || this._seriesModel;
      this._ecModel = ecModel || this._ecModel;
      var focus = emphasisModel.get('focus');
      var focusDataIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : null;
      enableHoverEmphasis(this, focusDataIndices || focus, emphasisModel.get('blurScope'));
    };

    SunburstPiece.prototype._updateLabel = function (seriesModel) {
      var _this = this;

      var itemModel = this.node.getModel();
      var normalLabelModel = itemModel.getModel('label');
      var layout = this.node.getLayout();
      var angle = layout.endAngle - layout.startAngle;
      var midAngle = (layout.startAngle + layout.endAngle) / 2;
      var dx = Math.cos(midAngle);
      var dy = Math.sin(midAngle);
      var sector = this;
      var label = sector.getTextContent();
      var dataIndex = this.node.dataIndex;
      var labelMinAngle = normalLabelModel.get('minAngle') / 180 * Math.PI;
      var isNormalShown = normalLabelModel.get('show') && !(labelMinAngle != null && Math.abs(angle) < labelMinAngle);
      label.ignore = !isNormalShown;
      each(DISPLAY_STATES, function (stateName) {
        var labelStateModel = stateName === 'normal' ? itemModel.getModel('label') : itemModel.getModel([stateName, 'label']);
        var isNormal = stateName === 'normal';
        var state = isNormal ? label : label.ensureState(stateName);
        var text = seriesModel.getFormattedLabel(dataIndex, stateName);

        if (isNormal) {
          text = text || _this.node.name;
        }

        state.style = createTextStyle(labelStateModel, {}, null, stateName !== 'normal', true);

        if (text) {
          state.style.text = text;
        }

        var isShown = labelStateModel.get('show');

        if (isShown != null && !isNormal) {
          state.ignore = !isShown;
        }

        var labelPosition = getLabelAttr(labelStateModel, 'position');
        var sectorState = isNormal ? sector : sector.states[stateName];
        var labelColor = sectorState.style.fill;
        sectorState.textConfig = {
          outsideFill: labelStateModel.get('color') === 'inherit' ? labelColor : null,
          inside: labelPosition !== 'outside'
        };
        var r;
        var labelPadding = getLabelAttr(labelStateModel, 'distance') || 0;
        var textAlign = getLabelAttr(labelStateModel, 'align');

        if (labelPosition === 'outside') {
          r = layout.r + labelPadding;
          textAlign = midAngle > Math.PI / 2 ? 'right' : 'left';
        } else {
          if (!textAlign || textAlign === 'center') {
            r = (layout.r + layout.r0) / 2;
            textAlign = 'center';
          } else if (textAlign === 'left') {
            r = layout.r0 + labelPadding;

            if (midAngle > Math.PI / 2) {
              textAlign = 'right';
            }
          } else if (textAlign === 'right') {
            r = layout.r - labelPadding;

            if (midAngle > Math.PI / 2) {
              textAlign = 'left';
            }
          }
        }

        state.style.align = textAlign;
        state.style.verticalAlign = getLabelAttr(labelStateModel, 'verticalAlign') || 'middle';
        state.x = r * dx + layout.cx;
        state.y = r * dy + layout.cy;
        var rotateType = getLabelAttr(labelStateModel, 'rotate');
        var rotate = 0;

        if (rotateType === 'radial') {
          rotate = -midAngle;

          if (rotate < -Math.PI / 2) {
            rotate += Math.PI;
          }
        } else if (rotateType === 'tangential') {
          rotate = Math.PI / 2 - midAngle;

          if (rotate > Math.PI / 2) {
            rotate -= Math.PI;
          } else if (rotate < -Math.PI / 2) {
            rotate += Math.PI;
          }
        } else if (typeof rotateType === 'number') {
          rotate = rotateType * Math.PI / 180;
        }

        state.rotation = rotate;
      });

      function getLabelAttr(model, name) {
        var stateAttr = model.get(name);

        if (stateAttr == null) {
          return normalLabelModel.get(name);
        }

        return stateAttr;
      }

      label.dirtyStyle();
    };

    return SunburstPiece;
  }(Sector);

  var ROOT_TO_NODE_ACTION = 'sunburstRootToNode';
  registerAction({
    type: ROOT_TO_NODE_ACTION,
    update: 'updateView'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'sunburst',
      query: payload
    }, handleRootToNode);

    function handleRootToNode(model, index) {
      var targetInfo = retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION], model);

      if (targetInfo) {
        var originViewRoot = model.getViewRoot();

        if (originViewRoot) {
          payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown';
        }

        model.resetViewRoot(targetInfo.node);
      }
    }
  });
  var HIGHLIGHT_ACTION = 'sunburstHighlight';
  registerAction({
    type: HIGHLIGHT_ACTION,
    update: 'none'
  }, function (payload, ecModel, api) {
    payload = extend({}, payload);
    ecModel.eachComponent({
      mainType: 'series',
      subType: 'sunburst',
      query: payload
    }, handleHighlight);

    function handleHighlight(model) {
      var targetInfo = retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model);

      if (targetInfo) {
        payload.dataIndex = targetInfo.node.dataIndex;
      }
    }

    if (true) {
      deprecateReplaceLog('highlight', 'sunburstHighlight');
    }

    api.dispatchAction(extend(payload, {
      type: 'highlight'
    }));
  });
  var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight';
  registerAction({
    type: UNHIGHLIGHT_ACTION,
    update: 'updateView'
  }, function (payload, ecModel, api) {
    payload = extend({}, payload);

    if (true) {
      deprecateReplaceLog('downplay', 'sunburstUnhighlight');
    }

    api.dispatchAction(extend(payload, {
      type: 'downplay'
    }));
  });

  var SunburstView = function (_super) {
    __extends(SunburstView, _super);

    function SunburstView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SunburstView.type;
      return _this;
    }

    SunburstView.prototype.render = function (seriesModel, ecModel, api, payload) {
      var self = this;
      this.seriesModel = seriesModel;
      this.api = api;
      this.ecModel = ecModel;
      var data = seriesModel.getData();
      var virtualRoot = data.tree.root;
      var newRoot = seriesModel.getViewRoot();
      var group = this.group;
      var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData');
      var newChildren = [];
      newRoot.eachNode(function (node) {
        newChildren.push(node);
      });
      var oldChildren = this._oldChildren || [];
      dualTravel(newChildren, oldChildren);
      renderRollUp(virtualRoot, newRoot);

      this._initEvents();

      this._oldChildren = newChildren;

      function dualTravel(newChildren, oldChildren) {
        if (newChildren.length === 0 && oldChildren.length === 0) {
          return;
        }

        new DataDiffer(oldChildren, newChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute();

        function getKey(node) {
          return node.getId();
        }

        function processNode(newIdx, oldIdx) {
          var newNode = newIdx == null ? null : newChildren[newIdx];
          var oldNode = oldIdx == null ? null : oldChildren[oldIdx];
          doRenderNode(newNode, oldNode);
        }
      }

      function doRenderNode(newNode, oldNode) {
        if (!renderLabelForZeroData && newNode && !newNode.getValue()) {
          newNode = null;
        }

        if (newNode !== virtualRoot && oldNode !== virtualRoot) {
          if (oldNode && oldNode.piece) {
            if (newNode) {
              oldNode.piece.updateData(false, newNode, seriesModel, ecModel, api);
              data.setItemGraphicEl(newNode.dataIndex, oldNode.piece);
            } else {
              removeNode(oldNode);
            }
          } else if (newNode) {
            var piece = new SunburstPiece(newNode, seriesModel, ecModel, api);
            group.add(piece);
            data.setItemGraphicEl(newNode.dataIndex, piece);
          }
        }
      }

      function removeNode(node) {
        if (!node) {
          return;
        }

        if (node.piece) {
          group.remove(node.piece);
          node.piece = null;
        }
      }

      function renderRollUp(virtualRoot, viewRoot) {
        if (viewRoot.depth > 0) {
          if (self.virtualPiece) {
            self.virtualPiece.updateData(false, virtualRoot, seriesModel, ecModel, api);
          } else {
            self.virtualPiece = new SunburstPiece(virtualRoot, seriesModel, ecModel, api);
            group.add(self.virtualPiece);
          }

          viewRoot.piece.off('click');
          self.virtualPiece.on('click', function (e) {
            self._rootToNode(viewRoot.parentNode);
          });
        } else if (self.virtualPiece) {
          group.remove(self.virtualPiece);
          self.virtualPiece = null;
        }
      }
    };

    SunburstView.prototype._initEvents = function () {
      var _this = this;

      this.group.off('click');
      this.group.on('click', function (e) {
        var targetFound = false;

        var viewRoot = _this.seriesModel.getViewRoot();

        viewRoot.eachNode(function (node) {
          if (!targetFound && node.piece && node.piece === e.target) {
            var nodeClick = node.getModel().get('nodeClick');

            if (nodeClick === 'rootToNode') {
              _this._rootToNode(node);
            } else if (nodeClick === 'link') {
              var itemModel = node.getModel();
              var link = itemModel.get('link');

              if (link) {
                var linkTarget = itemModel.get('target', true) || '_blank';
                windowOpen(link, linkTarget);
              }
            }

            targetFound = true;
          }
        });
      });
    };

    SunburstView.prototype._rootToNode = function (node) {
      if (node !== this.seriesModel.getViewRoot()) {
        this.api.dispatchAction({
          type: ROOT_TO_NODE_ACTION,
          from: this.uid,
          seriesId: this.seriesModel.id,
          targetNode: node
        });
      }
    };

    SunburstView.prototype.containPoint = function (point, seriesModel) {
      var treeRoot = seriesModel.getData();
      var itemLayout = treeRoot.getItemLayout(0);

      if (itemLayout) {
        var dx = point[0] - itemLayout.cx;
        var dy = point[1] - itemLayout.cy;
        var radius = Math.sqrt(dx * dx + dy * dy);
        return radius <= itemLayout.r && radius >= itemLayout.r0;
      }
    };

    SunburstView.type = 'sunburst';
    return SunburstView;
  }(ChartView);

  ChartView.registerClass(SunburstView);
  var RADIAN$2 = Math.PI / 180;

  function sunburstLayout(seriesType, ecModel, api) {
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
      var center = seriesModel.get('center');
      var radius = seriesModel.get('radius');

      if (!isArray(radius)) {
        radius = [0, radius];
      }

      if (!isArray(center)) {
        center = [center, center];
      }

      var width = api.getWidth();
      var height = api.getHeight();
      var size = Math.min(width, height);
      var cx = parsePercent$2(center[0], width);
      var cy = parsePercent$2(center[1], height);
      var r0 = parsePercent$2(radius[0], size / 2);
      var r = parsePercent$2(radius[1], size / 2);
      var startAngle = -seriesModel.get('startAngle') * RADIAN$2;
      var minAngle = seriesModel.get('minAngle') * RADIAN$2;
      var virtualRoot = seriesModel.getData().tree.root;
      var treeRoot = seriesModel.getViewRoot();
      var rootDepth = treeRoot.depth;
      var sort = seriesModel.get('sort');

      if (sort != null) {
        initChildren$1(treeRoot, sort);
      }

      var validDataCount = 0;
      each(treeRoot.children, function (child) {
        !isNaN(child.getValue()) && validDataCount++;
      });
      var sum = treeRoot.getValue();
      var unitRadian = Math.PI / (sum || validDataCount) * 2;
      var renderRollupNode = treeRoot.depth > 0;
      var levels = treeRoot.height - (renderRollupNode ? -1 : 1);
      var rPerLevel = (r - r0) / (levels || 1);
      var clockwise = seriesModel.get('clockwise');
      var stillShowZeroSum = seriesModel.get('stillShowZeroSum');
      var dir = clockwise ? 1 : -1;

      var renderNode = function (node, startAngle) {
        if (!node) {
          return;
        }

        var endAngle = startAngle;

        if (node !== virtualRoot) {
          var value = node.getValue();
          var angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian;

          if (angle < minAngle) {
            angle = minAngle;
          }

          endAngle = startAngle + dir * angle;
          var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1);
          var rStart = r0 + rPerLevel * depth;
          var rEnd = r0 + rPerLevel * (depth + 1);
          var itemModel = node.getModel();

          if (itemModel.get('r0') != null) {
            rStart = parsePercent$2(itemModel.get('r0'), size / 2);
          }

          if (itemModel.get('r') != null) {
            rEnd = parsePercent$2(itemModel.get('r'), size / 2);
          }

          node.setLayout({
            angle: angle,
            startAngle: startAngle,
            endAngle: endAngle,
            clockwise: clockwise,
            cx: cx,
            cy: cy,
            r0: rStart,
            r: rEnd
          });
        }

        if (node.children && node.children.length) {
          var siblingAngle_1 = 0;
          each(node.children, function (node) {
            siblingAngle_1 += renderNode(node, startAngle + siblingAngle_1);
          });
        }

        return endAngle - startAngle;
      };

      if (renderRollupNode) {
        var rStart = r0;
        var rEnd = r0 + rPerLevel;
        var angle = Math.PI * 2;
        virtualRoot.setLayout({
          angle: angle,
          startAngle: startAngle,
          endAngle: startAngle + angle,
          clockwise: clockwise,
          cx: cx,
          cy: cy,
          r0: rStart,
          r: rEnd
        });
      }

      renderNode(treeRoot, startAngle);
    });
  }

  function initChildren$1(node, sortOrder) {
    var children = node.children || [];
    node.children = sort$2(children, sortOrder);

    if (children.length) {
      each(node.children, function (child) {
        initChildren$1(child, sortOrder);
      });
    }
  }

  function sort$2(children, sortOrder) {
    if (typeof sortOrder === 'function') {
      var sortTargets = map(children, function (child, idx) {
        var value = child.getValue();
        return {
          params: {
            depth: child.depth,
            height: child.height,
            dataIndex: child.dataIndex,
            getValue: function () {
              return value;
            }
          },
          index: idx
        };
      });
      sortTargets.sort(function (a, b) {
        return sortOrder(a.params, b.params);
      });
      return map(sortTargets, function (target) {
        return children[target.index];
      });
    } else {
      var isAsc_1 = sortOrder === 'asc';
      return children.sort(function (a, b) {
        var diff = (a.getValue() - b.getValue()) * (isAsc_1 ? 1 : -1);
        return diff === 0 ? (a.dataIndex - b.dataIndex) * (isAsc_1 ? -1 : 1) : diff;
      });
    }
  }

  function sunburstVisual(ecModel) {
    var paletteScope = {};

    function pickColor(node, seriesModel, treeHeight) {
      var current = node;

      while (current && current.depth > 1) {
        current = current.parentNode;
      }

      var color = seriesModel.getColorFromPalette(current.name || current.dataIndex + '', paletteScope);

      if (node.depth > 1 && typeof color === 'string') {
        color = lift(color, (node.depth - 1) / (treeHeight - 1) * 0.5);
      }

      return color;
    }

    ecModel.eachSeriesByType('sunburst', function (seriesModel) {
      var data = seriesModel.getData();
      var tree = data.tree;
      tree.eachNode(function (node) {
        var model = node.getModel();
        var style = model.getModel('itemStyle').getItemStyle();

        if (!style.fill) {
          style.fill = pickColor(node, seriesModel, tree.root.height);
        }

        var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style');
        extend(existsStyle, style);
      });
    });
  }

  registerLayout(curry(sunburstLayout, 'sunburst'));
  registerProcessor(curry(dataFilter, 'sunburst'));
  registerVisual(sunburstVisual);

  function dataToCoordSize(dataSize, dataItem) {
    dataItem = dataItem || [0, 0];
    return map(['x', 'y'], function (dim, dimIdx) {
      var axis = this.getAxis(dim);
      var val = dataItem[dimIdx];
      var halfSize = dataSize[dimIdx] / 2;
      return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
    }, this);
  }

  function cartesianPrepareCustom(coordSys) {
    var rect = coordSys.master.getRect();
    return {
      coordSys: {
        type: 'cartesian2d',
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height
      },
      api: {
        coord: function (data) {
          return coordSys.dataToPoint(data);
        },
        size: bind(dataToCoordSize, coordSys)
      }
    };
  }

  function dataToCoordSize$1(dataSize, dataItem) {
    dataItem = dataItem || [0, 0];
    return map([0, 1], function (dimIdx) {
      var val = dataItem[dimIdx];
      var halfSize = dataSize[dimIdx] / 2;
      var p1 = [];
      var p2 = [];
      p1[dimIdx] = val - halfSize;
      p2[dimIdx] = val + halfSize;
      p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx];
      return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]);
    }, this);
  }

  function geoPrepareCustom(coordSys) {
    var rect = coordSys.getBoundingRect();
    return {
      coordSys: {
        type: 'geo',
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height,
        zoom: coordSys.getZoom()
      },
      api: {
        coord: function (data) {
          return coordSys.dataToPoint(data);
        },
        size: bind(dataToCoordSize$1, coordSys)
      }
    };
  }

  function dataToCoordSize$2(dataSize, dataItem) {
    var axis = this.getAxis();
    var val = dataItem instanceof Array ? dataItem[0] : dataItem;
    var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2;
    return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
  }

  function singlePrepareCustom(coordSys) {
    var rect = coordSys.getRect();
    return {
      coordSys: {
        type: 'singleAxis',
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height
      },
      api: {
        coord: function (val) {
          return coordSys.dataToPoint(val);
        },
        size: bind(dataToCoordSize$2, coordSys)
      }
    };
  }

  function dataToCoordSize$3(dataSize, dataItem) {
    dataItem = dataItem || [0, 0];
    return map(['Radius', 'Angle'], function (dim, dimIdx) {
      var getterName = 'get' + dim + 'Axis';
      var axis = this[getterName]();
      var val = dataItem[dimIdx];
      var halfSize = dataSize[dimIdx] / 2;
      var result = axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));

      if (dim === 'Angle') {
        result = result * Math.PI / 180;
      }

      return result;
    }, this);
  }

  function polarPrepareCustom(coordSys) {
    var radiusAxis = coordSys.getRadiusAxis();
    var angleAxis = coordSys.getAngleAxis();
    var radius = radiusAxis.getExtent();
    radius[0] > radius[1] && radius.reverse();
    return {
      coordSys: {
        type: 'polar',
        cx: coordSys.cx,
        cy: coordSys.cy,
        r: radius[1],
        r0: radius[0]
      },
      api: {
        coord: function (data) {
          var radius = radiusAxis.dataToRadius(data[0]);
          var angle = angleAxis.dataToAngle(data[1]);
          var coord = coordSys.coordToPoint([radius, angle]);
          coord.push(radius, angle * Math.PI / 180);
          return coord;
        },
        size: bind(dataToCoordSize$3, coordSys)
      }
    };
  }

  function calendarPrepareCustom(coordSys) {
    var rect = coordSys.getRect();
    var rangeInfo = coordSys.getRangeInfo();
    return {
      coordSys: {
        type: 'calendar',
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height,
        cellWidth: coordSys.getCellWidth(),
        cellHeight: coordSys.getCellHeight(),
        rangeInfo: {
          start: rangeInfo.start,
          end: rangeInfo.end,
          weeks: rangeInfo.weeks,
          dayCount: rangeInfo.allDay
        }
      },
      api: {
        coord: function (data, clamp) {
          return coordSys.dataToPoint(data, clamp);
        }
      }
    };
  }

  var deprecatedLogs = {};

  function isEC4CompatibleStyle(style, elType, hasOwnTextContentOption, hasOwnTextConfig) {
    return style && (style.legacy || style.legacy !== false && !hasOwnTextContentOption && !hasOwnTextConfig && elType !== 'tspan' && (elType === 'text' || hasOwn(style, 'text')));
  }

  function convertFromEC4CompatibleStyle(hostStyle, elType, isNormal) {
    var srcStyle = hostStyle;
    var textConfig;
    var textContent;
    var textContentStyle;

    if (elType === 'text') {
      textContentStyle = srcStyle;
    } else {
      textContentStyle = {};
      hasOwn(srcStyle, 'text') && (textContentStyle.text = srcStyle.text);
      hasOwn(srcStyle, 'rich') && (textContentStyle.rich = srcStyle.rich);
      hasOwn(srcStyle, 'textFill') && (textContentStyle.fill = srcStyle.textFill);
      hasOwn(srcStyle, 'textStroke') && (textContentStyle.stroke = srcStyle.textStroke);
      textContent = {
        type: 'text',
        style: textContentStyle,
        silent: true
      };
      textConfig = {};
      var hasOwnPos = hasOwn(srcStyle, 'textPosition');

      if (isNormal) {
        textConfig.position = hasOwnPos ? srcStyle.textPosition : 'inside';
      } else {
        hasOwnPos && (textConfig.position = srcStyle.textPosition);
      }

      hasOwn(srcStyle, 'textPosition') && (textConfig.position = srcStyle.textPosition);
      hasOwn(srcStyle, 'textOffset') && (textConfig.offset = srcStyle.textOffset);
      hasOwn(srcStyle, 'textRotation') && (textConfig.rotation = srcStyle.textRotation);
      hasOwn(srcStyle, 'textDistance') && (textConfig.distance = srcStyle.textDistance);
    }

    convertEC4CompatibleRichItem(textContentStyle, hostStyle);
    each(textContentStyle.rich, function (richItem) {
      convertEC4CompatibleRichItem(richItem, richItem);
    });
    return {
      textConfig: textConfig,
      textContent: textContent
    };
  }

  function convertEC4CompatibleRichItem(out, richItem) {
    if (!richItem) {
      return;
    }

    richItem.font = richItem.textFont || richItem.font;
    hasOwn(richItem, 'textStrokeWidth') && (out.lineWidth = richItem.textStrokeWidth);
    hasOwn(richItem, 'textAlign') && (out.align = richItem.textAlign);
    hasOwn(richItem, 'textVerticalAlign') && (out.verticalAlign = richItem.textVerticalAlign);
    hasOwn(richItem, 'textLineHeight') && (out.lineHeight = richItem.textLineHeight);
    hasOwn(richItem, 'textWidth') && (out.width = richItem.textWidth);
    hasOwn(richItem, 'textHeight') && (out.height = richItem.textHeight);
    hasOwn(richItem, 'textBackgroundColor') && (out.backgroundColor = richItem.textBackgroundColor);
    hasOwn(richItem, 'textPadding') && (out.padding = richItem.textPadding);
    hasOwn(richItem, 'textBorderColor') && (out.borderColor = richItem.textBorderColor);
    hasOwn(richItem, 'textBorderWidth') && (out.borderWidth = richItem.textBorderWidth);
    hasOwn(richItem, 'textBorderRadius') && (out.borderRadius = richItem.textBorderRadius);
    hasOwn(richItem, 'textBoxShadowColor') && (out.shadowColor = richItem.textBoxShadowColor);
    hasOwn(richItem, 'textBoxShadowBlur') && (out.shadowBlur = richItem.textBoxShadowBlur);
    hasOwn(richItem, 'textBoxShadowOffsetX') && (out.shadowOffsetX = richItem.textBoxShadowOffsetX);
    hasOwn(richItem, 'textBoxShadowOffsetY') && (out.shadowOffsetY = richItem.textBoxShadowOffsetY);
  }

  function convertToEC4StyleForCustomSerise(itemStl, txStl, txCfg) {
    var out = itemStl;
    out.textPosition = out.textPosition || txCfg.position || 'inside';
    txCfg.offset != null && (out.textOffset = txCfg.offset);
    txCfg.rotation != null && (out.textRotation = txCfg.rotation);
    txCfg.distance != null && (out.textDistance = txCfg.distance);
    var isInside = out.textPosition.indexOf('inside') >= 0;
    var hostFill = itemStl.fill || '#000';
    convertToEC4RichItem(out, txStl);
    var textFillNotSet = out.textFill == null;

    if (isInside) {
      if (textFillNotSet) {
        out.textFill = txCfg.insideFill || '#fff';
        !out.textStroke && txCfg.insideStroke && (out.textStroke = txCfg.insideStroke);
        !out.textStroke && (out.textStroke = hostFill);
        out.textStrokeWidth == null && (out.textStrokeWidth = 2);
      }
    } else {
      if (textFillNotSet) {
        out.textFill = txCfg.outsideFill || hostFill;
      }

      !out.textStroke && txCfg.outsideStroke && (out.textStroke = txCfg.outsideStroke);
    }

    out.text = txStl.text;
    out.rich = txStl.rich;
    each(txStl.rich, function (richItem) {
      convertToEC4RichItem(richItem, richItem);
    });
    return out;
  }

  function convertToEC4RichItem(out, richItem) {
    if (!richItem) {
      return;
    }

    hasOwn(richItem, 'fill') && (out.textFill = richItem.fill);
    hasOwn(richItem, 'stroke') && (out.textStroke = richItem.fill);
    hasOwn(richItem, 'lineWidth') && (out.textStrokeWidth = richItem.lineWidth);
    hasOwn(richItem, 'font') && (out.font = richItem.font);
    hasOwn(richItem, 'fontStyle') && (out.fontStyle = richItem.fontStyle);
    hasOwn(richItem, 'fontWeight') && (out.fontWeight = richItem.fontWeight);
    hasOwn(richItem, 'fontSize') && (out.fontSize = richItem.fontSize);
    hasOwn(richItem, 'fontFamily') && (out.fontFamily = richItem.fontFamily);
    hasOwn(richItem, 'align') && (out.textAlign = richItem.align);
    hasOwn(richItem, 'verticalAlign') && (out.textVerticalAlign = richItem.verticalAlign);
    hasOwn(richItem, 'lineHeight') && (out.textLineHeight = richItem.lineHeight);
    hasOwn(richItem, 'width') && (out.textWidth = richItem.width);
    hasOwn(richItem, 'height') && (out.textHeight = richItem.height);
    hasOwn(richItem, 'backgroundColor') && (out.textBackgroundColor = richItem.backgroundColor);
    hasOwn(richItem, 'padding') && (out.textPadding = richItem.padding);
    hasOwn(richItem, 'borderColor') && (out.textBorderColor = richItem.borderColor);
    hasOwn(richItem, 'borderWidth') && (out.textBorderWidth = richItem.borderWidth);
    hasOwn(richItem, 'borderRadius') && (out.textBorderRadius = richItem.borderRadius);
    hasOwn(richItem, 'shadowColor') && (out.textBoxShadowColor = richItem.shadowColor);
    hasOwn(richItem, 'shadowBlur') && (out.textBoxShadowBlur = richItem.shadowBlur);
    hasOwn(richItem, 'shadowOffsetX') && (out.textBoxShadowOffsetX = richItem.shadowOffsetX);
    hasOwn(richItem, 'shadowOffsetY') && (out.textBoxShadowOffsetY = richItem.shadowOffsetY);
    hasOwn(richItem, 'textShadowColor') && (out.textShadowColor = richItem.textShadowColor);
    hasOwn(richItem, 'textShadowBlur') && (out.textShadowBlur = richItem.textShadowBlur);
    hasOwn(richItem, 'textShadowOffsetX') && (out.textShadowOffsetX = richItem.textShadowOffsetX);
    hasOwn(richItem, 'textShadowOffsetY') && (out.textShadowOffsetY = richItem.textShadowOffsetY);
  }

  function warnDeprecated(deprecated, insteadApproach) {
    if (true) {
      var key = deprecated + '^_^' + insteadApproach;

      if (!deprecatedLogs[key]) {
        console.warn("[ECharts] DEPRECATED: \"" + deprecated + "\" has been deprecated. " + insteadApproach);
        deprecatedLogs[key] = true;
      }
    }
  }

  var inner$e = makeInner();
  var TRANSFORM_PROPS = {
    x: 1,
    y: 1,
    scaleX: 1,
    scaleY: 1,
    originX: 1,
    originY: 1,
    rotation: 1
  };
  var transformPropNamesStr = keys(TRANSFORM_PROPS).join(', ');
  var STYLE_VISUAL_TYPE = {
    color: 'fill',
    borderColor: 'stroke'
  };
  var NON_STYLE_VISUAL_PROPS = {
    symbol: 1,
    symbolSize: 1,
    symbolKeepAspect: 1,
    legendSymbol: 1,
    visualMeta: 1,
    liftZ: 1,
    decal: 1
  };
  var EMPHASIS = 'emphasis';
  var NORMAL = 'normal';
  var BLUR = 'blur';
  var SELECT = 'select';
  var STATES = [NORMAL, EMPHASIS, BLUR, SELECT];
  var PATH_ITEM_STYLE = {
    normal: ['itemStyle'],
    emphasis: [EMPHASIS, 'itemStyle'],
    blur: [BLUR, 'itemStyle'],
    select: [SELECT, 'itemStyle']
  };
  var PATH_LABEL = {
    normal: ['label'],
    emphasis: [EMPHASIS, 'label'],
    blur: [BLUR, 'label'],
    select: [SELECT, 'label']
  };
  var GROUP_DIFF_PREFIX = 'e\0\0';
  var attachedTxInfoTmp = {
    normal: {},
    emphasis: {},
    blur: {},
    select: {}
  };
  var LEGACY_TRANSFORM_PROPS = {
    position: ['x', 'y'],
    scale: ['scaleX', 'scaleY'],
    origin: ['originX', 'originY']
  };
  var tmpTransformable = new Transformable();
  var prepareCustoms = {
    cartesian2d: cartesianPrepareCustom,
    geo: geoPrepareCustom,
    singleAxis: singlePrepareCustom,
    polar: polarPrepareCustom,
    calendar: calendarPrepareCustom
  };

  var CustomSeriesModel = function (_super) {
    __extends(CustomSeriesModel, _super);

    function CustomSeriesModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CustomSeriesModel.type;
      return _this;
    }

    CustomSeriesModel.prototype.optionUpdated = function () {
      this.currentZLevel = this.get('zlevel', true);
      this.currentZ = this.get('z', true);
    };

    CustomSeriesModel.prototype.getInitialData = function (option, ecModel) {
      return createListFromArray(this.getSource(), this);
    };

    CustomSeriesModel.prototype.getDataParams = function (dataIndex, dataType, el) {
      var params = _super.prototype.getDataParams.call(this, dataIndex, dataType);

      el && (params.info = inner$e(el).info);
      return params;
    };

    CustomSeriesModel.type = 'series.custom';
    CustomSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar'];
    CustomSeriesModel.defaultOption = {
      coordinateSystem: 'cartesian2d',
      zlevel: 0,
      z: 2,
      legendHoverLink: true,
      clip: false
    };
    return CustomSeriesModel;
  }(SeriesModel);

  ComponentModel.registerClass(CustomSeriesModel);

  var CustomSeriesView = function (_super) {
    __extends(CustomSeriesView, _super);

    function CustomSeriesView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CustomSeriesView.type;
      return _this;
    }

    CustomSeriesView.prototype.render = function (customSeries, ecModel, api, payload) {
      var oldData = this._data;
      var data = customSeries.getData();
      var group = this.group;
      var renderItem = makeRenderItem(customSeries, data, ecModel, api);
      var transOpt = customSeries.__transientTransitionOpt;

      if (transOpt && (transOpt.from == null || transOpt.to == null)) {
        oldData && oldData.each(function (oldIdx) {
          doRemoveEl(oldData.getItemGraphicEl(oldIdx), customSeries, group);
        });
        data.each(function (newIdx) {
          createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, null);
        });
      } else {
        var morphPreparation_1 = new MorphPreparation(customSeries, transOpt);
        var diffMode = transOpt ? 'multiple' : 'oneToOne';
        new DataDiffer(oldData ? oldData.getIndices() : [], data.getIndices(), createGetKey(oldData, diffMode, transOpt && transOpt.from), createGetKey(data, diffMode, transOpt && transOpt.to), null, diffMode).add(function (newIdx) {
          createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, null);
        }).remove(function (oldIdx) {
          doRemoveEl(oldData.getItemGraphicEl(oldIdx), customSeries, group);
        }).update(function (newIdx, oldIdx) {
          morphPreparation_1.reset('oneToOne');
          var oldEl = oldData.getItemGraphicEl(oldIdx);
          morphPreparation_1.findAndAddFrom(oldEl);

          if (morphPreparation_1.hasFrom()) {
            removeElementDirectly(oldEl, group);
            oldEl = null;
          }

          createOrUpdateItem(api, oldEl, newIdx, renderItem(newIdx, payload), customSeries, group, data, morphPreparation_1);
          morphPreparation_1.applyMorphing();
        }).updateManyToOne(function (newIdx, oldIndices) {
          morphPreparation_1.reset('manyToOne');

          for (var i = 0; i < oldIndices.length; i++) {
            var oldEl = oldData.getItemGraphicEl(oldIndices[i]);
            morphPreparation_1.findAndAddFrom(oldEl);
            removeElementDirectly(oldEl, group);
          }

          createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, morphPreparation_1);
          morphPreparation_1.applyMorphing();
        }).updateOneToMany(function (newIndices, oldIdx) {
          morphPreparation_1.reset('oneToMany');
          var newLen = newIndices.length;
          var oldEl = oldData.getItemGraphicEl(oldIdx);
          morphPreparation_1.findAndAddFrom(oldEl);
          removeElementDirectly(oldEl, group);

          for (var i = 0; i < newLen; i++) {
            createOrUpdateItem(api, null, newIndices[i], renderItem(newIndices[i], payload), customSeries, group, data, morphPreparation_1);
          }

          morphPreparation_1.applyMorphing();
        }).execute();
      }

      var clipPath = customSeries.get('clip', true) ? createClipPath(customSeries.coordinateSystem, false, customSeries) : null;

      if (clipPath) {
        group.setClipPath(clipPath);
      } else {
        group.removeClipPath();
      }

      this._data = data;
    };

    CustomSeriesView.prototype.incrementalPrepareRender = function (customSeries, ecModel, api) {
      this.group.removeAll();
      this._data = null;
    };

    CustomSeriesView.prototype.incrementalRender = function (params, customSeries, ecModel, api, payload) {
      var data = customSeries.getData();
      var renderItem = makeRenderItem(customSeries, data, ecModel, api);

      function setIncrementalAndHoverLayer(el) {
        if (!el.isGroup) {
          el.incremental = true;
          el.ensureState('emphasis').hoverLayer = true;
        }
      }

      for (var idx = params.start; idx < params.end; idx++) {
        var el = createOrUpdateItem(null, null, idx, renderItem(idx, payload), customSeries, this.group, data, null);
        el.traverse(setIncrementalAndHoverLayer);
      }
    };

    CustomSeriesView.prototype.filterForExposedEvent = function (eventType, query, targetEl, packedEvent) {
      var elementName = query.element;

      if (elementName == null || targetEl.name === elementName) {
        return true;
      }

      while ((targetEl = targetEl.__hostTarget || targetEl.parent) && targetEl !== this.group) {
        if (targetEl.name === elementName) {
          return true;
        }
      }

      return false;
    };

    CustomSeriesView.type = 'custom';
    return CustomSeriesView;
  }(ChartView);

  ChartView.registerClass(CustomSeriesView);

  function createGetKey(data, diffMode, dimension) {
    if (!data) {
      return;
    }

    if (diffMode === 'oneToOne') {
      return function (rawIdx, dataIndex) {
        return data.getId(dataIndex);
      };
    }

    var diffByDimName = data.getDimension(dimension);
    var dimInfo = data.getDimensionInfo(diffByDimName);

    if (!dimInfo) {
      var errMsg = '';

      if (true) {
        errMsg = dimension + " is not a valid dimension.";
      }

      throwError(errMsg);
    }

    var ordinalMeta = dimInfo.ordinalMeta;
    return function (rawIdx, dataIndex) {
      var key = data.get(diffByDimName, dataIndex);

      if (ordinalMeta) {
        key = ordinalMeta.categories[key];
      }

      return key == null || eqNaN(key) ? rawIdx + '' : '_ec_' + key;
    };
  }

  function createEl(elOption) {
    var graphicType = elOption.type;
    var el;

    if (graphicType === 'path') {
      var shape = elOption.shape;
      var pathRect = shape.width != null && shape.height != null ? {
        x: shape.x || 0,
        y: shape.y || 0,
        width: shape.width,
        height: shape.height
      } : null;
      var pathData = getPathData(shape);
      el = makePath(pathData, null, pathRect, shape.layout || 'center');
      inner$e(el).customPathData = pathData;
    } else if (graphicType === 'image') {
      el = new ZRImage({});
      inner$e(el).customImagePath = elOption.style.image;
    } else if (graphicType === 'text') {
      el = new ZRText({});
    } else if (graphicType === 'group') {
      el = new Group();
    } else if (graphicType === 'compoundPath') {
      throw new Error('"compoundPath" is not supported yet.');
    } else {
      var Clz = getShapeClass(graphicType);

      if (!Clz) {
        var errMsg = '';

        if (true) {
          errMsg = 'graphic type "' + graphicType + '" can not be found.';
        }

        throwError(errMsg);
      }

      el = new Clz();
    }

    inner$e(el).customGraphicType = graphicType;
    el.name = elOption.name;
    el.z2EmphasisLift = 1;
    el.z2SelectLift = 1;
    return el;
  }

  function updateElNormal(api, el, isMorphTo, dataIndex, elOption, styleOpt, attachedTxInfo, seriesModel, isInit, isTextContent) {
    var transFromProps = {};
    var allPropsFinal = {};
    var elDisplayable = el.isGroup ? null : el;
    !isMorphTo && prepareShapeOrExtraTransitionFrom('shape', el, null, elOption, transFromProps, isInit);
    prepareShapeOrExtraAllPropsFinal('shape', elOption, allPropsFinal);
    !isMorphTo && prepareShapeOrExtraTransitionFrom('extra', el, null, elOption, transFromProps, isInit);
    prepareShapeOrExtraAllPropsFinal('extra', elOption, allPropsFinal);
    !isMorphTo && prepareTransformTransitionFrom(el, null, elOption, transFromProps, isInit);
    prepareTransformAllPropsFinal(elOption, allPropsFinal);
    var txCfgOpt = attachedTxInfo && attachedTxInfo.normal.cfg;

    if (txCfgOpt) {
      el.setTextConfig(txCfgOpt);
    }

    if (el.type === 'text' && styleOpt) {
      var textOptionStyle = styleOpt;
      hasOwn(textOptionStyle, 'textFill') && (textOptionStyle.fill = textOptionStyle.textFill);
      hasOwn(textOptionStyle, 'textStroke') && (textOptionStyle.stroke = textOptionStyle.textStroke);
    }

    if (styleOpt) {
      var decalPattern = void 0;
      var decalObj = isPath$1(el) ? styleOpt.decal : null;

      if (api && decalObj) {
        decalObj.dirty = true;
        decalPattern = createOrUpdatePatternFromDecal(decalObj, api);
      }

      styleOpt.__decalPattern = decalPattern;
    }

    !isMorphTo && prepareStyleTransitionFrom(el, null, elOption, styleOpt, transFromProps, isInit);

    if (elDisplayable) {
      hasOwn(elOption, 'invisible') && (elDisplayable.invisible = elOption.invisible);
    }

    if (!isMorphTo) {
      applyPropsFinal(el, allPropsFinal, styleOpt);
      applyTransitionFrom(el, dataIndex, elOption, seriesModel, transFromProps, isInit);
    }

    hasOwn(elOption, 'silent') && (el.silent = elOption.silent);
    hasOwn(elOption, 'ignore') && (el.ignore = elOption.ignore);

    if (!isTextContent) {
      hasOwn(elOption, 'info') && (inner$e(el).info = elOption.info);
    }

    styleOpt ? el.dirty() : el.markRedraw();
    return isMorphTo ? allPropsFinal : null;
  }

  function applyPropsFinal(el, allPropsFinal, styleOpt) {
    var elDisplayable = el.isGroup ? null : el;

    if (elDisplayable && styleOpt) {
      var decalPattern = styleOpt.__decalPattern;
      var originalDecalObj = void 0;

      if (decalPattern) {
        originalDecalObj = styleOpt.decal;
        styleOpt.decal = decalPattern;
      }

      elDisplayable.useStyle(styleOpt);

      if (decalPattern) {
        styleOpt.decal = originalDecalObj;
      }

      var animators = elDisplayable.animators;

      for (var i = 0; i < animators.length; i++) {
        var animator = animators[i];

        if (animator.targetName === 'style') {
          animator.changeTarget(elDisplayable.style);
        }
      }
    }

    allPropsFinal && el.attr(allPropsFinal);
  }

  function applyTransitionFrom(el, dataIndex, elOption, seriesModel, transFromProps, isInit) {
    if (transFromProps) {
      var userDuring = elOption.during;
      inner$e(el).userDuring = userDuring;
      var cfgDuringCall = userDuring ? bind(duringCall, {
        el: el,
        userDuring: userDuring
      }) : null;
      var cfg = {
        dataIndex: dataIndex,
        isFrom: true,
        during: cfgDuringCall
      };
      isInit ? initProps(el, transFromProps, seriesModel, cfg) : updateProps(el, transFromProps, seriesModel, cfg);
    }
  }

  function prepareShapeOrExtraTransitionFrom(mainAttr, el, morphFromEl, elOption, transFromProps, isInit) {
    var attrOpt = elOption[mainAttr];

    if (!attrOpt) {
      return;
    }

    var elPropsInAttr = el[mainAttr];
    var transFromPropsInAttr;
    var enterFrom = attrOpt.enterFrom;

    if (isInit && enterFrom) {
      !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {});
      var enterFromKeys = keys(enterFrom);

      for (var i = 0; i < enterFromKeys.length; i++) {
        var key = enterFromKeys[i];
        transFromPropsInAttr[key] = enterFrom[key];
      }
    }

    if (!isInit && elPropsInAttr && !(morphFromEl != null && mainAttr === 'shape')) {
      if (attrOpt.transition) {
        !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {});
        var transitionKeys = normalizeToArray(attrOpt.transition);

        for (var i = 0; i < transitionKeys.length; i++) {
          var key = transitionKeys[i];
          var elVal = elPropsInAttr[key];

          if (true) {
            checkNonStyleTansitionRefer(key, attrOpt[key], elVal);
          }

          transFromPropsInAttr[key] = elVal;
        }
      } else if (indexOf(elOption.transition, mainAttr) >= 0) {
        !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {});
        var elPropsInAttrKeys = keys(elPropsInAttr);

        for (var i = 0; i < elPropsInAttrKeys.length; i++) {
          var key = elPropsInAttrKeys[i];
          var elVal = elPropsInAttr[key];

          if (isNonStyleTransitionEnabled(attrOpt[key], elVal)) {
            transFromPropsInAttr[key] = elVal;
          }
        }
      }
    }

    var leaveTo = attrOpt.leaveTo;

    if (leaveTo) {
      var leaveToProps = getOrCreateLeaveToPropsFromEl(el);
      var leaveToPropsInAttr = leaveToProps[mainAttr] || (leaveToProps[mainAttr] = {});
      var leaveToKeys = keys(leaveTo);

      for (var i = 0; i < leaveToKeys.length; i++) {
        var key = leaveToKeys[i];
        leaveToPropsInAttr[key] = leaveTo[key];
      }
    }
  }

  function prepareShapeOrExtraAllPropsFinal(mainAttr, elOption, allProps) {
    var attrOpt = elOption[mainAttr];

    if (!attrOpt) {
      return;
    }

    var allPropsInAttr = allProps[mainAttr] = {};
    var keysInAttr = keys(attrOpt);

    for (var i = 0; i < keysInAttr.length; i++) {
      var key = keysInAttr[i];
      allPropsInAttr[key] = cloneValue(attrOpt[key]);
    }
  }

  function prepareTransformTransitionFrom(el, morphFromEl, elOption, transFromProps, isInit) {
    var enterFrom = elOption.enterFrom;

    if (isInit && enterFrom) {
      var enterFromKeys = keys(enterFrom);

      for (var i = 0; i < enterFromKeys.length; i++) {
        var key = enterFromKeys[i];

        if (true) {
          checkTransformPropRefer(key, 'el.enterFrom');
        }

        transFromProps[key] = enterFrom[key];
      }
    }

    if (!isInit) {
      if (morphFromEl) {
        var fromTransformable = calcOldElLocalTransformBasedOnNewElParent(morphFromEl, el);
        setTransformPropToTransitionFrom(transFromProps, 'x', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'y', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'scaleX', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'scaleY', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'originX', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'originY', fromTransformable);
        setTransformPropToTransitionFrom(transFromProps, 'rotation', fromTransformable);
      } else if (elOption.transition) {
        var transitionKeys = normalizeToArray(elOption.transition);

        for (var i = 0; i < transitionKeys.length; i++) {
          var key = transitionKeys[i];

          if (key === 'style' || key === 'shape' || key === 'extra') {
            continue;
          }

          var elVal = el[key];

          if (true) {
            checkTransformPropRefer(key, 'el.transition');
            checkNonStyleTansitionRefer(key, elOption[key], elVal);
          }

          transFromProps[key] = elVal;
        }
      } else {
        setTransformPropToTransitionFrom(transFromProps, 'x', el);
        setTransformPropToTransitionFrom(transFromProps, 'y', el);
      }
    }

    var leaveTo = elOption.leaveTo;

    if (leaveTo) {
      var leaveToProps = getOrCreateLeaveToPropsFromEl(el);
      var leaveToKeys = keys(leaveTo);

      for (var i = 0; i < leaveToKeys.length; i++) {
        var key = leaveToKeys[i];

        if (true) {
          checkTransformPropRefer(key, 'el.leaveTo');
        }

        leaveToProps[key] = leaveTo[key];
      }
    }
  }

  function prepareTransformAllPropsFinal(elOption, allProps) {
    setLagecyTransformProp(elOption, allProps, 'position');
    setLagecyTransformProp(elOption, allProps, 'scale');
    setLagecyTransformProp(elOption, allProps, 'origin');
    setTransformProp(elOption, allProps, 'x');
    setTransformProp(elOption, allProps, 'y');
    setTransformProp(elOption, allProps, 'scaleX');
    setTransformProp(elOption, allProps, 'scaleY');
    setTransformProp(elOption, allProps, 'originX');
    setTransformProp(elOption, allProps, 'originY');
    setTransformProp(elOption, allProps, 'rotation');
  }

  function prepareStyleTransitionFrom(el, morphFromEl, elOption, styleOpt, transFromProps, isInit) {
    if (!styleOpt) {
      return;
    }

    var fromEl = morphFromEl || el;
    var fromElStyle = fromEl.style;
    var transFromStyleProps;
    var enterFrom = styleOpt.enterFrom;

    if (isInit && enterFrom) {
      var enterFromKeys = keys(enterFrom);
      !transFromStyleProps && (transFromStyleProps = transFromProps.style = {});

      for (var i = 0; i < enterFromKeys.length; i++) {
        var key = enterFromKeys[i];
        transFromStyleProps[key] = enterFrom[key];
      }
    }

    if (!isInit && fromElStyle) {
      if (styleOpt.transition) {
        var transitionKeys = normalizeToArray(styleOpt.transition);
        !transFromStyleProps && (transFromStyleProps = transFromProps.style = {});

        for (var i = 0; i < transitionKeys.length; i++) {
          var key = transitionKeys[i];
          var elVal = fromElStyle[key];
          transFromStyleProps[key] = elVal;
        }
      } else if (el.getAnimationStyleProps && indexOf(elOption.transition, 'style') >= 0) {
        var animationProps = el.getAnimationStyleProps();
        var animationStyleProps = animationProps ? animationProps.style : null;

        if (animationStyleProps) {
          !transFromStyleProps && (transFromStyleProps = transFromProps.style = {});
          var styleKeys = keys(styleOpt);

          for (var i = 0; i < styleKeys.length; i++) {
            var key = styleKeys[i];

            if (animationStyleProps[key]) {
              var elVal = fromElStyle[key];
              transFromStyleProps[key] = elVal;
            }
          }
        }
      }
    }

    var leaveTo = styleOpt.leaveTo;

    if (leaveTo) {
      var leaveToKeys = keys(leaveTo);
      var leaveToProps = getOrCreateLeaveToPropsFromEl(el);
      var leaveToStyleProps = leaveToProps.style || (leaveToProps.style = {});

      for (var i = 0; i < leaveToKeys.length; i++) {
        var key = leaveToKeys[i];
        leaveToStyleProps[key] = leaveTo[key];
      }
    }
  }

  function calcOldElLocalTransformBasedOnNewElParent(oldEl, newEl) {
    if (!oldEl || oldEl === newEl || oldEl.parent === newEl.parent) {
      return oldEl;
    }

    var tmpM = tmpTransformable.transform || (tmpTransformable.transform = identity([]));
    var oldGlobalTransform = oldEl.getComputedTransform();
    oldGlobalTransform ? copy$1(tmpM, oldGlobalTransform) : identity(tmpM);
    var newParent = newEl.parent;

    if (newParent) {
      newParent.getComputedTransform();
    }

    tmpTransformable.originX = oldEl.originX;
    tmpTransformable.originY = oldEl.originY;
    tmpTransformable.parent = newParent;
    tmpTransformable.decomposeTransform();
    return tmpTransformable;
  }

  var checkNonStyleTansitionRefer;

  if (true) {
    checkNonStyleTansitionRefer = function (propName, optVal, elVal) {
      if (!isArrayLike(optVal)) {
        assert(optVal != null && isFinite(optVal), 'Prop `' + propName + '` must refer to a finite number or ArrayLike for transition.');
      } else {
        assert(optVal !== elVal, 'Prop `' + propName + '` must use different Array object each time for transition.');
      }
    };
  }

  function isNonStyleTransitionEnabled(optVal, elVal) {
    return !isArrayLike(optVal) ? optVal != null && isFinite(optVal) : optVal !== elVal;
  }

  var checkTransformPropRefer;

  if (true) {
    checkTransformPropRefer = function (key, usedIn) {
      assert(hasOwn(TRANSFORM_PROPS, key), 'Prop `' + key + '` is not a permitted in `' + usedIn + '`. ' + 'Only `' + keys(TRANSFORM_PROPS).join('`, `') + '` are permitted.');
    };
  }

  function getOrCreateLeaveToPropsFromEl(el) {
    var innerEl = inner$e(el);
    return innerEl.leaveToProps || (innerEl.leaveToProps = {});
  }

  var tmpDuringScope = {};
  var customDuringAPI = {
    setTransform: function (key, val) {
      if (true) {
        assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `setTransform`.');
      }

      tmpDuringScope.el[key] = val;
      return this;
    },
    getTransform: function (key) {
      if (true) {
        assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.');
      }

      return tmpDuringScope.el[key];
    },
    setShape: function (key, val) {
      if (true) {
        assertNotReserved(key);
      }

      var shape = tmpDuringScope.el.shape || (tmpDuringScope.el.shape = {});
      shape[key] = val;
      tmpDuringScope.isShapeDirty = true;
      return this;
    },
    getShape: function (key) {
      if (true) {
        assertNotReserved(key);
      }

      var shape = tmpDuringScope.el.shape;

      if (shape) {
        return shape[key];
      }
    },
    setStyle: function (key, val) {
      if (true) {
        assertNotReserved(key);
      }

      var style = tmpDuringScope.el.style;

      if (style) {
        if (true) {
          if (eqNaN(val)) {
            warn('style.' + key + ' must not be assigned with NaN.');
          }
        }

        style[key] = val;
        tmpDuringScope.isStyleDirty = true;
      }

      return this;
    },
    getStyle: function (key) {
      if (true) {
        assertNotReserved(key);
      }

      var style = tmpDuringScope.el.style;

      if (style) {
        return style[key];
      }
    },
    setExtra: function (key, val) {
      if (true) {
        assertNotReserved(key);
      }

      var extra = tmpDuringScope.el.extra || (tmpDuringScope.el.extra = {});
      extra[key] = val;
      return this;
    },
    getExtra: function (key) {
      if (true) {
        assertNotReserved(key);
      }

      var extra = tmpDuringScope.el.extra;

      if (extra) {
        return extra[key];
      }
    }
  };

  function assertNotReserved(key) {
    if (true) {
      if (key === 'transition' || key === 'enterFrom' || key === 'leaveTo') {
        throw new Error('key must not be "' + key + '"');
      }
    }
  }

  function duringCall() {
    var scope = this;
    var el = scope.el;

    if (!el) {
      return;
    }

    var newstUserDuring = inner$e(el).userDuring;
    var scopeUserDuring = scope.userDuring;

    if (newstUserDuring !== scopeUserDuring) {
      scope.el = scope.userDuring = null;
      return;
    }

    tmpDuringScope.el = el;
    tmpDuringScope.isShapeDirty = false;
    tmpDuringScope.isStyleDirty = false;
    scopeUserDuring(customDuringAPI);

    if (tmpDuringScope.isShapeDirty && el.dirtyShape) {
      el.dirtyShape();
    }

    if (tmpDuringScope.isStyleDirty && el.dirtyStyle) {
      el.dirtyStyle();
    }
  }

  function updateElOnState(state, el, elStateOpt, styleOpt, attachedTxInfo, isRoot, isTextContent) {
    var elDisplayable = el.isGroup ? null : el;
    var txCfgOpt = attachedTxInfo && attachedTxInfo[state].cfg;

    if (elDisplayable) {
      var stateObj = elDisplayable.ensureState(state);

      if (styleOpt === false) {
        var existingEmphasisState = elDisplayable.getState(state);

        if (existingEmphasisState) {
          existingEmphasisState.style = null;
        }
      } else {
        stateObj.style = styleOpt || null;
      }

      if (txCfgOpt) {
        stateObj.textConfig = txCfgOpt;
      }

      setDefaultStateProxy(elDisplayable);
    }
  }

  function updateZ$1(el, elOption, seriesModel, attachedTxInfo) {
    if (el.isGroup) {
      return;
    }

    var elDisplayable = el;
    var currentZ = seriesModel.currentZ;
    var currentZLevel = seriesModel.currentZLevel;
    elDisplayable.z = currentZ;
    elDisplayable.zlevel = currentZLevel;
    var optZ2 = elOption.z2;
    optZ2 != null && (elDisplayable.z2 = optZ2 || 0);

    for (var i = 0; i < STATES.length; i++) {
      updateZForEachState(elDisplayable, elOption, STATES[i]);
    }
  }

  function updateZForEachState(elDisplayable, elOption, state) {
    var isNormal = state === NORMAL;
    var elStateOpt = isNormal ? elOption : retrieveStateOption(elOption, state);
    var optZ2 = elStateOpt ? elStateOpt.z2 : null;
    var stateObj;

    if (optZ2 != null) {
      stateObj = isNormal ? elDisplayable : elDisplayable.ensureState(state);
      stateObj.z2 = optZ2 || 0;
    }
  }

  function setLagecyTransformProp(elOption, targetProps, legacyName, fromTransformable) {
    var legacyArr = elOption[legacyName];
    var xyName = LEGACY_TRANSFORM_PROPS[legacyName];

    if (legacyArr) {
      if (fromTransformable) {
        targetProps[xyName[0]] = fromTransformable[xyName[0]];
        targetProps[xyName[1]] = fromTransformable[xyName[1]];
      } else {
        targetProps[xyName[0]] = legacyArr[0];
        targetProps[xyName[1]] = legacyArr[1];
      }
    }
  }

  function setTransformProp(elOption, allProps, name, fromTransformable) {
    if (elOption[name] != null) {
      allProps[name] = fromTransformable ? fromTransformable[name] : elOption[name];
    }
  }

  function setTransformPropToTransitionFrom(transitionFrom, name, fromTransformable) {
    if (fromTransformable) {
      transitionFrom[name] = fromTransformable[name];
    }
  }

  function makeRenderItem(customSeries, data, ecModel, api) {
    var renderItem = customSeries.get('renderItem');
    var coordSys = customSeries.coordinateSystem;
    var prepareResult = {};

    if (coordSys) {
      if (true) {
        assert(renderItem, 'series.render is required.');
        assert(coordSys.prepareCustoms || prepareCustoms[coordSys.type], 'This coordSys does not support custom series.');
      }

      prepareResult = coordSys.prepareCustoms ? coordSys.prepareCustoms(coordSys) : prepareCustoms[coordSys.type](coordSys);
    }

    var userAPI = defaults({
      getWidth: api.getWidth,
      getHeight: api.getHeight,
      getZr: api.getZr,
      getDevicePixelRatio: api.getDevicePixelRatio,
      value: value,
      style: style,
      ordinalRawValue: ordinalRawValue,
      styleEmphasis: styleEmphasis,
      visual: visual,
      barLayout: barLayout,
      currentSeriesIndices: currentSeriesIndices,
      font: font
    }, prepareResult.api || {});
    var userParams = {
      context: {},
      seriesId: customSeries.id,
      seriesName: customSeries.name,
      seriesIndex: customSeries.seriesIndex,
      coordSys: prepareResult.coordSys,
      dataInsideLength: data.count(),
      encode: wrapEncodeDef(customSeries.getData())
    };
    var currDataIndexInside;
    var currItemModel;
    var currItemStyleModels = {};
    var currLabelModels = {};
    var seriesItemStyleModels = {};
    var seriesLabelModels = {};

    for (var i = 0; i < STATES.length; i++) {
      var stateName = STATES[i];
      seriesItemStyleModels[stateName] = customSeries.getModel(PATH_ITEM_STYLE[stateName]);
      seriesLabelModels[stateName] = customSeries.getModel(PATH_LABEL[stateName]);
    }

    function getItemModel(dataIndexInside) {
      return dataIndexInside === currDataIndexInside ? currItemModel || (currItemModel = data.getItemModel(dataIndexInside)) : data.getItemModel(dataIndexInside);
    }

    function getItemStyleModel(dataIndexInside, state) {
      return !data.hasItemOption ? seriesItemStyleModels[state] : dataIndexInside === currDataIndexInside ? currItemStyleModels[state] || (currItemStyleModels[state] = getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state])) : getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state]);
    }

    function getLabelModel(dataIndexInside, state) {
      return !data.hasItemOption ? seriesLabelModels[state] : dataIndexInside === currDataIndexInside ? currLabelModels[state] || (currLabelModels[state] = getItemModel(dataIndexInside).getModel(PATH_LABEL[state])) : getItemModel(dataIndexInside).getModel(PATH_LABEL[state]);
    }

    return function (dataIndexInside, payload) {
      currDataIndexInside = dataIndexInside;
      currItemModel = null;
      currItemStyleModels = {};
      currLabelModels = {};
      return renderItem && renderItem(defaults({
        dataIndexInside: dataIndexInside,
        dataIndex: data.getRawIndex(dataIndexInside),
        actionType: payload ? payload.type : null
      }, userParams), userAPI);
    };

    function value(dim, dataIndexInside) {
      dataIndexInside == null && (dataIndexInside = currDataIndexInside);
      return data.get(data.getDimension(dim || 0), dataIndexInside);
    }

    function ordinalRawValue(dim, dataIndexInside) {
      dataIndexInside == null && (dataIndexInside = currDataIndexInside);
      var dimInfo = data.getDimensionInfo(dim || 0);

      if (!dimInfo) {
        return;
      }

      var val = data.get(dimInfo.name, dataIndexInside);
      var ordinalMeta = dimInfo && dimInfo.ordinalMeta;
      return ordinalMeta ? ordinalMeta.categories[val] : val;
    }

    function style(userProps, dataIndexInside) {
      if (true) {
        warnDeprecated('api.style', 'Please write literal style directly instead.');
      }

      dataIndexInside == null && (dataIndexInside = currDataIndexInside);
      var style = data.getItemVisual(dataIndexInside, 'style');
      var visualColor = style && style.fill;
      var opacity = style && style.opacity;
      var itemStyle = getItemStyleModel(dataIndexInside, NORMAL).getItemStyle();
      visualColor != null && (itemStyle.fill = visualColor);
      opacity != null && (itemStyle.opacity = opacity);
      var opt = {
        inheritColor: isString(visualColor) ? visualColor : '#000'
      };
      var labelModel = getLabelModel(dataIndexInside, NORMAL);
      var textStyle = createTextStyle(labelModel, null, opt, false, true);
      textStyle.text = labelModel.getShallow('show') ? retrieve2(customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null;
      var textConfig = createTextConfig(labelModel, opt, false);
      preFetchFromExtra(userProps, itemStyle);
      itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig);
      userProps && applyUserPropsAfter(itemStyle, userProps);
      itemStyle.legacy = true;
      return itemStyle;
    }

    function styleEmphasis(userProps, dataIndexInside) {
      if (true) {
        warnDeprecated('api.styleEmphasis', 'Please write literal style directly instead.');
      }

      dataIndexInside == null && (dataIndexInside = currDataIndexInside);
      var itemStyle = getItemStyleModel(dataIndexInside, EMPHASIS).getItemStyle();
      var labelModel = getLabelModel(dataIndexInside, EMPHASIS);
      var textStyle = createTextStyle(labelModel, null, null, true, true);
      textStyle.text = labelModel.getShallow('show') ? retrieve3(customSeries.getFormattedLabel(dataIndexInside, EMPHASIS), customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null;
      var textConfig = createTextConfig(labelModel, null, true);
      preFetchFromExtra(userProps, itemStyle);
      itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig);
      userProps && applyUserPropsAfter(itemStyle, userProps);
      itemStyle.legacy = true;
      return itemStyle;
    }

    function applyUserPropsAfter(itemStyle, extra) {
      for (var key in extra) {
        if (hasOwn(extra, key)) {
          itemStyle[key] = extra[key];
        }
      }
    }

    function preFetchFromExtra(extra, itemStyle) {
      if (extra) {
        extra.textFill && (itemStyle.textFill = extra.textFill);
        extra.textPosition && (itemStyle.textPosition = extra.textPosition);
      }
    }

    function visual(visualType, dataIndexInside) {
      dataIndexInside == null && (dataIndexInside = currDataIndexInside);

      if (hasOwn(STYLE_VISUAL_TYPE, visualType)) {
        var style_1 = data.getItemVisual(dataIndexInside, 'style');
        return style_1 ? style_1[STYLE_VISUAL_TYPE[visualType]] : null;
      }

      if (hasOwn(NON_STYLE_VISUAL_PROPS, visualType)) {
        return data.getItemVisual(dataIndexInside, visualType);
      }
    }

    function barLayout(opt) {
      if (coordSys.type === 'cartesian2d') {
        var baseAxis = coordSys.getBaseAxis();
        return getLayoutOnAxis(defaults({
          axis: baseAxis
        }, opt));
      }
    }

    function currentSeriesIndices() {
      return ecModel.getCurrentSeriesIndices();
    }

    function font(opt) {
      return getFont(opt, ecModel);
    }
  }

  function wrapEncodeDef(data) {
    var encodeDef = {};
    each(data.dimensions, function (dimName, dataDimIndex) {
      var dimInfo = data.getDimensionInfo(dimName);

      if (!dimInfo.isExtraCoord) {
        var coordDim = dimInfo.coordDim;
        var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || [];
        dataDims[dimInfo.coordDimIndex] = dataDimIndex;
      }
    });
    return encodeDef;
  }

  function createOrUpdateItem(api, el, dataIndex, elOption, seriesModel, group, data, morphPreparation) {
    if (!elOption) {
      removeElementDirectly(el, group);
      return;
    }

    el = doCreateOrUpdateEl(api, el, dataIndex, elOption, seriesModel, group, true, morphPreparation);
    el && data.setItemGraphicEl(dataIndex, el);
    enableHoverEmphasis(el, elOption.focus, elOption.blurScope);
    return el;
  }

  function doCreateOrUpdateEl(api, el, dataIndex, elOption, seriesModel, group, isRoot, morphPreparation) {
    if (true) {
      assert(elOption, 'should not have an null/undefined element setting');
    }

    var toBeReplacedIdx = -1;

    if (el && doesElNeedRecreate(el, elOption)) {
      toBeReplacedIdx = group.childrenRef().indexOf(el);
      el = null;
    }

    var elIsNewCreated = !el;

    if (!el) {
      el = createEl(elOption);
    } else {
      el.clearStates();
    }

    var canMorph = inner$e(el).canMorph = elOption.morph && isPath$1(el);
    var thisElIsMorphTo = canMorph && morphPreparation && morphPreparation.hasFrom();
    var isInit = elIsNewCreated && !thisElIsMorphTo;
    attachedTxInfoTmp.normal.cfg = attachedTxInfoTmp.normal.conOpt = attachedTxInfoTmp.emphasis.cfg = attachedTxInfoTmp.emphasis.conOpt = attachedTxInfoTmp.blur.cfg = attachedTxInfoTmp.blur.conOpt = attachedTxInfoTmp.select.cfg = attachedTxInfoTmp.select.conOpt = null;
    attachedTxInfoTmp.isLegacy = false;
    doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfoTmp);
    doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit);
    var pendingAllPropsFinal = updateElNormal(api, el, thisElIsMorphTo, dataIndex, elOption, elOption.style, attachedTxInfoTmp, seriesModel, isInit, false);

    if (thisElIsMorphTo) {
      morphPreparation.addTo(el, elOption, dataIndex, pendingAllPropsFinal);
    }

    for (var i = 0; i < STATES.length; i++) {
      var stateName = STATES[i];

      if (stateName !== NORMAL) {
        var otherStateOpt = retrieveStateOption(elOption, stateName);
        var otherStyleOpt = retrieveStyleOptionOnState(elOption, otherStateOpt, stateName);
        updateElOnState(stateName, el, otherStateOpt, otherStyleOpt, attachedTxInfoTmp);
      }
    }

    updateZ$1(el, elOption, seriesModel);

    if (elOption.type === 'group') {
      mergeChildren(api, el, dataIndex, elOption, seriesModel, morphPreparation);
    }

    if (toBeReplacedIdx >= 0) {
      group.replaceAt(el, toBeReplacedIdx);
    } else {
      group.add(el);
    }

    return el;
  }

  function doesElNeedRecreate(el, elOption) {
    var elInner = inner$e(el);
    var elOptionType = elOption.type;
    var elOptionShape = elOption.shape;
    var elOptionStyle = elOption.style;
    return elOptionType != null && elOptionType !== elInner.customGraphicType || elOptionType === 'path' && hasOwnPathData(elOptionShape) && getPathData(elOptionShape) !== elInner.customPathData || elOptionType === 'image' && hasOwn(elOptionStyle, 'image') && elOptionStyle.image !== elInner.customImagePath;
  }

  function doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit) {
    var clipPathOpt = elOption.clipPath;

    if (clipPathOpt === false) {
      if (el && el.getClipPath()) {
        el.removeClipPath();
      }
    } else if (clipPathOpt) {
      var clipPath = el.getClipPath();

      if (clipPath && doesElNeedRecreate(clipPath, clipPathOpt)) {
        clipPath = null;
      }

      if (!clipPath) {
        clipPath = createEl(clipPathOpt);

        if (true) {
          assert(clipPath instanceof Path, 'Only any type of `path` can be used in `clipPath`, rather than ' + clipPath.type + '.');
        }

        el.setClipPath(clipPath);
      }

      updateElNormal(null, clipPath, null, dataIndex, clipPathOpt, null, null, seriesModel, isInit, false);
    }
  }

  function doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfo) {
    if (el.isGroup) {
      return;
    }

    processTxInfo(elOption, null, attachedTxInfo);
    processTxInfo(elOption, EMPHASIS, attachedTxInfo);
    var txConOptNormal = attachedTxInfo.normal.conOpt;
    var txConOptEmphasis = attachedTxInfo.emphasis.conOpt;
    var txConOptBlur = attachedTxInfo.blur.conOpt;
    var txConOptSelect = attachedTxInfo.select.conOpt;

    if (txConOptNormal != null || txConOptEmphasis != null || txConOptSelect != null || txConOptBlur != null) {
      var textContent = el.getTextContent();

      if (txConOptNormal === false) {
        textContent && el.removeTextContent();
      } else {
        txConOptNormal = attachedTxInfo.normal.conOpt = txConOptNormal || {
          type: 'text'
        };

        if (!textContent) {
          textContent = createEl(txConOptNormal);
          el.setTextContent(textContent);
        } else {
          textContent.clearStates();
        }

        var txConStlOptNormal = txConOptNormal && txConOptNormal.style;
        updateElNormal(null, textContent, null, dataIndex, txConOptNormal, txConStlOptNormal, null, seriesModel, isInit, true);

        for (var i = 0; i < STATES.length; i++) {
          var stateName = STATES[i];

          if (stateName !== NORMAL) {
            var txConOptOtherState = attachedTxInfo[stateName].conOpt;
            updateElOnState(stateName, textContent, txConOptOtherState, retrieveStyleOptionOnState(txConOptNormal, txConOptOtherState, stateName), null);
          }
        }

        txConStlOptNormal ? textContent.dirty() : textContent.markRedraw();
      }
    }
  }

  function processTxInfo(elOption, state, attachedTxInfo) {
    var stateOpt = !state ? elOption : retrieveStateOption(elOption, state);
    var styleOpt = !state ? elOption.style : retrieveStyleOptionOnState(elOption, stateOpt, EMPHASIS);
    var elType = elOption.type;
    var txCfg = stateOpt ? stateOpt.textConfig : null;
    var txConOptNormal = elOption.textContent;
    var txConOpt = !txConOptNormal ? null : !state ? txConOptNormal : retrieveStateOption(txConOptNormal, state);

    if (styleOpt && (attachedTxInfo.isLegacy || isEC4CompatibleStyle(styleOpt, elType, !!txCfg, !!txConOpt))) {
      attachedTxInfo.isLegacy = true;
      var convertResult = convertFromEC4CompatibleStyle(styleOpt, elType, !state);

      if (!txCfg && convertResult.textConfig) {
        txCfg = convertResult.textConfig;
      }

      if (!txConOpt && convertResult.textContent) {
        txConOpt = convertResult.textContent;
      }
    }

    if (!state && txConOpt) {
      var txConOptNormal_1 = txConOpt;
      !txConOptNormal_1.type && (txConOptNormal_1.type = 'text');

      if (true) {
        txConOptNormal_1.type !== 'text' && assert(txConOptNormal_1.type === 'text', 'textContent.type must be "text"');
      }
    }

    var info = !state ? attachedTxInfo.normal : attachedTxInfo[state];
    info.cfg = txCfg;
    info.conOpt = txConOpt;
  }

  function retrieveStateOption(elOption, state) {
    return !state ? elOption : elOption ? elOption[state] : null;
  }

  function retrieveStyleOptionOnState(stateOptionNormal, stateOption, state) {
    var style = stateOption && stateOption.style;

    if (style == null && state === EMPHASIS && stateOptionNormal) {
      style = stateOptionNormal.styleEmphasis;
    }

    return style;
  }

  function mergeChildren(api, el, dataIndex, elOption, seriesModel, morphPreparation) {
    var newChildren = elOption.children;
    var newLen = newChildren ? newChildren.length : 0;
    var mergeChildren = elOption.$mergeChildren;
    var byName = mergeChildren === 'byName' || elOption.diffChildrenByName;
    var notMerge = mergeChildren === false;

    if (!newLen && !byName && !notMerge) {
      return;
    }

    if (byName) {
      diffGroupChildren({
        api: api,
        oldChildren: el.children() || [],
        newChildren: newChildren || [],
        dataIndex: dataIndex,
        seriesModel: seriesModel,
        group: el,
        morphPreparation: morphPreparation
      });
      return;
    }

    notMerge && el.removeAll();
    var index = 0;

    for (; index < newLen; index++) {
      newChildren[index] && doCreateOrUpdateEl(api, el.childAt(index), dataIndex, newChildren[index], seriesModel, el, false, morphPreparation);
    }

    for (var i = el.childCount() - 1; i >= index; i--) {
      doRemoveEl(el.childAt(i), seriesModel, el);
    }
  }

  function diffGroupChildren(context) {
    new DataDiffer(context.oldChildren, context.newChildren, getKey, getKey, context).add(processAddUpdate).update(processAddUpdate).remove(processRemove).execute();
  }

  function getKey(item, idx) {
    var name = item && item.name;
    return name != null ? name : GROUP_DIFF_PREFIX + idx;
  }

  function processAddUpdate(newIndex, oldIndex) {
    var context = this.context;
    var childOption = newIndex != null ? context.newChildren[newIndex] : null;
    var child = oldIndex != null ? context.oldChildren[oldIndex] : null;
    doCreateOrUpdateEl(context.api, child, context.dataIndex, childOption, context.seriesModel, context.group, false, context.morphPreparation);
  }

  function processRemove(oldIndex) {
    var context = this.context;
    var child = context.oldChildren[oldIndex];
    doRemoveEl(child, context.seriesModel, context.group);
  }

  function doRemoveEl(el, seriesModel, group) {
    if (el) {
      var leaveToProps = inner$e(el).leaveToProps;
      leaveToProps ? updateProps(el, leaveToProps, seriesModel, {
        cb: function () {
          group.remove(el);
        }
      }) : group.remove(el);
    }
  }

  function getPathData(shape) {
    return shape && (shape.pathData || shape.d);
  }

  function hasOwnPathData(shape) {
    return shape && (hasOwn(shape, 'pathData') || hasOwn(shape, 'd'));
  }

  function isPath$1(el) {
    return el && el instanceof Path;
  }

  function removeElementDirectly(el, group) {
    el && group.remove(el);
  }

  var MorphPreparation = function () {
    function MorphPreparation(seriesModel, transOpt) {
      this._fromList = [];
      this._toList = [];
      this._toElOptionList = [];
      this._allPropsFinalList = [];
      this._toDataIndices = [];
      this._morphConfigList = [];
      this._seriesModel = seriesModel;
      this._transOpt = transOpt;
    }

    MorphPreparation.prototype.hasFrom = function () {
      return !!this._fromList.length;
    };

    MorphPreparation.prototype.findAndAddFrom = function (el) {
      if (!el) {
        return;
      }

      if (inner$e(el).canMorph) {
        this._fromList.push(el);
      }

      if (el.isGroup) {
        var children = el.childrenRef();

        for (var i = 0; i < children.length; i++) {
          this.findAndAddFrom(children[i]);
        }
      }
    };

    MorphPreparation.prototype.addTo = function (path, elOption, dataIndex, allPropsFinal) {
      if (path) {
        this._toList.push(path);

        this._toElOptionList.push(elOption);

        this._toDataIndices.push(dataIndex);

        this._allPropsFinalList.push(allPropsFinal);
      }
    };

    MorphPreparation.prototype.applyMorphing = function () {
      var type = this._type;
      var fromList = this._fromList;
      var toList = this._toList;
      var toListLen = toList.length;
      var fromListLen = fromList.length;

      if (!fromListLen || !toListLen) {
        return;
      }

      if (type === 'oneToOne') {
        for (var toIdx = 0; toIdx < toListLen; toIdx++) {
          this._oneToOneForSingleTo(toIdx, toIdx);
        }
      } else if (type === 'manyToOne') {
        var fromSingleSegLen = Math.max(1, Math.floor(fromListLen / toListLen));

        for (var toIdx = 0, fromIdxStart = 0; toIdx < toListLen; toIdx++, fromIdxStart += fromSingleSegLen) {
          var fromCount = toIdx + 1 >= toListLen ? fromListLen - fromIdxStart : fromSingleSegLen;

          this._manyToOneForSingleTo(toIdx, fromIdxStart >= fromListLen ? null : fromIdxStart, fromCount);
        }
      } else if (type === 'oneToMany') {
        var toSingleSegLen = Math.max(1, Math.floor(toListLen / fromListLen));

        for (var toIdxStart = 0, fromIdx = 0; toIdxStart < toListLen; toIdxStart += toSingleSegLen, fromIdx++) {
          var toCount = toIdxStart + toSingleSegLen >= toListLen ? toListLen - toIdxStart : toSingleSegLen;

          this._oneToManyForSingleFrom(toIdxStart, toCount, fromIdx >= fromListLen ? null : fromIdx);
        }
      }
    };

    MorphPreparation.prototype._oneToOneForSingleTo = function (toIdx, fromIdx) {
      var to = this._toList[toIdx];
      var toElOption = this._toElOptionList[toIdx];
      var toDataIndex = this._toDataIndices[toIdx];
      var allPropsFinal = this._allPropsFinalList[toIdx];
      var from = this._fromList[fromIdx];

      var elAnimationConfig = this._getOrCreateMorphConfig(toDataIndex);

      var morphDuration = elAnimationConfig.duration;

      if (from && isCombiningPath(from)) {
        applyPropsFinal(to, allPropsFinal, toElOption.style);

        if (morphDuration) {
          var combineResult = combine([from], to, elAnimationConfig, copyPropsWhenDivided);

          this._processResultIndividuals(combineResult, toIdx, null);
        }
      } else {
        var morphFrom = morphDuration && from && (from !== to || isInAnyMorphing(from)) ? from : null;
        var transFromProps = {};
        prepareShapeOrExtraTransitionFrom('shape', to, morphFrom, toElOption, transFromProps, false);
        prepareShapeOrExtraTransitionFrom('extra', to, morphFrom, toElOption, transFromProps, false);
        prepareTransformTransitionFrom(to, morphFrom, toElOption, transFromProps, false);
        prepareStyleTransitionFrom(to, morphFrom, toElOption, toElOption.style, transFromProps, false);
        applyPropsFinal(to, allPropsFinal, toElOption.style);

        if (morphFrom) {
          morphPath(morphFrom, to, elAnimationConfig);
        }

        applyTransitionFrom(to, toDataIndex, toElOption, this._seriesModel, transFromProps, false);
      }
    };

    MorphPreparation.prototype._manyToOneForSingleTo = function (toIdx, fromIdxStart, fromCount) {
      var to = this._toList[toIdx];
      var toElOption = this._toElOptionList[toIdx];
      var allPropsFinal = this._allPropsFinalList[toIdx];
      applyPropsFinal(to, allPropsFinal, toElOption.style);

      var elAnimationConfig = this._getOrCreateMorphConfig(this._toDataIndices[toIdx]);

      if (elAnimationConfig.duration && fromIdxStart != null) {
        var combineFromList = [];

        for (var fromIdx = fromIdxStart; fromIdx < fromCount; fromIdx++) {
          combineFromList.push(this._fromList[fromIdx]);
        }

        var combineResult = combine(combineFromList, to, elAnimationConfig, copyPropsWhenDivided);

        this._processResultIndividuals(combineResult, toIdx, null);
      }
    };

    MorphPreparation.prototype._oneToManyForSingleFrom = function (toIdxStart, toCount, fromIdx) {
      var from = fromIdx == null ? null : this._fromList[fromIdx];
      var toList = this._toList;
      var separateToList = [];

      for (var toIdx = toIdxStart; toIdx < toCount; toIdx++) {
        var to = toList[toIdx];
        applyPropsFinal(to, this._allPropsFinalList[toIdx], this._toElOptionList[toIdx].style);
        separateToList.push(to);
      }

      var elAnimationConfig = this._getOrCreateMorphConfig(this._toDataIndices[toIdxStart]);

      if (elAnimationConfig.duration && from) {
        var separateResult = separate(from, separateToList, elAnimationConfig, copyPropsWhenDivided);

        this._processResultIndividuals(separateResult, toIdxStart, toCount);
      }
    };

    MorphPreparation.prototype._processResultIndividuals = function (combineSeparateResult, toIdxStart, toCount) {
      var isSeparate = toCount != null;

      for (var i = 0; i < combineSeparateResult.count; i++) {
        var fromIndividual = combineSeparateResult.fromIndividuals[i];
        var toIndividual = combineSeparateResult.toIndividuals[i];
        var toIdx = toIdxStart + (isSeparate ? i : 0);
        var toElOption = this._toElOptionList[toIdx];
        var dataIndex = this._toDataIndices[toIdx];
        var transFromProps = {};
        prepareTransformTransitionFrom(toIndividual, fromIndividual, toElOption, transFromProps, false);
        prepareStyleTransitionFrom(toIndividual, fromIndividual, toElOption, toElOption.style, transFromProps, false);
        applyTransitionFrom(toIndividual, dataIndex, toElOption, this._seriesModel, transFromProps, false);
      }
    };

    MorphPreparation.prototype._getOrCreateMorphConfig = function (dataIndex) {
      var morphConfigList = this._morphConfigList;
      var config = morphConfigList[dataIndex];

      if (config) {
        return config;
      }

      var duration;
      var easing;
      var delay;
      var seriesModel = this._seriesModel;
      var transOpt = this._transOpt;

      if (seriesModel.isAnimationEnabled()) {
        var animationPayload = void 0;

        if (seriesModel && seriesModel.ecModel) {
          var updatePayload = seriesModel.ecModel.getUpdatePayload();
          animationPayload = updatePayload && updatePayload.animation;
        }

        if (animationPayload) {
          duration = animationPayload.duration || 0;
          easing = animationPayload.easing || 'cubicOut';
          delay = animationPayload.delay || 0;
        } else {
          easing = seriesModel.get('animationEasingUpdate');
          var delayOption = seriesModel.get('animationDelayUpdate');
          delay = isFunction(delayOption) ? delayOption(dataIndex) : delayOption;
          var durationOption = seriesModel.get('animationDurationUpdate');
          duration = isFunction(durationOption) ? durationOption(dataIndex) : durationOption;
        }
      }

      config = {
        duration: duration || 0,
        delay: delay,
        easing: easing,
        dividingMethod: transOpt ? transOpt.dividingMethod : null
      };
      morphConfigList[dataIndex] = config;
      return config;
    };

    MorphPreparation.prototype.reset = function (type) {
      this._type = type;
      this._fromList.length = this._toList.length = this._toElOptionList.length = this._allPropsFinalList.length = this._toDataIndices.length = 0;
    };

    return MorphPreparation;
  }();

  function copyPropsWhenDivided(srcPath, tarPath, willClone) {
    tarPath.style = willClone ? clone(srcPath.style) : srcPath.style;
    tarPath.zlevel = srcPath.zlevel;
    tarPath.z = srcPath.z;
    tarPath.z2 = srcPath.z2;
  }

  function getSeriesStackId$1(seriesModel) {
    return seriesModel.get('stack') || '__ec_stack_' + seriesModel.seriesIndex;
  }

  function getAxisKey$1(polar, axis) {
    return axis.dim + polar.model.componentIndex;
  }

  function barLayoutPolar(seriesType, ecModel, api) {
    var lastStackCoords = {};
    var barWidthAndOffset = calRadialBar(filter(ecModel.getSeriesByType(seriesType), function (seriesModel) {
      return !ecModel.isSeriesFiltered(seriesModel) && seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'polar';
    }));
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
      if (seriesModel.coordinateSystem.type !== 'polar') {
        return;
      }

      var data = seriesModel.getData();
      var polar = seriesModel.coordinateSystem;
      var baseAxis = polar.getBaseAxis();
      var axisKey = getAxisKey$1(polar, baseAxis);
      var stackId = getSeriesStackId$1(seriesModel);
      var columnLayoutInfo = barWidthAndOffset[axisKey][stackId];
      var columnOffset = columnLayoutInfo.offset;
      var columnWidth = columnLayoutInfo.width;
      var valueAxis = polar.getOtherAxis(baseAxis);
      var cx = seriesModel.coordinateSystem.cx;
      var cy = seriesModel.coordinateSystem.cy;
      var barMinHeight = seriesModel.get('barMinHeight') || 0;
      var barMinAngle = seriesModel.get('barMinAngle') || 0;
      lastStackCoords[stackId] = lastStackCoords[stackId] || [];
      var valueDim = data.mapDimension(valueAxis.dim);
      var baseDim = data.mapDimension(baseAxis.dim);
      var stacked = isDimensionStacked(data, valueDim);
      var clampLayout = baseAxis.dim !== 'radius' || !seriesModel.get('roundCap', true);
      var valueAxisStart = valueAxis.dataToCoord(0);

      for (var idx = 0, len = data.count(); idx < len; idx++) {
        var value = data.get(valueDim, idx);
        var baseValue = data.get(baseDim, idx);
        var sign = value >= 0 ? 'p' : 'n';
        var baseCoord = valueAxisStart;

        if (stacked) {
          if (!lastStackCoords[stackId][baseValue]) {
            lastStackCoords[stackId][baseValue] = {
              p: valueAxisStart,
              n: valueAxisStart
            };
          }

          baseCoord = lastStackCoords[stackId][baseValue][sign];
        }

        var r0 = void 0;
        var r = void 0;
        var startAngle = void 0;
        var endAngle = void 0;

        if (valueAxis.dim === 'radius') {
          var radiusSpan = valueAxis.dataToCoord(value) - valueAxisStart;
          var angle = baseAxis.dataToCoord(baseValue);

          if (Math.abs(radiusSpan) < barMinHeight) {
            radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight;
          }

          r0 = baseCoord;
          r = baseCoord + radiusSpan;
          startAngle = angle - columnOffset;
          endAngle = startAngle - columnWidth;
          stacked && (lastStackCoords[stackId][baseValue][sign] = r);
        } else {
          var angleSpan = valueAxis.dataToCoord(value, clampLayout) - valueAxisStart;
          var radius = baseAxis.dataToCoord(baseValue);

          if (Math.abs(angleSpan) < barMinAngle) {
            angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle;
          }

          r0 = radius + columnOffset;
          r = r0 + columnWidth;
          startAngle = baseCoord;
          endAngle = baseCoord + angleSpan;
          stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle);
        }

        data.setItemLayout(idx, {
          cx: cx,
          cy: cy,
          r0: r0,
          r: r,
          startAngle: -startAngle * Math.PI / 180,
          endAngle: -endAngle * Math.PI / 180
        });
      }
    });
  }

  function calRadialBar(barSeries) {
    var columnsMap = {};
    each(barSeries, function (seriesModel, idx) {
      var data = seriesModel.getData();
      var polar = seriesModel.coordinateSystem;
      var baseAxis = polar.getBaseAxis();
      var axisKey = getAxisKey$1(polar, baseAxis);
      var axisExtent = baseAxis.getExtent();
      var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : Math.abs(axisExtent[1] - axisExtent[0]) / data.count();
      var columnsOnAxis = columnsMap[axisKey] || {
        bandWidth: bandWidth,
        remainedWidth: bandWidth,
        autoWidthCount: 0,
        categoryGap: '20%',
        gap: '30%',
        stacks: {}
      };
      var stacks = columnsOnAxis.stacks;
      columnsMap[axisKey] = columnsOnAxis;
      var stackId = getSeriesStackId$1(seriesModel);

      if (!stacks[stackId]) {
        columnsOnAxis.autoWidthCount++;
      }

      stacks[stackId] = stacks[stackId] || {
        width: 0,
        maxWidth: 0
      };
      var barWidth = parsePercent$2(seriesModel.get('barWidth'), bandWidth);
      var barMaxWidth = parsePercent$2(seriesModel.get('barMaxWidth'), bandWidth);
      var barGap = seriesModel.get('barGap');
      var barCategoryGap = seriesModel.get('barCategoryGap');

      if (barWidth && !stacks[stackId].width) {
        barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
        stacks[stackId].width = barWidth;
        columnsOnAxis.remainedWidth -= barWidth;
      }

      barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
      barGap != null && (columnsOnAxis.gap = barGap);
      barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap);
    });
    var result = {};
    each(columnsMap, function (columnsOnAxis, coordSysName) {
      result[coordSysName] = {};
      var stacks = columnsOnAxis.stacks;
      var bandWidth = columnsOnAxis.bandWidth;
      var categoryGap = parsePercent$2(columnsOnAxis.categoryGap, bandWidth);
      var barGapPercent = parsePercent$2(columnsOnAxis.gap, 1);
      var remainedWidth = columnsOnAxis.remainedWidth;
      var autoWidthCount = columnsOnAxis.autoWidthCount;
      var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
      autoWidth = Math.max(autoWidth, 0);
      each(stacks, function (column, stack) {
        var maxWidth = column.maxWidth;

        if (maxWidth && maxWidth < autoWidth) {
          maxWidth = Math.min(maxWidth, remainedWidth);

          if (column.width) {
            maxWidth = Math.min(maxWidth, column.width);
          }

          remainedWidth -= maxWidth;
          column.width = maxWidth;
          autoWidthCount--;
        }
      });
      autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
      autoWidth = Math.max(autoWidth, 0);
      var widthSum = 0;
      var lastColumn;
      each(stacks, function (column, idx) {
        if (!column.width) {
          column.width = autoWidth;
        }

        lastColumn = column;
        widthSum += column.width * (1 + barGapPercent);
      });

      if (lastColumn) {
        widthSum -= lastColumn.width * barGapPercent;
      }

      var offset = -widthSum / 2;
      each(stacks, function (column, stackId) {
        result[coordSysName][stackId] = result[coordSysName][stackId] || {
          offset: offset,
          width: column.width
        };
        offset += column.width * (1 + barGapPercent);
      });
    });
    return result;
  }

  var PolarModel = function (_super) {
    __extends(PolarModel, _super);

    function PolarModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = PolarModel.type;
      return _this;
    }

    PolarModel.prototype.findAxisModel = function (axisType) {
      var foundAxisModel;
      var ecModel = this.ecModel;
      ecModel.eachComponent(axisType, function (axisModel) {
        if (axisModel.getCoordSysModel() === this) {
          foundAxisModel = axisModel;
        }
      }, this);
      return foundAxisModel;
    };

    PolarModel.type = 'polar';
    PolarModel.dependencies = ['radiusAxis', 'angleAxis'];
    PolarModel.defaultOption = {
      zlevel: 0,
      z: 0,
      center: ['50%', '50%'],
      radius: '80%'
    };
    return PolarModel;
  }(ComponentModel);

  ComponentModel.registerClass(PolarModel);

  var PolarAxisModel = function (_super) {
    __extends(PolarAxisModel, _super);

    function PolarAxisModel() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    PolarAxisModel.prototype.getCoordSysModel = function () {
      return this.getReferringComponents('polar', SINGLE_REFERRING).models[0];
    };

    PolarAxisModel.type = 'polarAxis';
    return PolarAxisModel;
  }(ComponentModel);

  mixin(PolarAxisModel, AxisModelCommonMixin);

  var AngleAxisModel = function (_super) {
    __extends(AngleAxisModel, _super);

    function AngleAxisModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = AngleAxisModel.type;
      return _this;
    }

    AngleAxisModel.type = 'angleAxis';
    return AngleAxisModel;
  }(PolarAxisModel);

  var RadiusAxisModel = function (_super) {
    __extends(RadiusAxisModel, _super);

    function RadiusAxisModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadiusAxisModel.type;
      return _this;
    }

    RadiusAxisModel.type = 'radiusAxis';
    return RadiusAxisModel;
  }(PolarAxisModel);

  var angleAxisExtraOption = {
    startAngle: 90,
    clockwise: true,
    splitNumber: 12,
    axisLabel: {
      rotate: 0
    }
  };
  var radiusAxisExtraOption = {
    splitNumber: 5
  };
  axisModelCreator('angle', AngleAxisModel, angleAxisExtraOption);
  axisModelCreator('radius', RadiusAxisModel, radiusAxisExtraOption);

  var RadiusAxis = function (_super) {
    __extends(RadiusAxis, _super);

    function RadiusAxis(scale, radiusExtent) {
      return _super.call(this, 'radius', scale, radiusExtent) || this;
    }

    RadiusAxis.prototype.pointToData = function (point, clamp) {
      return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
    };

    return RadiusAxis;
  }(Axis);

  RadiusAxis.prototype.dataToRadius = Axis.prototype.dataToCoord;
  RadiusAxis.prototype.radiusToData = Axis.prototype.coordToData;
  var inner$f = makeInner();

  var AngleAxis = function (_super) {
    __extends(AngleAxis, _super);

    function AngleAxis(scale, angleExtent) {
      return _super.call(this, 'angle', scale, angleExtent || [0, 360]) || this;
    }

    AngleAxis.prototype.pointToData = function (point, clamp) {
      return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
    };

    AngleAxis.prototype.calculateCategoryInterval = function () {
      var axis = this;
      var labelModel = axis.getLabelModel();
      var ordinalScale = axis.scale;
      var ordinalExtent = ordinalScale.getExtent();
      var tickCount = ordinalScale.count();

      if (ordinalExtent[1] - ordinalExtent[0] < 1) {
        return 0;
      }

      var tickValue = ordinalExtent[0];
      var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
      var unitH = Math.abs(unitSpan);
      var rect = getBoundingRect(tickValue == null ? '' : tickValue + '', labelModel.getFont(), 'center', 'top');
      var maxH = Math.max(rect.height, 7);
      var dh = maxH / unitH;
      isNaN(dh) && (dh = Infinity);
      var interval = Math.max(0, Math.floor(dh));
      var cache = inner$f(axis.model);
      var lastAutoInterval = cache.lastAutoInterval;
      var lastTickCount = cache.lastTickCount;

      if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 && lastAutoInterval > interval) {
        interval = lastAutoInterval;
      } else {
        cache.lastTickCount = tickCount;
        cache.lastAutoInterval = interval;
      }

      return interval;
    };

    return AngleAxis;
  }(Axis);

  AngleAxis.prototype.dataToAngle = Axis.prototype.dataToCoord;
  AngleAxis.prototype.angleToData = Axis.prototype.coordToData;

  var Polar = function () {
    function Polar(name) {
      this.dimensions = ['radius', 'angle'];
      this.type = 'polar';
      this.cx = 0;
      this.cy = 0;
      this._radiusAxis = new RadiusAxis();
      this._angleAxis = new AngleAxis();
      this.axisPointerEnabled = true;
      this.name = name || '';
      this._radiusAxis.polar = this._angleAxis.polar = this;
    }

    Polar.prototype.containPoint = function (point) {
      var coord = this.pointToCoord(point);
      return this._radiusAxis.contain(coord[0]) && this._angleAxis.contain(coord[1]);
    };

    Polar.prototype.containData = function (data) {
      return this._radiusAxis.containData(data[0]) && this._angleAxis.containData(data[1]);
    };

    Polar.prototype.getAxis = function (dim) {
      var key = '_' + dim + 'Axis';
      return this[key];
    };

    Polar.prototype.getAxes = function () {
      return [this._radiusAxis, this._angleAxis];
    };

    Polar.prototype.getAxesByScale = function (scaleType) {
      var axes = [];
      var angleAxis = this._angleAxis;
      var radiusAxis = this._radiusAxis;
      angleAxis.scale.type === scaleType && axes.push(angleAxis);
      radiusAxis.scale.type === scaleType && axes.push(radiusAxis);
      return axes;
    };

    Polar.prototype.getAngleAxis = function () {
      return this._angleAxis;
    };

    Polar.prototype.getRadiusAxis = function () {
      return this._radiusAxis;
    };

    Polar.prototype.getOtherAxis = function (axis) {
      var angleAxis = this._angleAxis;
      return axis === angleAxis ? this._radiusAxis : angleAxis;
    };

    Polar.prototype.getBaseAxis = function () {
      return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAngleAxis();
    };

    Polar.prototype.getTooltipAxes = function (dim) {
      var baseAxis = dim != null && dim !== 'auto' ? this.getAxis(dim) : this.getBaseAxis();
      return {
        baseAxes: [baseAxis],
        otherAxes: [this.getOtherAxis(baseAxis)]
      };
    };

    Polar.prototype.dataToPoint = function (data, clamp) {
      return this.coordToPoint([this._radiusAxis.dataToRadius(data[0], clamp), this._angleAxis.dataToAngle(data[1], clamp)]);
    };

    Polar.prototype.pointToData = function (point, clamp) {
      var coord = this.pointToCoord(point);
      return [this._radiusAxis.radiusToData(coord[0], clamp), this._angleAxis.angleToData(coord[1], clamp)];
    };

    Polar.prototype.pointToCoord = function (point) {
      var dx = point[0] - this.cx;
      var dy = point[1] - this.cy;
      var angleAxis = this.getAngleAxis();
      var extent = angleAxis.getExtent();
      var minAngle = Math.min(extent[0], extent[1]);
      var maxAngle = Math.max(extent[0], extent[1]);
      angleAxis.inverse ? minAngle = maxAngle - 360 : maxAngle = minAngle + 360;
      var radius = Math.sqrt(dx * dx + dy * dy);
      dx /= radius;
      dy /= radius;
      var radian = Math.atan2(-dy, dx) / Math.PI * 180;
      var dir = radian < minAngle ? 1 : -1;

      while (radian < minAngle || radian > maxAngle) {
        radian += dir * 360;
      }

      return [radius, radian];
    };

    Polar.prototype.coordToPoint = function (coord) {
      var radius = coord[0];
      var radian = coord[1] / 180 * Math.PI;
      var x = Math.cos(radian) * radius + this.cx;
      var y = -Math.sin(radian) * radius + this.cy;
      return [x, y];
    };

    Polar.prototype.getArea = function () {
      var angleAxis = this.getAngleAxis();
      var radiusAxis = this.getRadiusAxis();
      var radiusExtent = radiusAxis.getExtent().slice();
      radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse();
      var angleExtent = angleAxis.getExtent();
      var RADIAN = Math.PI / 180;
      return {
        cx: this.cx,
        cy: this.cy,
        r0: radiusExtent[0],
        r: radiusExtent[1],
        startAngle: -angleExtent[0] * RADIAN,
        endAngle: -angleExtent[1] * RADIAN,
        clockwise: angleAxis.inverse,
        contain: function (x, y) {
          var dx = x - this.cx;
          var dy = y - this.cy;
          var d2 = dx * dx + dy * dy;
          var r = this.r;
          var r0 = this.r0;
          return d2 <= r * r && d2 >= r0 * r0;
        }
      };
    };

    Polar.prototype.convertToPixel = function (ecModel, finder, value) {
      var coordSys = getCoordSys$3(finder);
      return coordSys === this ? this.dataToPoint(value) : null;
    };

    Polar.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      var coordSys = getCoordSys$3(finder);
      return coordSys === this ? this.pointToData(pixel) : null;
    };

    return Polar;
  }();

  function getCoordSys$3(finder) {
    var seriesModel = finder.seriesModel;
    var polarModel = finder.polarModel;
    return polarModel && polarModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem;
  }

  function resizePolar(polar, polarModel, api) {
    var center = polarModel.get('center');
    var width = api.getWidth();
    var height = api.getHeight();
    polar.cx = parsePercent$2(center[0], width);
    polar.cy = parsePercent$2(center[1], height);
    var radiusAxis = polar.getRadiusAxis();
    var size = Math.min(width, height) / 2;
    var radius = polarModel.get('radius');

    if (radius == null) {
      radius = [0, '100%'];
    } else if (!isArray(radius)) {
      radius = [0, radius];
    }

    var parsedRadius = [parsePercent$2(radius[0], size), parsePercent$2(radius[1], size)];
    radiusAxis.inverse ? radiusAxis.setExtent(parsedRadius[1], parsedRadius[0]) : radiusAxis.setExtent(parsedRadius[0], parsedRadius[1]);
  }

  function updatePolarScale(ecModel, api) {
    var polar = this;
    var angleAxis = polar.getAngleAxis();
    var radiusAxis = polar.getRadiusAxis();
    angleAxis.scale.setExtent(Infinity, -Infinity);
    radiusAxis.scale.setExtent(Infinity, -Infinity);
    ecModel.eachSeries(function (seriesModel) {
      if (seriesModel.coordinateSystem === polar) {
        var data_1 = seriesModel.getData();
        each(getDataDimensionsOnAxis(data_1, 'radius'), function (dim) {
          radiusAxis.scale.unionExtentFromData(data_1, dim);
        });
        each(getDataDimensionsOnAxis(data_1, 'angle'), function (dim) {
          angleAxis.scale.unionExtentFromData(data_1, dim);
        });
      }
    });
    niceScaleExtent(angleAxis.scale, angleAxis.model);
    niceScaleExtent(radiusAxis.scale, radiusAxis.model);

    if (angleAxis.type === 'category' && !angleAxis.onBand) {
      var extent = angleAxis.getExtent();
      var diff = 360 / angleAxis.scale.count();
      angleAxis.inverse ? extent[1] += diff : extent[1] -= diff;
      angleAxis.setExtent(extent[0], extent[1]);
    }
  }

  function isAngleAxisModel(axisModel) {
    return axisModel.mainType === 'angleAxis';
  }

  function setAxis(axis, axisModel) {
    axis.type = axisModel.get('type');
    axis.scale = createScaleByModel(axisModel);
    axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category';
    axis.inverse = axisModel.get('inverse');

    if (isAngleAxisModel(axisModel)) {
      axis.inverse = axis.inverse !== axisModel.get('clockwise');
      var startAngle = axisModel.get('startAngle');
      axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360));
    }

    axisModel.axis = axis;
    axis.model = axisModel;
  }

  var polarCreator = {
    dimensions: Polar.prototype.dimensions,
    create: function (ecModel, api) {
      var polarList = [];
      ecModel.eachComponent('polar', function (polarModel, idx) {
        var polar = new Polar(idx + '');
        polar.update = updatePolarScale;
        var radiusAxis = polar.getRadiusAxis();
        var angleAxis = polar.getAngleAxis();
        var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
        var angleAxisModel = polarModel.findAxisModel('angleAxis');
        setAxis(radiusAxis, radiusAxisModel);
        setAxis(angleAxis, angleAxisModel);
        resizePolar(polar, polarModel, api);
        polarList.push(polar);
        polarModel.coordinateSystem = polar;
        polar.model = polarModel;
      });
      ecModel.eachSeries(function (seriesModel) {
        if (seriesModel.get('coordinateSystem') === 'polar') {
          var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0];

          if (true) {
            if (!polarModel) {
              throw new Error('Polar "' + retrieve(seriesModel.get('polarIndex'), seriesModel.get('polarId'), 0) + '" not found');
            }
          }

          seriesModel.coordinateSystem = polarModel.coordinateSystem;
        }
      });
      return polarList;
    }
  };
  CoordinateSystemManager.register('polar', polarCreator);
  var elementList$1 = ['axisLine', 'axisLabel', 'axisTick', 'minorTick', 'splitLine', 'minorSplitLine', 'splitArea'];

  function getAxisLineShape(polar, rExtent, angle) {
    rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse());
    var start = polar.coordToPoint([rExtent[0], angle]);
    var end = polar.coordToPoint([rExtent[1], angle]);
    return {
      x1: start[0],
      y1: start[1],
      x2: end[0],
      y2: end[1]
    };
  }

  function getRadiusIdx(polar) {
    var radiusAxis = polar.getRadiusAxis();
    return radiusAxis.inverse ? 0 : 1;
  }

  function fixAngleOverlap(list) {
    var firstItem = list[0];
    var lastItem = list[list.length - 1];

    if (firstItem && lastItem && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4) {
      list.pop();
    }
  }

  var AngleAxisView = function (_super) {
    __extends(AngleAxisView, _super);

    function AngleAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = AngleAxisView.type;
      _this.axisPointerClass = 'PolarAxisPointer';
      return _this;
    }

    AngleAxisView.prototype.render = function (angleAxisModel, ecModel) {
      this.group.removeAll();

      if (!angleAxisModel.get('show')) {
        return;
      }

      var angleAxis = angleAxisModel.axis;
      var polar = angleAxis.polar;
      var radiusExtent = polar.getRadiusAxis().getExtent();
      var ticksAngles = angleAxis.getTicksCoords();
      var minorTickAngles = angleAxis.getMinorTicksCoords();
      var labels = map(angleAxis.getViewLabels(), function (labelItem) {
        labelItem = clone(labelItem);
        labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
        return labelItem;
      });
      fixAngleOverlap(labels);
      fixAngleOverlap(ticksAngles);
      each(elementList$1, function (name) {
        if (angleAxisModel.get([name, 'show']) && (!angleAxis.scale.isBlank() || name === 'axisLine')) {
          angelAxisElementsBuilders[name](this.group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels);
        }
      }, this);
    };

    AngleAxisView.type = 'angleAxis';
    return AngleAxisView;
  }(AxisView);

  var angelAxisElementsBuilders = {
    axisLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
      var lineStyleModel = angleAxisModel.getModel(['axisLine', 'lineStyle']);
      var rId = getRadiusIdx(polar);
      var r0Id = rId ? 0 : 1;
      var shape;

      if (radiusExtent[r0Id] === 0) {
        shape = new Circle({
          shape: {
            cx: polar.cx,
            cy: polar.cy,
            r: radiusExtent[rId]
          },
          style: lineStyleModel.getLineStyle(),
          z2: 1,
          silent: true
        });
      } else {
        shape = new Ring({
          shape: {
            cx: polar.cx,
            cy: polar.cy,
            r: radiusExtent[rId],
            r0: radiusExtent[r0Id]
          },
          style: lineStyleModel.getLineStyle(),
          z2: 1,
          silent: true
        });
      }

      shape.style.fill = null;
      group.add(shape);
    },
    axisTick: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
      var tickModel = angleAxisModel.getModel('axisTick');
      var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
      var radius = radiusExtent[getRadiusIdx(polar)];
      var lines = map(ticksAngles, function (tickAngleItem) {
        return new Line({
          shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
        });
      });
      group.add(mergePath$1(lines, {
        style: defaults(tickModel.getModel('lineStyle').getLineStyle(), {
          stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color'])
        })
      }));
    },
    minorTick: function (group, angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) {
      if (!minorTickAngles.length) {
        return;
      }

      var tickModel = angleAxisModel.getModel('axisTick');
      var minorTickModel = angleAxisModel.getModel('minorTick');
      var tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length');
      var radius = radiusExtent[getRadiusIdx(polar)];
      var lines = [];

      for (var i = 0; i < minorTickAngles.length; i++) {
        for (var k = 0; k < minorTickAngles[i].length; k++) {
          lines.push(new Line({
            shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord)
          }));
        }
      }

      group.add(mergePath$1(lines, {
        style: defaults(minorTickModel.getModel('lineStyle').getLineStyle(), defaults(tickModel.getLineStyle(), {
          stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color'])
        }))
      }));
    },
    axisLabel: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) {
      var rawCategoryData = angleAxisModel.getCategories(true);
      var commonLabelModel = angleAxisModel.getModel('axisLabel');
      var labelMargin = commonLabelModel.get('margin');
      var triggerEvent = angleAxisModel.get('triggerEvent');
      each(labels, function (labelItem, idx) {
        var labelModel = commonLabelModel;
        var tickValue = labelItem.tickValue;
        var r = radiusExtent[getRadiusIdx(polar)];
        var p = polar.coordToPoint([r + labelMargin, labelItem.coord]);
        var cx = polar.cx;
        var cy = polar.cy;
        var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 ? 'center' : p[0] > cx ? 'left' : 'right';
        var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3 ? 'middle' : p[1] > cy ? 'top' : 'bottom';

        if (rawCategoryData && rawCategoryData[tickValue]) {
          var rawCategoryItem = rawCategoryData[tickValue];

          if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) {
            labelModel = new Model(rawCategoryItem.textStyle, commonLabelModel, commonLabelModel.ecModel);
          }
        }

        var textEl = new ZRText({
          silent: AxisBuilder.isLabelSilent(angleAxisModel),
          style: createTextStyle(labelModel, {
            x: p[0],
            y: p[1],
            fill: labelModel.getTextColor() || angleAxisModel.get(['axisLine', 'lineStyle', 'color']),
            text: labelItem.formattedLabel,
            align: labelTextAlign,
            verticalAlign: labelTextVerticalAlign
          })
        });
        group.add(textEl);

        if (triggerEvent) {
          var eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel);
          eventData.targetType = 'axisLabel';
          eventData.value = labelItem.rawLabel;
          getECData(textEl).eventData = eventData;
        }
      }, this);
    },
    splitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
      var splitLineModel = angleAxisModel.getModel('splitLine');
      var lineStyleModel = splitLineModel.getModel('lineStyle');
      var lineColors = lineStyleModel.get('color');
      var lineCount = 0;
      lineColors = lineColors instanceof Array ? lineColors : [lineColors];
      var splitLines = [];

      for (var i = 0; i < ticksAngles.length; i++) {
        var colorIndex = lineCount++ % lineColors.length;
        splitLines[colorIndex] = splitLines[colorIndex] || [];
        splitLines[colorIndex].push(new Line({
          shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
        }));
      }

      for (var i = 0; i < splitLines.length; i++) {
        group.add(mergePath$1(splitLines[i], {
          style: defaults({
            stroke: lineColors[i % lineColors.length]
          }, lineStyleModel.getLineStyle()),
          silent: true,
          z: angleAxisModel.get('z')
        }));
      }
    },
    minorSplitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
      if (!minorTickAngles.length) {
        return;
      }

      var minorSplitLineModel = angleAxisModel.getModel('minorSplitLine');
      var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
      var lines = [];

      for (var i = 0; i < minorTickAngles.length; i++) {
        for (var k = 0; k < minorTickAngles[i].length; k++) {
          lines.push(new Line({
            shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord)
          }));
        }
      }

      group.add(mergePath$1(lines, {
        style: lineStyleModel.getLineStyle(),
        silent: true,
        z: angleAxisModel.get('z')
      }));
    },
    splitArea: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
      if (!ticksAngles.length) {
        return;
      }

      var splitAreaModel = angleAxisModel.getModel('splitArea');
      var areaStyleModel = splitAreaModel.getModel('areaStyle');
      var areaColors = areaStyleModel.get('color');
      var lineCount = 0;
      areaColors = areaColors instanceof Array ? areaColors : [areaColors];
      var splitAreas = [];
      var RADIAN = Math.PI / 180;
      var prevAngle = -ticksAngles[0].coord * RADIAN;
      var r0 = Math.min(radiusExtent[0], radiusExtent[1]);
      var r1 = Math.max(radiusExtent[0], radiusExtent[1]);
      var clockwise = angleAxisModel.get('clockwise');

      for (var i = 1, len = ticksAngles.length; i <= len; i++) {
        var coord = i === len ? ticksAngles[0].coord : ticksAngles[i].coord;
        var colorIndex = lineCount++ % areaColors.length;
        splitAreas[colorIndex] = splitAreas[colorIndex] || [];
        splitAreas[colorIndex].push(new Sector({
          shape: {
            cx: polar.cx,
            cy: polar.cy,
            r0: r0,
            r: r1,
            startAngle: prevAngle,
            endAngle: -coord * RADIAN,
            clockwise: clockwise
          },
          silent: true
        }));
        prevAngle = -coord * RADIAN;
      }

      for (var i = 0; i < splitAreas.length; i++) {
        group.add(mergePath$1(splitAreas[i], {
          style: defaults({
            fill: areaColors[i % areaColors.length]
          }, areaStyleModel.getAreaStyle()),
          silent: true
        }));
      }
    }
  };
  ComponentView.registerClass(AngleAxisView);
  var axisBuilderAttrs$3 = ['axisLine', 'axisTickLabel', 'axisName'];
  var selfBuilderAttrs$2 = ['splitLine', 'splitArea', 'minorSplitLine'];

  var RadiusAxisView = function (_super) {
    __extends(RadiusAxisView, _super);

    function RadiusAxisView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = RadiusAxisView.type;
      _this.axisPointerClass = 'PolarAxisPointer';
      return _this;
    }

    RadiusAxisView.prototype.render = function (radiusAxisModel, ecModel) {
      this.group.removeAll();

      if (!radiusAxisModel.get('show')) {
        return;
      }

      var oldAxisGroup = this._axisGroup;
      var newAxisGroup = this._axisGroup = new Group();
      this.group.add(newAxisGroup);
      var radiusAxis = radiusAxisModel.axis;
      var polar = radiusAxis.polar;
      var angleAxis = polar.getAngleAxis();
      var ticksCoords = radiusAxis.getTicksCoords();
      var minorTicksCoords = radiusAxis.getMinorTicksCoords();
      var axisAngle = angleAxis.getExtent()[0];
      var radiusExtent = radiusAxis.getExtent();
      var layout = layoutAxis(polar, radiusAxisModel, axisAngle);
      var axisBuilder = new AxisBuilder(radiusAxisModel, layout);
      each(axisBuilderAttrs$3, axisBuilder.add, axisBuilder);
      newAxisGroup.add(axisBuilder.getGroup());
      groupTransition(oldAxisGroup, newAxisGroup, radiusAxisModel);
      each(selfBuilderAttrs$2, function (name) {
        if (radiusAxisModel.get([name, 'show']) && !radiusAxis.scale.isBlank()) {
          axisElementBuilders$2[name](this.group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords);
        }
      }, this);
    };

    RadiusAxisView.type = 'radiusAxis';
    return RadiusAxisView;
  }(AxisView);

  var axisElementBuilders$2 = {
    splitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
      var splitLineModel = radiusAxisModel.getModel('splitLine');
      var lineStyleModel = splitLineModel.getModel('lineStyle');
      var lineColors = lineStyleModel.get('color');
      var lineCount = 0;
      lineColors = lineColors instanceof Array ? lineColors : [lineColors];
      var splitLines = [];

      for (var i = 0; i < ticksCoords.length; i++) {
        var colorIndex = lineCount++ % lineColors.length;
        splitLines[colorIndex] = splitLines[colorIndex] || [];
        splitLines[colorIndex].push(new Circle({
          shape: {
            cx: polar.cx,
            cy: polar.cy,
            r: ticksCoords[i].coord
          }
        }));
      }

      for (var i = 0; i < splitLines.length; i++) {
        group.add(mergePath$1(splitLines[i], {
          style: defaults({
            stroke: lineColors[i % lineColors.length],
            fill: null
          }, lineStyleModel.getLineStyle()),
          silent: true
        }));
      }
    },
    minorSplitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords) {
      if (!minorTicksCoords.length) {
        return;
      }

      var minorSplitLineModel = radiusAxisModel.getModel('minorSplitLine');
      var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
      var lines = [];

      for (var i = 0; i < minorTicksCoords.length; i++) {
        for (var k = 0; k < minorTicksCoords[i].length; k++) {
          lines.push(new Circle({
            shape: {
              cx: polar.cx,
              cy: polar.cy,
              r: minorTicksCoords[i][k].coord
            }
          }));
        }
      }

      group.add(mergePath$1(lines, {
        style: defaults({
          fill: null
        }, lineStyleModel.getLineStyle()),
        silent: true
      }));
    },
    splitArea: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
      if (!ticksCoords.length) {
        return;
      }

      var splitAreaModel = radiusAxisModel.getModel('splitArea');
      var areaStyleModel = splitAreaModel.getModel('areaStyle');
      var areaColors = areaStyleModel.get('color');
      var lineCount = 0;
      areaColors = areaColors instanceof Array ? areaColors : [areaColors];
      var splitAreas = [];
      var prevRadius = ticksCoords[0].coord;

      for (var i = 1; i < ticksCoords.length; i++) {
        var colorIndex = lineCount++ % areaColors.length;
        splitAreas[colorIndex] = splitAreas[colorIndex] || [];
        splitAreas[colorIndex].push(new Sector({
          shape: {
            cx: polar.cx,
            cy: polar.cy,
            r0: prevRadius,
            r: ticksCoords[i].coord,
            startAngle: 0,
            endAngle: Math.PI * 2
          },
          silent: true
        }));
        prevRadius = ticksCoords[i].coord;
      }

      for (var i = 0; i < splitAreas.length; i++) {
        group.add(mergePath$1(splitAreas[i], {
          style: defaults({
            fill: areaColors[i % areaColors.length]
          }, areaStyleModel.getAreaStyle()),
          silent: true
        }));
      }
    }
  };

  function layoutAxis(polar, radiusAxisModel, axisAngle) {
    return {
      position: [polar.cx, polar.cy],
      rotation: axisAngle / 180 * Math.PI,
      labelDirection: -1,
      tickDirection: -1,
      nameDirection: 1,
      labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'),
      z2: 1
    };
  }

  AxisView.registerClass(RadiusAxisView);

  var PolarAxisPointer = function (_super) {
    __extends(PolarAxisPointer, _super);

    function PolarAxisPointer() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    PolarAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {
      var axis = axisModel.axis;

      if (axis.dim === 'angle') {
        this.animationThreshold = Math.PI / 18;
      }

      var polar = axis.polar;
      var otherAxis = polar.getOtherAxis(axis);
      var otherExtent = otherAxis.getExtent();
      var coordValue = axis.dataToCoord(value);
      var axisPointerType = axisPointerModel.get('type');

      if (axisPointerType && axisPointerType !== 'none') {
        var elStyle = buildElStyle(axisPointerModel);
        var pointerOption = pointerShapeBuilder$2[axisPointerType](axis, polar, coordValue, otherExtent);
        pointerOption.style = elStyle;
        elOption.graphicKey = pointerOption.type;
        elOption.pointer = pointerOption;
      }

      var labelMargin = axisPointerModel.get(['label', 'margin']);
      var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin);
      buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos);
    };

    return PolarAxisPointer;
  }(BaseAxisPointer);

  function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) {
    var axis = axisModel.axis;
    var coord = axis.dataToCoord(value);
    var axisAngle = polar.getAngleAxis().getExtent()[0];
    axisAngle = axisAngle / 180 * Math.PI;
    var radiusExtent = polar.getRadiusAxis().getExtent();
    var position;
    var align;
    var verticalAlign;

    if (axis.dim === 'radius') {
      var transform = create$1();
      rotate(transform, transform, axisAngle);
      translate(transform, transform, [polar.cx, polar.cy]);
      position = applyTransform$1([coord, -labelMargin], transform);
      var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0;
      var labelLayout = AxisBuilder.innerTextLayout(axisAngle, labelRotation * Math.PI / 180, -1);
      align = labelLayout.textAlign;
      verticalAlign = labelLayout.textVerticalAlign;
    } else {
      var r = radiusExtent[1];
      position = polar.coordToPoint([r + labelMargin, coord]);
      var cx = polar.cx;
      var cy = polar.cy;
      align = Math.abs(position[0] - cx) / r < 0.3 ? 'center' : position[0] > cx ? 'left' : 'right';
      verticalAlign = Math.abs(position[1] - cy) / r < 0.3 ? 'middle' : position[1] > cy ? 'top' : 'bottom';
    }

    return {
      position: position,
      align: align,
      verticalAlign: verticalAlign
    };
  }

  var pointerShapeBuilder$2 = {
    line: function (axis, polar, coordValue, otherExtent) {
      return axis.dim === 'angle' ? {
        type: 'Line',
        shape: makeLineShape(polar.coordToPoint([otherExtent[0], coordValue]), polar.coordToPoint([otherExtent[1], coordValue]))
      } : {
        type: 'Circle',
        shape: {
          cx: polar.cx,
          cy: polar.cy,
          r: coordValue
        }
      };
    },
    shadow: function (axis, polar, coordValue, otherExtent) {
      var bandWidth = Math.max(1, axis.getBandWidth());
      var radian = Math.PI / 180;
      return axis.dim === 'angle' ? {
        type: 'Sector',
        shape: makeSectorShape(polar.cx, polar.cy, otherExtent[0], otherExtent[1], (-coordValue - bandWidth / 2) * radian, (-coordValue + bandWidth / 2) * radian)
      } : {
        type: 'Sector',
        shape: makeSectorShape(polar.cx, polar.cy, coordValue - bandWidth / 2, coordValue + bandWidth / 2, 0, Math.PI * 2)
      };
    }
  };
  AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer);
  registerLayout(curry(barLayoutPolar, 'bar'));
  extendComponentView({
    type: 'polar'
  });

  var GeoView = function (_super) {
    __extends(GeoView, _super);

    function GeoView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GeoView.type;
      return _this;
    }

    GeoView.prototype.init = function (ecModel, api) {
      var mapDraw = new MapDraw(api);
      this._mapDraw = mapDraw;
      this.group.add(mapDraw.group);
      this._api = api;
    };

    GeoView.prototype.render = function (geoModel, ecModel, api, payload) {
      var mapDraw = this._mapDraw;

      if (geoModel.get('show')) {
        mapDraw.draw(geoModel, ecModel, api, this, payload);
      } else {
        this._mapDraw.group.removeAll();
      }

      mapDraw.group.on('click', this._handleRegionClick, this);
      mapDraw.group.silent = geoModel.get('silent');
      this._model = geoModel;
      this.updateSelectStatus(geoModel, ecModel, api);
    };

    GeoView.prototype._handleRegionClick = function (e) {
      var current = e.target;
      var eventData;

      while (current && (eventData = getECData(current).eventData) == null) {
        current = current.__hostTarget || current.parent;
      }

      if (eventData) {
        this._api.dispatchAction({
          type: 'geoToggleSelect',
          geoId: this._model.id,
          name: eventData.name
        });
      }
    };

    GeoView.prototype.updateSelectStatus = function (model, ecModel, api) {
      var _this = this;

      this._mapDraw.group.traverse(function (node) {
        var eventData = getECData(node).eventData;

        if (eventData) {
          _this._model.isSelected(eventData.name) ? api.enterSelect(node) : api.leaveSelect(node);
          return true;
        }
      });
    };

    GeoView.prototype.dispose = function () {
      this._mapDraw && this._mapDraw.remove();
    };

    GeoView.type = 'geo';
    return GeoView;
  }(ComponentView);

  ComponentView.registerClass(GeoView);

  var GeoModel = function (_super) {
    __extends(GeoModel, _super);

    function GeoModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GeoModel.type;
      return _this;
    }

    GeoModel.prototype.init = function (option, parentModel, ecModel) {
      _super.prototype.init.call(this, option, parentModel, ecModel);

      defaultEmphasis(option, 'label', ['show']);
    };

    GeoModel.prototype.optionUpdated = function () {
      var option = this.option;
      var self = this;
      option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap);
      var selectedMap = {};
      this._optionModelMap = reduce(option.regions || [], function (optionModelMap, regionOpt) {
        var regionName = regionOpt.name;

        if (regionName) {
          optionModelMap.set(regionName, new Model(regionOpt, self));

          if (regionOpt.selected) {
            selectedMap[regionName] = true;
          }
        }

        return optionModelMap;
      }, createHashMap());

      if (!option.selectedMap) {
        option.selectedMap = selectedMap;
      }
    };

    GeoModel.prototype.getRegionModel = function (name) {
      return this._optionModelMap.get(name) || new Model(null, this, this.ecModel);
    };

    GeoModel.prototype.getFormattedLabel = function (name, status) {
      var regionModel = this.getRegionModel(name);
      var formatter = status === 'normal' ? regionModel.get(['label', 'formatter']) : regionModel.get(['emphasis', 'label', 'formatter']);
      var params = {
        name: name
      };

      if (typeof formatter === 'function') {
        params.status = status;
        return formatter(params);
      } else if (typeof formatter === 'string') {
        return formatter.replace('{a}', name != null ? name : '');
      }
    };

    GeoModel.prototype.setZoom = function (zoom) {
      this.option.zoom = zoom;
    };

    GeoModel.prototype.setCenter = function (center) {
      this.option.center = center;
    };

    GeoModel.prototype.select = function (name) {
      var option = this.option;
      var selectedMode = option.selectedMode;

      if (!selectedMode) {
        return;
      }

      if (selectedMode !== 'multiple') {
        option.selectedMap = null;
      }

      var selectedMap = option.selectedMap || (option.selectedMap = {});
      selectedMap[name] = true;
    };

    GeoModel.prototype.unSelect = function (name) {
      var selectedMap = this.option.selectedMap;

      if (selectedMap) {
        selectedMap[name] = false;
      }
    };

    GeoModel.prototype.toggleSelected = function (name) {
      this[this.isSelected(name) ? 'unSelect' : 'select'](name);
    };

    GeoModel.prototype.isSelected = function (name) {
      var selectedMap = this.option.selectedMap;
      return !!(selectedMap && selectedMap[name]);
    };

    GeoModel.prototype._initSelectedMapFromData = function () {};

    GeoModel.type = 'geo';
    GeoModel.layoutMode = 'box';
    GeoModel.defaultOption = {
      zlevel: 0,
      z: 0,
      show: true,
      left: 'center',
      top: 'center',
      aspectScale: null,
      silent: false,
      map: '',
      boundingCoords: null,
      center: null,
      zoom: 1,
      scaleLimit: null,
      label: {
        show: false,
        color: '#000'
      },
      itemStyle: {
        borderWidth: 0.5,
        borderColor: '#444',
        color: '#eee'
      },
      emphasis: {
        label: {
          show: true,
          color: 'rgb(100,0,0)'
        },
        itemStyle: {
          color: 'rgba(255,215,0,0.8)'
        }
      },
      select: {
        label: {
          show: true,
          color: 'rgb(100,0,0)'
        },
        itemStyle: {
          color: 'rgba(255,215,0,0.8)'
        }
      },
      regions: []
    };
    return GeoModel;
  }(ComponentModel);

  ComponentModel.registerClass(GeoModel);

  function makeAction(method, actionInfo) {
    actionInfo.update = 'geo:updateSelectStatus';
    registerAction(actionInfo, function (payload, ecModel) {
      var selected = {};
      ecModel.eachComponent({
        mainType: 'geo',
        query: payload
      }, function (geoModel) {
        geoModel[method](payload.name);
        var geo = geoModel.coordinateSystem;
        each(geo.regions, function (region) {
          selected[region.name] = geoModel.isSelected(region.name) || false;
        });
      });
      return {
        selected: selected,
        name: payload.name
      };
    });
  }

  makeAction('toggleSelected', {
    type: 'geoToggleSelect',
    event: 'geoselectchanged'
  });
  makeAction('select', {
    type: 'geoSelect',
    event: 'geoselected'
  });
  makeAction('unSelect', {
    type: 'geoUnSelect',
    event: 'geounselected'
  });
  var PROXIMATE_ONE_DAY = 86400000;

  var Calendar = function () {
    function Calendar(calendarModel, ecModel, api) {
      this.type = 'calendar';
      this.dimensions = Calendar.dimensions;
      this.getDimensionsInfo = Calendar.getDimensionsInfo;
      this._model = calendarModel;
    }

    Calendar.getDimensionsInfo = function () {
      return [{
        name: 'time',
        type: 'time'
      }, 'value'];
    };

    Calendar.prototype.getRangeInfo = function () {
      return this._rangeInfo;
    };

    Calendar.prototype.getModel = function () {
      return this._model;
    };

    Calendar.prototype.getRect = function () {
      return this._rect;
    };

    Calendar.prototype.getCellWidth = function () {
      return this._sw;
    };

    Calendar.prototype.getCellHeight = function () {
      return this._sh;
    };

    Calendar.prototype.getOrient = function () {
      return this._orient;
    };

    Calendar.prototype.getFirstDayOfWeek = function () {
      return this._firstDayOfWeek;
    };

    Calendar.prototype.getDateInfo = function (date) {
      date = parseDate(date);
      var y = date.getFullYear();
      var m = date.getMonth() + 1;
      var mStr = m < 10 ? '0' + m : '' + m;
      var d = date.getDate();
      var dStr = d < 10 ? '0' + d : '' + d;
      var day = date.getDay();
      day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7);
      return {
        y: y + '',
        m: mStr,
        d: dStr,
        day: day,
        time: date.getTime(),
        formatedDate: y + '-' + mStr + '-' + dStr,
        date: date
      };
    };

    Calendar.prototype.getNextNDay = function (date, n) {
      n = n || 0;

      if (n === 0) {
        return this.getDateInfo(date);
      }

      date = new Date(this.getDateInfo(date).time);
      date.setDate(date.getDate() + n);
      return this.getDateInfo(date);
    };

    Calendar.prototype.update = function (ecModel, api) {
      this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay');
      this._orient = this._model.get('orient');
      this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0;
      this._rangeInfo = this._getRangeInfo(this._initRangeOption());
      var weeks = this._rangeInfo.weeks || 1;
      var whNames = ['width', 'height'];

      var cellSize = this._model.getCellSize().slice();

      var layoutParams = this._model.getBoxLayoutParams();

      var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks];
      each([0, 1], function (idx) {
        if (cellSizeSpecified(cellSize, idx)) {
          layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx];
        }
      });
      var whGlobal = {
        width: api.getWidth(),
        height: api.getHeight()
      };
      var calendarRect = this._rect = getLayoutRect(layoutParams, whGlobal);
      each([0, 1], function (idx) {
        if (!cellSizeSpecified(cellSize, idx)) {
          cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx];
        }
      });

      function cellSizeSpecified(cellSize, idx) {
        return cellSize[idx] != null && cellSize[idx] !== 'auto';
      }

      this._sw = cellSize[0];
      this._sh = cellSize[1];
    };

    Calendar.prototype.dataToPoint = function (data, clamp) {
      isArray(data) && (data = data[0]);
      clamp == null && (clamp = true);
      var dayInfo = this.getDateInfo(data);
      var range = this._rangeInfo;
      var date = dayInfo.formatedDate;

      if (clamp && !(dayInfo.time >= range.start.time && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY)) {
        return [NaN, NaN];
      }

      var week = dayInfo.day;

      var nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek;

      if (this._orient === 'vertical') {
        return [this._rect.x + week * this._sw + this._sw / 2, this._rect.y + nthWeek * this._sh + this._sh / 2];
      }

      return [this._rect.x + nthWeek * this._sw + this._sw / 2, this._rect.y + week * this._sh + this._sh / 2];
    };

    Calendar.prototype.pointToData = function (point) {
      var date = this.pointToDate(point);
      return date && date.time;
    };

    Calendar.prototype.dataToRect = function (data, clamp) {
      var point = this.dataToPoint(data, clamp);
      return {
        contentShape: {
          x: point[0] - (this._sw - this._lineWidth) / 2,
          y: point[1] - (this._sh - this._lineWidth) / 2,
          width: this._sw - this._lineWidth,
          height: this._sh - this._lineWidth
        },
        center: point,
        tl: [point[0] - this._sw / 2, point[1] - this._sh / 2],
        tr: [point[0] + this._sw / 2, point[1] - this._sh / 2],
        br: [point[0] + this._sw / 2, point[1] + this._sh / 2],
        bl: [point[0] - this._sw / 2, point[1] + this._sh / 2]
      };
    };

    Calendar.prototype.pointToDate = function (point) {
      var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1;
      var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1;
      var range = this._rangeInfo.range;

      if (this._orient === 'vertical') {
        return this._getDateByWeeksAndDay(nthY, nthX - 1, range);
      }

      return this._getDateByWeeksAndDay(nthX, nthY - 1, range);
    };

    Calendar.prototype.convertToPixel = function (ecModel, finder, value) {
      var coordSys = getCoordSys$4(finder);
      return coordSys === this ? coordSys.dataToPoint(value) : null;
    };

    Calendar.prototype.convertFromPixel = function (ecModel, finder, pixel) {
      var coordSys = getCoordSys$4(finder);
      return coordSys === this ? coordSys.pointToData(pixel) : null;
    };

    Calendar.prototype.containPoint = function (point) {
      console.warn('Not implemented.');
      return false;
    };

    Calendar.prototype._initRangeOption = function () {
      var range = this._model.get('range');

      var normalizedRange;

      if (isArray(range) && range.length === 1) {
        range = range[0];
      }

      if (!isArray(range)) {
        var rangeStr = range.toString();

        if (/^\d{4}$/.test(rangeStr)) {
          normalizedRange = [rangeStr + '-01-01', rangeStr + '-12-31'];
        }

        if (/^\d{4}[\/|-]\d{1,2}$/.test(rangeStr)) {
          var start = this.getDateInfo(rangeStr);
          var firstDay = start.date;
          firstDay.setMonth(firstDay.getMonth() + 1);
          var end = this.getNextNDay(firstDay, -1);
          normalizedRange = [start.formatedDate, end.formatedDate];
        }

        if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rangeStr)) {
          normalizedRange = [rangeStr, rangeStr];
        }
      } else {
        normalizedRange = range;
      }

      if (!normalizedRange) {
        if (true) {
          logError('Invalid date range.');
        }

        return range;
      }

      var tmp = this._getRangeInfo(normalizedRange);

      if (tmp.start.time > tmp.end.time) {
        normalizedRange.reverse();
      }

      return normalizedRange;
    };

    Calendar.prototype._getRangeInfo = function (range) {
      var parsedRange = [this.getDateInfo(range[0]), this.getDateInfo(range[1])];
      var reversed;

      if (parsedRange[0].time > parsedRange[1].time) {
        reversed = true;
        parsedRange.reverse();
      }

      var allDay = Math.floor(parsedRange[1].time / PROXIMATE_ONE_DAY) - Math.floor(parsedRange[0].time / PROXIMATE_ONE_DAY) + 1;
      var date = new Date(parsedRange[0].time);
      var startDateNum = date.getDate();
      var endDateNum = parsedRange[1].date.getDate();
      date.setDate(startDateNum + allDay - 1);
      var dateNum = date.getDate();

      if (dateNum !== endDateNum) {
        var sign = date.getTime() - parsedRange[1].time > 0 ? 1 : -1;

        while ((dateNum = date.getDate()) !== endDateNum && (date.getTime() - parsedRange[1].time) * sign > 0) {
          allDay -= sign;
          date.setDate(dateNum - sign);
        }
      }

      var weeks = Math.floor((allDay + parsedRange[0].day + 6) / 7);
      var nthWeek = reversed ? -weeks + 1 : weeks - 1;
      reversed && parsedRange.reverse();
      return {
        range: [parsedRange[0].formatedDate, parsedRange[1].formatedDate],
        start: parsedRange[0],
        end: parsedRange[1],
        allDay: allDay,
        weeks: weeks,
        nthWeek: nthWeek,
        fweek: parsedRange[0].day,
        lweek: parsedRange[1].day
      };
    };

    Calendar.prototype._getDateByWeeksAndDay = function (nthWeek, day, range) {
      var rangeInfo = this._getRangeInfo(range);

      if (nthWeek > rangeInfo.weeks || nthWeek === 0 && day < rangeInfo.fweek || nthWeek === rangeInfo.weeks && day > rangeInfo.lweek) {
        return null;
      }

      var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day;
      var date = new Date(rangeInfo.start.time);
      date.setDate(+rangeInfo.start.d + nthDay);
      return this.getDateInfo(date);
    };

    Calendar.create = function (ecModel, api) {
      var calendarList = [];
      ecModel.eachComponent('calendar', function (calendarModel) {
        var calendar = new Calendar(calendarModel, ecModel, api);
        calendarList.push(calendar);
        calendarModel.coordinateSystem = calendar;
      });
      ecModel.eachSeries(function (calendarSeries) {
        if (calendarSeries.get('coordinateSystem') === 'calendar') {
          calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
        }
      });
      return calendarList;
    };

    Calendar.dimensions = ['time', 'value'];
    return Calendar;
  }();

  function getCoordSys$4(finder) {
    var calendarModel = finder.calendarModel;
    var seriesModel = finder.seriesModel;
    var coordSys = calendarModel ? calendarModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem : null;
    return coordSys;
  }

  CoordinateSystemManager.register('calendar', Calendar);

  var CalendarModel = function (_super) {
    __extends(CalendarModel, _super);

    function CalendarModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CalendarModel.type;
      return _this;
    }

    CalendarModel.prototype.init = function (option, parentModel, ecModel) {
      var inputPositionParams = getLayoutParams(option);

      _super.prototype.init.apply(this, arguments);

      mergeAndNormalizeLayoutParams(option, inputPositionParams);
    };

    CalendarModel.prototype.mergeOption = function (option) {
      _super.prototype.mergeOption.apply(this, arguments);

      mergeAndNormalizeLayoutParams(this.option, option);
    };

    CalendarModel.prototype.getCellSize = function () {
      return this.option.cellSize;
    };

    CalendarModel.type = 'calendar';
    CalendarModel.defaultOption = {
      zlevel: 0,
      z: 2,
      left: 80,
      top: 60,
      cellSize: 20,
      orient: 'horizontal',
      splitLine: {
        show: true,
        lineStyle: {
          color: '#000',
          width: 1,
          type: 'solid'
        }
      },
      itemStyle: {
        color: '#fff',
        borderWidth: 1,
        borderColor: '#ccc'
      },
      dayLabel: {
        show: true,
        firstDay: 0,
        position: 'start',
        margin: '50%',
        nameMap: 'en',
        color: '#000'
      },
      monthLabel: {
        show: true,
        position: 'start',
        margin: 5,
        align: 'center',
        nameMap: 'en',
        formatter: null,
        color: '#000'
      },
      yearLabel: {
        show: true,
        position: null,
        margin: 30,
        formatter: null,
        color: '#ccc',
        fontFamily: 'sans-serif',
        fontWeight: 'bolder',
        fontSize: 20
      }
    };
    return CalendarModel;
  }(ComponentModel);

  function mergeAndNormalizeLayoutParams(target, raw) {
    var cellSize = target.cellSize;
    var cellSizeArr;

    if (!isArray(cellSize)) {
      cellSizeArr = target.cellSize = [cellSize, cellSize];
    } else {
      cellSizeArr = cellSize;
    }

    if (cellSizeArr.length === 1) {
      cellSizeArr[1] = cellSizeArr[0];
    }

    var ignoreSize = map([0, 1], function (hvIdx) {
      if (sizeCalculable(raw, hvIdx)) {
        cellSizeArr[hvIdx] = 'auto';
      }

      return cellSizeArr[hvIdx] != null && cellSizeArr[hvIdx] !== 'auto';
    });
    mergeLayoutParam(target, raw, {
      type: 'box',
      ignoreSize: ignoreSize
    });
  }

  ComponentModel.registerClass(CalendarModel);
  var MONTH_TEXT = {
    EN: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    CN: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
  };
  var WEEK_TEXT = {
    EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    CN: ['日', '一', '二', '三', '四', '五', '六']
  };

  var CalendarView = function (_super) {
    __extends(CalendarView, _super);

    function CalendarView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = CalendarView.type;
      return _this;
    }

    CalendarView.prototype.render = function (calendarModel, ecModel, api) {
      var group = this.group;
      group.removeAll();
      var coordSys = calendarModel.coordinateSystem;
      var rangeData = coordSys.getRangeInfo();
      var orient = coordSys.getOrient();

      this._renderDayRect(calendarModel, rangeData, group);

      this._renderLines(calendarModel, rangeData, orient, group);

      this._renderYearText(calendarModel, rangeData, orient, group);

      this._renderMonthText(calendarModel, orient, group);

      this._renderWeekText(calendarModel, rangeData, orient, group);
    };

    CalendarView.prototype._renderDayRect = function (calendarModel, rangeData, group) {
      var coordSys = calendarModel.coordinateSystem;
      var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle();
      var sw = coordSys.getCellWidth();
      var sh = coordSys.getCellHeight();

      for (var i = rangeData.start.time; i <= rangeData.end.time; i = coordSys.getNextNDay(i, 1).time) {
        var point = coordSys.dataToRect([i], false).tl;
        var rect = new Rect({
          shape: {
            x: point[0],
            y: point[1],
            width: sw,
            height: sh
          },
          cursor: 'default',
          style: itemRectStyleModel
        });
        group.add(rect);
      }
    };

    CalendarView.prototype._renderLines = function (calendarModel, rangeData, orient, group) {
      var self = this;
      var coordSys = calendarModel.coordinateSystem;
      var lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle();
      var show = calendarModel.get(['splitLine', 'show']);
      var lineWidth = lineStyleModel.lineWidth;
      this._tlpoints = [];
      this._blpoints = [];
      this._firstDayOfMonth = [];
      this._firstDayPoints = [];
      var firstDay = rangeData.start;

      for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
        addPoints(firstDay.formatedDate);

        if (i === 0) {
          firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
        }

        var date = firstDay.date;
        date.setMonth(date.getMonth() + 1);
        firstDay = coordSys.getDateInfo(date);
      }

      addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);

      function addPoints(date) {
        self._firstDayOfMonth.push(coordSys.getDateInfo(date));

        self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);

        var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);

        self._tlpoints.push(points[0]);

        self._blpoints.push(points[points.length - 1]);

        show && self._drawSplitline(points, lineStyleModel, group);
      }

      show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);
      show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);
    };

    CalendarView.prototype._getEdgesPoints = function (points, lineWidth, orient) {
      var rs = [points[0].slice(), points[points.length - 1].slice()];
      var idx = orient === 'horizontal' ? 0 : 1;
      rs[0][idx] = rs[0][idx] - lineWidth / 2;
      rs[1][idx] = rs[1][idx] + lineWidth / 2;
      return rs;
    };

    CalendarView.prototype._drawSplitline = function (points, lineStyle, group) {
      var poyline = new Polyline({
        z2: 20,
        shape: {
          points: points
        },
        style: lineStyle
      });
      group.add(poyline);
    };

    CalendarView.prototype._getLinePointsOfOneWeek = function (calendarModel, date, orient) {
      var coordSys = calendarModel.coordinateSystem;
      var parsedDate = coordSys.getDateInfo(date);
      var points = [];

      for (var i = 0; i < 7; i++) {
        var tmpD = coordSys.getNextNDay(parsedDate.time, i);
        var point = coordSys.dataToRect([tmpD.time], false);
        points[2 * tmpD.day] = point.tl;
        points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
      }

      return points;
    };

    CalendarView.prototype._formatterLabel = function (formatter, params) {
      if (typeof formatter === 'string' && formatter) {
        return formatTplSimple(formatter, params);
      }

      if (typeof formatter === 'function') {
        return formatter(params);
      }

      return params.nameMap;
    };

    CalendarView.prototype._yearTextPositionControl = function (textEl, point, orient, position, margin) {
      var x = point[0];
      var y = point[1];
      var aligns = ['center', 'bottom'];

      if (position === 'bottom') {
        y += margin;
        aligns = ['center', 'top'];
      } else if (position === 'left') {
        x -= margin;
      } else if (position === 'right') {
        x += margin;
        aligns = ['center', 'top'];
      } else {
        y -= margin;
      }

      var rotate = 0;

      if (position === 'left' || position === 'right') {
        rotate = Math.PI / 2;
      }

      return {
        rotation: rotate,
        x: x,
        y: y,
        style: {
          align: aligns[0],
          verticalAlign: aligns[1]
        }
      };
    };

    CalendarView.prototype._renderYearText = function (calendarModel, rangeData, orient, group) {
      var yearLabel = calendarModel.getModel('yearLabel');

      if (!yearLabel.get('show')) {
        return;
      }

      var margin = yearLabel.get('margin');
      var pos = yearLabel.get('position');

      if (!pos) {
        pos = orient !== 'horizontal' ? 'top' : 'left';
      }

      var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
      var xc = (points[0][0] + points[1][0]) / 2;
      var yc = (points[0][1] + points[1][1]) / 2;
      var idx = orient === 'horizontal' ? 0 : 1;
      var posPoints = {
        top: [xc, points[idx][1]],
        bottom: [xc, points[1 - idx][1]],
        left: [points[1 - idx][0], yc],
        right: [points[idx][0], yc]
      };
      var name = rangeData.start.y;

      if (+rangeData.end.y > +rangeData.start.y) {
        name = name + '-' + rangeData.end.y;
      }

      var formatter = yearLabel.get('formatter');
      var params = {
        start: rangeData.start.y,
        end: rangeData.end.y,
        nameMap: name
      };

      var content = this._formatterLabel(formatter, params);

      var yearText = new ZRText({
        z2: 30,
        style: createTextStyle(yearLabel, {
          text: content
        })
      });
      yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));
      group.add(yearText);
    };

    CalendarView.prototype._monthTextPositionControl = function (point, isCenter, orient, position, margin) {
      var align = 'left';
      var vAlign = 'top';
      var x = point[0];
      var y = point[1];

      if (orient === 'horizontal') {
        y = y + margin;

        if (isCenter) {
          align = 'center';
        }

        if (position === 'start') {
          vAlign = 'bottom';
        }
      } else {
        x = x + margin;

        if (isCenter) {
          vAlign = 'middle';
        }

        if (position === 'start') {
          align = 'right';
        }
      }

      return {
        x: x,
        y: y,
        align: align,
        verticalAlign: vAlign
      };
    };

    CalendarView.prototype._renderMonthText = function (calendarModel, orient, group) {
      var monthLabel = calendarModel.getModel('monthLabel');

      if (!monthLabel.get('show')) {
        return;
      }

      var nameMap = monthLabel.get('nameMap');
      var margin = monthLabel.get('margin');
      var pos = monthLabel.get('position');
      var align = monthLabel.get('align');
      var termPoints = [this._tlpoints, this._blpoints];

      if (isString(nameMap)) {
        nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
      }

      var idx = pos === 'start' ? 0 : 1;
      var axis = orient === 'horizontal' ? 0 : 1;
      margin = pos === 'start' ? -margin : margin;
      var isCenter = align === 'center';

      for (var i = 0; i < termPoints[idx].length - 1; i++) {
        var tmp = termPoints[idx][i].slice();
        var firstDay = this._firstDayOfMonth[i];

        if (isCenter) {
          var firstDayPoints = this._firstDayPoints[i];
          tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
        }

        var formatter = monthLabel.get('formatter');
        var name_1 = nameMap[+firstDay.m - 1];
        var params = {
          yyyy: firstDay.y,
          yy: (firstDay.y + '').slice(2),
          MM: firstDay.m,
          M: +firstDay.m,
          nameMap: name_1
        };

        var content = this._formatterLabel(formatter, params);

        var monthText = new ZRText({
          z2: 30,
          style: extend(createTextStyle(monthLabel, {
            text: content
          }), this._monthTextPositionControl(tmp, isCenter, orient, pos, margin))
        });
        group.add(monthText);
      }
    };

    CalendarView.prototype._weekTextPositionControl = function (point, orient, position, margin, cellSize) {
      var align = 'center';
      var vAlign = 'middle';
      var x = point[0];
      var y = point[1];
      var isStart = position === 'start';

      if (orient === 'horizontal') {
        x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
        align = isStart ? 'right' : 'left';
      } else {
        y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
        vAlign = isStart ? 'bottom' : 'top';
      }

      return {
        x: x,
        y: y,
        align: align,
        verticalAlign: vAlign
      };
    };

    CalendarView.prototype._renderWeekText = function (calendarModel, rangeData, orient, group) {
      var dayLabel = calendarModel.getModel('dayLabel');

      if (!dayLabel.get('show')) {
        return;
      }

      var coordSys = calendarModel.coordinateSystem;
      var pos = dayLabel.get('position');
      var nameMap = dayLabel.get('nameMap');
      var margin = dayLabel.get('margin');
      var firstDayOfWeek = coordSys.getFirstDayOfWeek();

      if (isString(nameMap)) {
        nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
      }

      var start = coordSys.getNextNDay(rangeData.end.time, 7 - rangeData.lweek).time;
      var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
      margin = parsePercent$2(margin, cellSize[orient === 'horizontal' ? 0 : 1]);

      if (pos === 'start') {
        start = coordSys.getNextNDay(rangeData.start.time, -(7 + rangeData.fweek)).time;
        margin = -margin;
      }

      for (var i = 0; i < 7; i++) {
        var tmpD = coordSys.getNextNDay(start, i);
        var point = coordSys.dataToRect([tmpD.time], false).center;
        var day = i;
        day = Math.abs((i + firstDayOfWeek) % 7);
        var weekText = new ZRText({
          z2: 30,
          style: extend(createTextStyle(dayLabel, {
            text: nameMap[day]
          }), this._weekTextPositionControl(point, orient, pos, margin, cellSize))
        });
        group.add(weekText);
      }
    };

    CalendarView.type = 'calendar';
    return CalendarView;
  }(ComponentView);

  ComponentView.registerClass(CalendarView);
  var inner$g = makeInner();
  var _nonShapeGraphicElements = {
    path: null,
    compoundPath: null,
    group: Group,
    image: ZRImage,
    text: ZRText
  };
  registerPreprocessor(function (option) {
    var graphicOption = option.graphic;

    if (isArray(graphicOption)) {
      if (!graphicOption[0] || !graphicOption[0].elements) {
        option.graphic = [{
          elements: graphicOption
        }];
      } else {
        option.graphic = [option.graphic[0]];
      }
    } else if (graphicOption && !graphicOption.elements) {
      option.graphic = [{
        elements: [graphicOption]
      }];
    }
  });

  var GraphicComponentModel = function (_super) {
    __extends(GraphicComponentModel, _super);

    function GraphicComponentModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GraphicComponentModel.type;
      return _this;
    }

    GraphicComponentModel.prototype.mergeOption = function (option, ecModel) {
      var elements = this.option.elements;
      this.option.elements = null;

      _super.prototype.mergeOption.call(this, option, ecModel);

      this.option.elements = elements;
    };

    GraphicComponentModel.prototype.optionUpdated = function (newOption, isInit) {
      var thisOption = this.option;
      var newList = (isInit ? thisOption : newOption).elements;
      var existList = thisOption.elements = isInit ? [] : thisOption.elements;
      var flattenedList = [];

      this._flatten(newList, flattenedList, null);

      var mappingResult = mappingToExists(existList, flattenedList, 'normalMerge');
      var elOptionsToUpdate = this._elOptionsToUpdate = [];
      each(mappingResult, function (resultItem, index) {
        var newElOption = resultItem.newOption;

        if (true) {
          assert(isObject(newElOption) || resultItem.existing, 'Empty graphic option definition');
        }

        if (!newElOption) {
          return;
        }

        elOptionsToUpdate.push(newElOption);
        setKeyInfoToNewElOption(resultItem, newElOption);
        mergeNewElOptionToExist(existList, index, newElOption);
        setLayoutInfoToExist(existList[index], newElOption);
      }, this);

      for (var i = existList.length - 1; i >= 0; i--) {
        if (existList[i] == null) {
          existList.splice(i, 1);
        } else {
          delete existList[i].$action;
        }
      }
    };

    GraphicComponentModel.prototype._flatten = function (optionList, result, parentOption) {
      each(optionList, function (option) {
        if (!option) {
          return;
        }

        if (parentOption) {
          option.parentOption = parentOption;
        }

        result.push(option);
        var children = option.children;

        if (option.type === 'group' && children) {
          this._flatten(children, result, option);
        }

        delete option.children;
      }, this);
    };

    GraphicComponentModel.prototype.useElOptionsToUpdate = function () {
      var els = this._elOptionsToUpdate;
      this._elOptionsToUpdate = null;
      return els;
    };

    GraphicComponentModel.type = 'graphic';
    GraphicComponentModel.defaultOption = {
      elements: []
    };
    return GraphicComponentModel;
  }(ComponentModel);

  ComponentModel.registerClass(GraphicComponentModel);

  var GraphicComponentView = function (_super) {
    __extends(GraphicComponentView, _super);

    function GraphicComponentView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = GraphicComponentView.type;
      return _this;
    }

    GraphicComponentView.prototype.init = function () {
      this._elMap = createHashMap();
    };

    GraphicComponentView.prototype.render = function (graphicModel, ecModel, api) {
      if (graphicModel !== this._lastGraphicModel) {
        this._clear();
      }

      this._lastGraphicModel = graphicModel;

      this._updateElements(graphicModel);

      this._relocate(graphicModel, api);
    };

    GraphicComponentView.prototype._updateElements = function (graphicModel) {
      var elOptionsToUpdate = graphicModel.useElOptionsToUpdate();

      if (!elOptionsToUpdate) {
        return;
      }

      var elMap = this._elMap;
      var rootGroup = this.group;
      each(elOptionsToUpdate, function (elOption) {
        var id = convertOptionIdName(elOption.id, null);
        var elExisting = id != null ? elMap.get(id) : null;
        var parentId = convertOptionIdName(elOption.parentId, null);
        var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup;
        var elType = elOption.type;
        var elOptionStyle = elOption.style;

        if (elType === 'text' && elOptionStyle) {
          if (elOption.hv && elOption.hv[1]) {
            elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = elOptionStyle.verticalAlign = elOptionStyle.align = null;
          }
        }

        var textContentOption = elOption.textContent;
        var textConfig = elOption.textConfig;

        if (elOptionStyle && isEC4CompatibleStyle(elOptionStyle, elType, !!textConfig, !!textContentOption)) {
          var convertResult = convertFromEC4CompatibleStyle(elOptionStyle, elType, true);

          if (!textConfig && convertResult.textConfig) {
            textConfig = elOption.textConfig = convertResult.textConfig;
          }

          if (!textContentOption && convertResult.textContent) {
            textContentOption = convertResult.textContent;
          }
        }

        var elOptionCleaned = getCleanedElOption(elOption);

        if (true) {
          elExisting && assert(targetElParent === elExisting.parent, 'Changing parent is not supported.');
        }

        var $action = elOption.$action || 'merge';

        if ($action === 'merge') {
          elExisting ? elExisting.attr(elOptionCleaned) : createEl$1(id, targetElParent, elOptionCleaned, elMap);
        } else if ($action === 'replace') {
          removeEl(elExisting, elMap);
          createEl$1(id, targetElParent, elOptionCleaned, elMap);
        } else if ($action === 'remove') {
          removeEl(elExisting, elMap);
        }

        var el = elMap.get(id);

        if (el && textContentOption) {
          if ($action === 'merge') {
            var textContentExisting = el.getTextContent();
            textContentExisting ? textContentExisting.attr(textContentOption) : el.setTextContent(new ZRText(textContentOption));
          } else if ($action === 'replace') {
            el.setTextContent(new ZRText(textContentOption));
          }
        }

        if (el) {
          var elInner = inner$g(el);
          elInner.__ecGraphicWidthOption = elOption.width;
          elInner.__ecGraphicHeightOption = elOption.height;
          setEventData(el, graphicModel, elOption);
        }
      });
    };

    GraphicComponentView.prototype._relocate = function (graphicModel, api) {
      var elOptions = graphicModel.option.elements;
      var rootGroup = this.group;
      var elMap = this._elMap;
      var apiWidth = api.getWidth();
      var apiHeight = api.getHeight();

      for (var i = 0; i < elOptions.length; i++) {
        var elOption = elOptions[i];
        var id = convertOptionIdName(elOption.id, null);
        var el = id != null ? elMap.get(id) : null;

        if (!el || !el.isGroup) {
          continue;
        }

        var parentEl = el.parent;
        var isParentRoot = parentEl === rootGroup;
        var elInner = inner$g(el);
        var parentElInner = inner$g(parentEl);
        elInner.__ecGraphicWidth = parsePercent$2(elInner.__ecGraphicWidthOption, isParentRoot ? apiWidth : parentElInner.__ecGraphicWidth) || 0;
        elInner.__ecGraphicHeight = parsePercent$2(elInner.__ecGraphicHeightOption, isParentRoot ? apiHeight : parentElInner.__ecGraphicHeight) || 0;
      }

      for (var i = elOptions.length - 1; i >= 0; i--) {
        var elOption = elOptions[i];
        var id = convertOptionIdName(elOption.id, null);
        var el = id != null ? elMap.get(id) : null;

        if (!el) {
          continue;
        }

        var parentEl = el.parent;
        var parentElInner = inner$g(parentEl);
        var containerInfo = parentEl === rootGroup ? {
          width: apiWidth,
          height: apiHeight
        } : {
          width: parentElInner.__ecGraphicWidth,
          height: parentElInner.__ecGraphicHeight
        };
        positionElement(el, elOption, containerInfo, null, {
          hv: elOption.hv,
          boundingMode: elOption.bounding
        });
      }
    };

    GraphicComponentView.prototype._clear = function () {
      var elMap = this._elMap;
      elMap.each(function (el) {
        removeEl(el, elMap);
      });
      this._elMap = createHashMap();
    };

    GraphicComponentView.prototype.dispose = function () {
      this._clear();
    };

    GraphicComponentView.type = 'graphic';
    return GraphicComponentView;
  }(ComponentView);

  ComponentView.registerClass(GraphicComponentView);

  function createEl$1(id, targetElParent, elOption, elMap) {
    var graphicType = elOption.type;

    if (true) {
      assert(graphicType, 'graphic type MUST be set');
    }

    var Clz = hasOwn(_nonShapeGraphicElements, graphicType) ? _nonShapeGraphicElements[graphicType] : getShapeClass(graphicType);

    if (true) {
      assert(Clz, 'graphic type can not be found');
    }

    var el = new Clz(elOption);
    targetElParent.add(el);
    elMap.set(id, el);
    inner$g(el).__ecGraphicId = id;
  }

  function removeEl(elExisting, elMap) {
    var existElParent = elExisting && elExisting.parent;

    if (existElParent) {
      elExisting.type === 'group' && elExisting.traverse(function (el) {
        removeEl(el, elMap);
      });
      elMap.removeKey(inner$g(elExisting).__ecGraphicId);
      existElParent.remove(elExisting);
    }
  }

  function getCleanedElOption(elOption) {
    elOption = extend({}, elOption);
    each(['id', 'parentId', '$action', 'hv', 'bounding', 'textContent'].concat(LOCATION_PARAMS), function (name) {
      delete elOption[name];
    });
    return elOption;
  }

  function isSetLoc(obj, props) {
    var isSet;
    each(props, function (prop) {
      obj[prop] != null && obj[prop] !== 'auto' && (isSet = true);
    });
    return isSet;
  }

  function setKeyInfoToNewElOption(resultItem, newElOption) {
    var existElOption = resultItem.existing;
    newElOption.id = resultItem.keyInfo.id;
    !newElOption.type && existElOption && (newElOption.type = existElOption.type);

    if (newElOption.parentId == null) {
      var newElParentOption = newElOption.parentOption;

      if (newElParentOption) {
        newElOption.parentId = newElParentOption.id;
      } else if (existElOption) {
        newElOption.parentId = existElOption.parentId;
      }
    }

    newElOption.parentOption = null;
  }

  function mergeNewElOptionToExist(existList, index, newElOption) {
    var newElOptCopy = extend({}, newElOption);
    var existElOption = existList[index];
    var $action = newElOption.$action || 'merge';

    if ($action === 'merge') {
      if (existElOption) {
        if (true) {
          var newType = newElOption.type;
          assert(!newType || existElOption.type === newType, 'Please set $action: "replace" to change `type`');
        }

        merge(existElOption, newElOptCopy, true);
        mergeLayoutParam(existElOption, newElOptCopy, {
          ignoreSize: true
        });
        copyLayoutParams(newElOption, existElOption);
      } else {
        existList[index] = newElOptCopy;
      }
    } else if ($action === 'replace') {
      existList[index] = newElOptCopy;
    } else if ($action === 'remove') {
      existElOption && (existList[index] = null);
    }
  }

  function setLayoutInfoToExist(existItem, newElOption) {
    if (!existItem) {
      return;
    }

    existItem.hv = newElOption.hv = [isSetLoc(newElOption, ['left', 'right']), isSetLoc(newElOption, ['top', 'bottom'])];

    if (existItem.type === 'group') {
      var existingGroupOpt = existItem;
      var newGroupOpt = newElOption;
      existingGroupOpt.width == null && (existingGroupOpt.width = newGroupOpt.width = 0);
      existingGroupOpt.height == null && (existingGroupOpt.height = newGroupOpt.height = 0);
    }
  }

  function setEventData(el, graphicModel, elOption) {
    var eventData = getECData(el).eventData;

    if (!el.silent && !el.ignore && !eventData) {
      eventData = getECData(el).eventData = {
        componentType: 'graphic',
        componentIndex: graphicModel.componentIndex,
        name: el.name
      };
    }

    if (eventData) {
      eventData.info = elOption.info;
    }
  }

  var ToolboxFeature = function () {
    function ToolboxFeature() {}

    return ToolboxFeature;
  }();

  var features = {};

  function registerFeature(name, ctor) {
    features[name] = ctor;
  }

  function getFeature(name) {
    return features[name];
  }

  var ToolboxModel = function (_super) {
    __extends(ToolboxModel, _super);

    function ToolboxModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ToolboxModel.type;
      return _this;
    }

    ToolboxModel.prototype.optionUpdated = function () {
      _super.prototype.optionUpdated.apply(this, arguments);

      var ecModel = this.ecModel;
      each(this.option.feature, function (featureOpt, featureName) {
        var Feature = getFeature(featureName);

        if (Feature) {
          if (Feature.getDefaultOption) {
            Feature.defaultOption = Feature.getDefaultOption(ecModel);
          }

          merge(featureOpt, Feature.defaultOption);
        }
      });
    };

    ToolboxModel.type = 'toolbox';
    ToolboxModel.layoutMode = {
      type: 'box',
      ignoreSize: true
    };
    ToolboxModel.defaultOption = {
      show: true,
      z: 6,
      zlevel: 0,
      orient: 'horizontal',
      left: 'right',
      top: 'top',
      backgroundColor: 'transparent',
      borderColor: '#ccc',
      borderRadius: 0,
      borderWidth: 0,
      padding: 5,
      itemSize: 15,
      itemGap: 8,
      showTitle: true,
      iconStyle: {
        borderColor: '#666',
        color: 'none'
      },
      emphasis: {
        iconStyle: {
          borderColor: '#3E98C5'
        }
      },
      tooltip: {
        show: false
      }
    };
    return ToolboxModel;
  }(ComponentModel);

  ComponentModel.registerClass(ToolboxModel);

  function layout$3(group, componentModel, api) {
    var boxLayoutParams = componentModel.getBoxLayoutParams();
    var padding = componentModel.get('padding');
    var viewportSize = {
      width: api.getWidth(),
      height: api.getHeight()
    };
    var rect = getLayoutRect(boxLayoutParams, viewportSize, padding);
    box(componentModel.get('orient'), group, componentModel.get('itemGap'), rect.width, rect.height);
    positionElement(group, boxLayoutParams, viewportSize, padding);
  }

  function makeBackground(rect, componentModel) {
    var padding = normalizeCssArray$1(componentModel.get('padding'));
    var style = componentModel.getItemStyle(['color', 'opacity']);
    style.fill = componentModel.get('backgroundColor');
    rect = new Rect({
      shape: {
        x: rect.x - padding[3],
        y: rect.y - padding[0],
        width: rect.width + padding[1] + padding[3],
        height: rect.height + padding[0] + padding[2],
        r: componentModel.get('borderRadius')
      },
      style: style,
      silent: true,
      z2: -1
    });
    return rect;
  }

  var ToolboxView = function (_super) {
    __extends(ToolboxView, _super);

    function ToolboxView() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    ToolboxView.prototype.render = function (toolboxModel, ecModel, api, payload) {
      var group = this.group;
      group.removeAll();

      if (!toolboxModel.get('show')) {
        return;
      }

      var itemSize = +toolboxModel.get('itemSize');
      var featureOpts = toolboxModel.get('feature') || {};
      var features = this._features || (this._features = {});
      var featureNames = [];
      each(featureOpts, function (opt, name) {
        featureNames.push(name);
      });
      new DataDiffer(this._featureNames || [], featureNames).add(processFeature).update(processFeature).remove(curry(processFeature, null)).execute();
      this._featureNames = featureNames;

      function processFeature(newIndex, oldIndex) {
        var featureName = featureNames[newIndex];
        var oldName = featureNames[oldIndex];
        var featureOpt = featureOpts[featureName];
        var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
        var feature;

        if (payload && payload.newTitle != null && payload.featureName === featureName) {
          featureOpt.title = payload.newTitle;
        }

        if (featureName && !oldName) {
          if (isUserFeatureName(featureName)) {
            feature = {
              onclick: featureModel.option.onclick,
              featureName: featureName
            };
          } else {
            var Feature = getFeature(featureName);

            if (!Feature) {
              return;
            }

            feature = new Feature();
          }

          features[featureName] = feature;
        } else {
          feature = features[oldName];

          if (!feature) {
            return;
          }
        }

        feature.uid = getUID('toolbox-feature');
        feature.model = featureModel;
        feature.ecModel = ecModel;
        feature.api = api;

        if (feature instanceof ToolboxFeature) {
          if (!featureName && oldName) {
            feature.dispose && feature.dispose(ecModel, api);
            return;
          }

          if (!featureModel.get('show') || feature.unusable) {
            feature.remove && feature.remove(ecModel, api);
            return;
          }
        }

        createIconPaths(featureModel, feature, featureName);

        featureModel.setIconStatus = function (iconName, status) {
          var option = this.option;
          var iconPaths = this.iconPaths;
          option.iconStatus = option.iconStatus || {};
          option.iconStatus[iconName] = status;

          if (iconPaths[iconName]) {
            (status === 'emphasis' ? enterEmphasis : leaveEmphasis)(iconPaths[iconName]);
          }
        };

        if (feature instanceof ToolboxFeature) {
          if (feature.render) {
            feature.render(featureModel, ecModel, api, payload);
          }
        }
      }

      function createIconPaths(featureModel, feature, featureName) {
        var iconStyleModel = featureModel.getModel('iconStyle');
        var iconStyleEmphasisModel = featureModel.getModel(['emphasis', 'iconStyle']);
        var icons = feature instanceof ToolboxFeature && feature.getIcons ? feature.getIcons() : featureModel.get('icon');
        var titles = featureModel.get('title') || {};
        var iconsMap;
        var titlesMap;

        if (typeof icons === 'string') {
          iconsMap = {};
          iconsMap[featureName] = icons;
        } else {
          iconsMap = icons;
        }

        if (typeof titles === 'string') {
          titlesMap = {};
          titlesMap[featureName] = titles;
        } else {
          titlesMap = titles;
        }

        var iconPaths = featureModel.iconPaths = {};
        each(iconsMap, function (iconStr, iconName) {
          var path = createIcon(iconStr, {}, {
            x: -itemSize / 2,
            y: -itemSize / 2,
            width: itemSize,
            height: itemSize
          });
          path.setStyle(iconStyleModel.getItemStyle());
          var pathEmphasisState = path.ensureState('emphasis');
          pathEmphasisState.style = iconStyleEmphasisModel.getItemStyle();
          var textContent = new ZRText({
            style: {
              text: titlesMap[iconName],
              align: iconStyleEmphasisModel.get('textAlign'),
              borderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
              padding: iconStyleEmphasisModel.get('textPadding'),
              fill: null
            },
            ignore: true
          });
          path.setTextContent(textContent);
          var tooltipModel = toolboxModel.getModel('tooltip');

          if (tooltipModel && tooltipModel.get('show')) {
            path.tooltip = extend({
              content: titlesMap[iconName],
              formatter: tooltipModel.get('formatter', true) || function () {
                return titlesMap[iconName];
              },
              formatterParams: {
                componentType: 'toolbox',
                name: iconName,
                title: titlesMap[iconName],
                $vars: ['name', 'title']
              },
              position: tooltipModel.get('position', true) || 'bottom'
            }, tooltipModel.option);
          }

          path.__title = titlesMap[iconName];
          path.on('mouseover', function () {
            var hoverStyle = iconStyleEmphasisModel.getItemStyle();
            var defaultTextPosition = toolboxModel.get('orient') === 'vertical' ? toolboxModel.get('right') == null ? 'right' : 'left' : toolboxModel.get('bottom') == null ? 'bottom' : 'top';
            textContent.setStyle({
              fill: iconStyleEmphasisModel.get('textFill') || hoverStyle.fill || hoverStyle.stroke || '#000',
              backgroundColor: iconStyleEmphasisModel.get('textBackgroundColor')
            });
            path.setTextConfig({
              position: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition
            });
            textContent.ignore = !toolboxModel.get('showTitle');
            enterEmphasis(this);
          }).on('mouseout', function () {
            if (featureModel.get(['iconStatus', iconName]) !== 'emphasis') {
              leaveEmphasis(this);
            }

            textContent.hide();
          });
          (featureModel.get(['iconStatus', iconName]) === 'emphasis' ? enterEmphasis : leaveEmphasis)(path);
          group.add(path);
          path.on('click', bind(feature.onclick, feature, ecModel, api, iconName));
          iconPaths[iconName] = path;
        });
      }

      layout$3(group, toolboxModel, api);
      group.add(makeBackground(group.getBoundingRect(), toolboxModel));
      group.eachChild(function (icon) {
        var titleText = icon.__title;
        var emphasisState = icon.ensureState('emphasis');
        var emphasisTextConfig = emphasisState.textConfig || (emphasisState.textConfig = {});
        var textContent = icon.getTextContent();
        var emphasisTextState = textContent && textContent.states.emphasis;

        if (emphasisTextState && !isFunction(emphasisTextState) && titleText) {
          var emphasisTextStyle = emphasisTextState.style || (emphasisTextState.style = {});
          var rect = getBoundingRect(titleText, ZRText.makeFont(emphasisTextStyle));
          var offsetX = icon.x + group.x;
          var offsetY = icon.y + group.y + itemSize;
          var needPutOnTop = false;

          if (offsetY + rect.height > api.getHeight()) {
            emphasisTextConfig.position = 'top';
            needPutOnTop = true;
          }

          var topOffset = needPutOnTop ? -5 - rect.height : itemSize + 8;

          if (offsetX + rect.width / 2 > api.getWidth()) {
            emphasisTextConfig.position = ['100%', topOffset];
            emphasisTextStyle.align = 'right';
          } else if (offsetX - rect.width / 2 < 0) {
            emphasisTextConfig.position = [0, topOffset];
            emphasisTextStyle.align = 'left';
          }
        }
      });
    };

    ToolboxView.prototype.updateView = function (toolboxModel, ecModel, api, payload) {
      each(this._features, function (feature) {
        feature instanceof ToolboxFeature && feature.updateView && feature.updateView(feature.model, ecModel, api, payload);
      });
    };

    ToolboxView.prototype.remove = function (ecModel, api) {
      each(this._features, function (feature) {
        feature instanceof ToolboxFeature && feature.remove && feature.remove(ecModel, api);
      });
      this.group.removeAll();
    };

    ToolboxView.prototype.dispose = function (ecModel, api) {
      each(this._features, function (feature) {
        feature instanceof ToolboxFeature && feature.dispose && feature.dispose(ecModel, api);
      });
    };

    ToolboxView.type = 'toolbox';
    return ToolboxView;
  }(ComponentView);

  ComponentView.registerClass(ToolboxView);

  function isUserFeatureName(featureName) {
    return featureName.indexOf('my') === 0;
  }

  var SaveAsImage = function (_super) {
    __extends(SaveAsImage, _super);

    function SaveAsImage() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    SaveAsImage.prototype.onclick = function (ecModel, api) {
      var model = this.model;
      var title = model.get('name') || ecModel.get('title.0.text') || 'echarts';
      var isSvg = api.getZr().painter.getType() === 'svg';
      var type = isSvg ? 'svg' : model.get('type', true) || 'png';
      var url = api.getConnectedDataURL({
        type: type,
        backgroundColor: model.get('backgroundColor', true) || ecModel.get('backgroundColor') || '#fff',
        connectedBackgroundColor: model.get('connectedBackgroundColor'),
        excludeComponents: model.get('excludeComponents'),
        pixelRatio: model.get('pixelRatio')
      });

      if (typeof MouseEvent === 'function' && !env.browser.ie && !env.browser.edge) {
        var $a = document.createElement('a');
        $a.download = title + '.' + type;
        $a.target = '_blank';
        $a.href = url;
        var evt = new MouseEvent('click', {
          view: document.defaultView,
          bubbles: true,
          cancelable: false
        });
        $a.dispatchEvent(evt);
      } else {
        if (window.navigator.msSaveOrOpenBlob) {
          var bstr = atob(url.split(',')[1]);
          var n = bstr.length;
          var u8arr = new Uint8Array(n);

          while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
          }

          var blob = new Blob([u8arr]);
          window.navigator.msSaveOrOpenBlob(blob, title + '.' + type);
        } else {
          var lang = model.get('lang');
          var html = '' + '<body style="margin:0;">' + '<img src="' + url + '" style="max-width:100%;" title="' + (lang && lang[0] || '') + '" />' + '</body>';
          var tab = window.open();
          tab.document.write(html);
        }
      }
    };

    SaveAsImage.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0',
        title: ecModel.getLocale(['toolbox', 'saveAsImage', 'title']),
        type: 'png',
        connectedBackgroundColor: '#fff',
        name: '',
        excludeComponents: ['toolbox'],
        pixelRatio: 1,
        lang: ecModel.getLocale(['toolbox', 'saveAsImage', 'lang'])
      };
      return defaultOption;
    };

    return SaveAsImage;
  }(ToolboxFeature);

  SaveAsImage.prototype.unusable = !env.canvasSupported;
  registerFeature('saveAsImage', SaveAsImage);
  var INNER_STACK_KEYWORD = '__ec_magicType_stack__';
  var radioTypes = [['line', 'bar'], ['stack']];

  var MagicType = function (_super) {
    __extends(MagicType, _super);

    function MagicType() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    MagicType.prototype.getIcons = function () {
      var model = this.model;
      var availableIcons = model.get('icon');
      var icons = {};
      each(model.get('type'), function (type) {
        if (availableIcons[type]) {
          icons[type] = availableIcons[type];
        }
      });
      return icons;
    };

    MagicType.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        type: [],
        icon: {
          line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
          bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
          stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z'
        },
        title: ecModel.getLocale(['toolbox', 'magicType', 'title']),
        option: {},
        seriesIndex: {}
      };
      return defaultOption;
    };

    MagicType.prototype.onclick = function (ecModel, api, type) {
      var model = this.model;
      var seriesIndex = model.get(['seriesIndex', type]);

      if (!seriesOptGenreator[type]) {
        return;
      }

      var newOption = {
        series: []
      };

      var generateNewSeriesTypes = function (seriesModel) {
        var seriesType = seriesModel.subType;
        var seriesId = seriesModel.id;
        var newSeriesOpt = seriesOptGenreator[type](seriesType, seriesId, seriesModel, model);

        if (newSeriesOpt) {
          defaults(newSeriesOpt, seriesModel.option);
          newOption.series.push(newSeriesOpt);
        }

        var coordSys = seriesModel.coordinateSystem;

        if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) {
          var categoryAxis = coordSys.getAxesByScale('ordinal')[0];

          if (categoryAxis) {
            var axisDim = categoryAxis.dim;
            var axisType = axisDim + 'Axis';
            var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0];
            var axisIndex = axisModel.componentIndex;
            newOption[axisType] = newOption[axisType] || [];

            for (var i = 0; i <= axisIndex; i++) {
              newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {};
            }

            newOption[axisType][axisIndex].boundaryGap = type === 'bar';
          }
        }
      };

      each(radioTypes, function (radio) {
        if (indexOf(radio, type) >= 0) {
          each(radio, function (item) {
            model.setIconStatus(item, 'normal');
          });
        }
      });
      model.setIconStatus(type, 'emphasis');
      ecModel.eachComponent({
        mainType: 'series',
        query: seriesIndex == null ? null : {
          seriesIndex: seriesIndex
        }
      }, generateNewSeriesTypes);
      var newTitle;

      if (type === 'stack') {
        newTitle = merge({
          stack: model.option.title.tiled,
          tiled: model.option.title.stack
        }, model.option.title);
      }

      api.dispatchAction({
        type: 'changeMagicType',
        currentType: type,
        newOption: newOption,
        newTitle: newTitle,
        featureName: 'magicType'
      });
    };

    return MagicType;
  }(ToolboxFeature);

  var seriesOptGenreator = {
    'line': function (seriesType, seriesId, seriesModel, model) {
      if (seriesType === 'bar') {
        return merge({
          id: seriesId,
          type: 'line',
          data: seriesModel.get('data'),
          stack: seriesModel.get('stack'),
          markPoint: seriesModel.get('markPoint'),
          markLine: seriesModel.get('markLine')
        }, model.get(['option', 'line']) || {}, true);
      }
    },
    'bar': function (seriesType, seriesId, seriesModel, model) {
      if (seriesType === 'line') {
        return merge({
          id: seriesId,
          type: 'bar',
          data: seriesModel.get('data'),
          stack: seriesModel.get('stack'),
          markPoint: seriesModel.get('markPoint'),
          markLine: seriesModel.get('markLine')
        }, model.get(['option', 'bar']) || {}, true);
      }
    },
    'stack': function (seriesType, seriesId, seriesModel, model) {
      var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD;

      if (seriesType === 'line' || seriesType === 'bar') {
        model.setIconStatus('stack', isStack ? 'normal' : 'emphasis');
        return merge({
          id: seriesId,
          stack: isStack ? '' : INNER_STACK_KEYWORD
        }, model.get(['option', 'stack']) || {}, true);
      }
    }
  };
  registerAction({
    type: 'changeMagicType',
    event: 'magicTypeChanged',
    update: 'prepareAndUpdate'
  }, function (payload, ecModel) {
    ecModel.mergeOption(payload.newOption);
  });
  registerFeature('magicType', MagicType);
  var BLOCK_SPLITER = new Array(60).join('-');
  var ITEM_SPLITER = '\t';

  function groupSeries(ecModel) {
    var seriesGroupByCategoryAxis = {};
    var otherSeries = [];
    var meta = [];
    ecModel.eachRawSeries(function (seriesModel) {
      var coordSys = seriesModel.coordinateSystem;

      if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) {
        var baseAxis = coordSys.getBaseAxis();

        if (baseAxis.type === 'category') {
          var key = baseAxis.dim + '_' + baseAxis.index;

          if (!seriesGroupByCategoryAxis[key]) {
            seriesGroupByCategoryAxis[key] = {
              categoryAxis: baseAxis,
              valueAxis: coordSys.getOtherAxis(baseAxis),
              series: []
            };
            meta.push({
              axisDim: baseAxis.dim,
              axisIndex: baseAxis.index
            });
          }

          seriesGroupByCategoryAxis[key].series.push(seriesModel);
        } else {
          otherSeries.push(seriesModel);
        }
      } else {
        otherSeries.push(seriesModel);
      }
    });
    return {
      seriesGroupByCategoryAxis: seriesGroupByCategoryAxis,
      other: otherSeries,
      meta: meta
    };
  }

  function assembleSeriesWithCategoryAxis(groups) {
    var tables = [];
    each(groups, function (group, key) {
      var categoryAxis = group.categoryAxis;
      var valueAxis = group.valueAxis;
      var valueAxisDim = valueAxis.dim;
      var headers = [' '].concat(map(group.series, function (series) {
        return series.name;
      }));
      var columns = [categoryAxis.model.getCategories()];
      each(group.series, function (series) {
        var rawData = series.getRawData();
        columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) {
          return val;
        }));
      });
      var lines = [headers.join(ITEM_SPLITER)];

      for (var i = 0; i < columns[0].length; i++) {
        var items = [];

        for (var j = 0; j < columns.length; j++) {
          items.push(columns[j][i]);
        }

        lines.push(items.join(ITEM_SPLITER));
      }

      tables.push(lines.join('\n'));
    });
    return tables.join('\n\n' + BLOCK_SPLITER + '\n\n');
  }

  function assembleOtherSeries(series) {
    return map(series, function (series) {
      var data = series.getRawData();
      var lines = [series.name];
      var vals = [];
      data.each(data.dimensions, function () {
        var argLen = arguments.length;
        var dataIndex = arguments[argLen - 1];
        var name = data.getName(dataIndex);

        for (var i = 0; i < argLen - 1; i++) {
          vals[i] = arguments[i];
        }

        lines.push((name ? name + ITEM_SPLITER : '') + vals.join(ITEM_SPLITER));
      });
      return lines.join('\n');
    }).join('\n\n' + BLOCK_SPLITER + '\n\n');
  }

  function getContentFromModel(ecModel) {
    var result = groupSeries(ecModel);
    return {
      value: filter([assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis), assembleOtherSeries(result.other)], function (str) {
        return !!str.replace(/[\n\t\s]/g, '');
      }).join('\n\n' + BLOCK_SPLITER + '\n\n'),
      meta: result.meta
    };
  }

  function trim$1(str) {
    return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  }

  function isTSVFormat(block) {
    var firstLine = block.slice(0, block.indexOf('\n'));

    if (firstLine.indexOf(ITEM_SPLITER) >= 0) {
      return true;
    }
  }

  var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g');

  function parseTSVContents(tsv) {
    var tsvLines = tsv.split(/\n+/g);
    var headers = trim$1(tsvLines.shift()).split(itemSplitRegex);
    var categories = [];
    var series = map(headers, function (header) {
      return {
        name: header,
        data: []
      };
    });

    for (var i = 0; i < tsvLines.length; i++) {
      var items = trim$1(tsvLines[i]).split(itemSplitRegex);
      categories.push(items.shift());

      for (var j = 0; j < items.length; j++) {
        series[j] && (series[j].data[i] = items[j]);
      }
    }

    return {
      series: series,
      categories: categories
    };
  }

  function parseListContents(str) {
    var lines = str.split(/\n+/g);
    var seriesName = trim$1(lines.shift());
    var data = [];

    for (var i = 0; i < lines.length; i++) {
      var line = trim$1(lines[i]);

      if (!line) {
        continue;
      }

      var items = line.split(itemSplitRegex);
      var name_1 = '';
      var value = void 0;
      var hasName = false;

      if (isNaN(items[0])) {
        hasName = true;
        name_1 = items[0];
        items = items.slice(1);
        data[i] = {
          name: name_1,
          value: []
        };
        value = data[i].value;
      } else {
        value = data[i] = [];
      }

      for (var j = 0; j < items.length; j++) {
        value.push(+items[j]);
      }

      if (value.length === 1) {
        hasName ? data[i].value = value[0] : data[i] = value[0];
      }
    }

    return {
      name: seriesName,
      data: data
    };
  }

  function parseContents(str, blockMetaList) {
    var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g'));
    var newOption = {
      series: []
    };
    each(blocks, function (block, idx) {
      if (isTSVFormat(block)) {
        var result = parseTSVContents(block);
        var blockMeta = blockMetaList[idx];
        var axisKey = blockMeta.axisDim + 'Axis';

        if (blockMeta) {
          newOption[axisKey] = newOption[axisKey] || [];
          newOption[axisKey][blockMeta.axisIndex] = {
            data: result.categories
          };
          newOption.series = newOption.series.concat(result.series);
        }
      } else {
        var result = parseListContents(block);
        newOption.series.push(result);
      }
    });
    return newOption;
  }

  var DataView = function (_super) {
    __extends(DataView, _super);

    function DataView() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    DataView.prototype.onclick = function (ecModel, api) {
      var container = api.getDom();
      var model = this.model;

      if (this._dom) {
        container.removeChild(this._dom);
      }

      var root = document.createElement('div');
      root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;';
      root.style.backgroundColor = model.get('backgroundColor') || '#fff';
      var header = document.createElement('h4');
      var lang = model.get('lang') || [];
      header.innerHTML = lang[0] || model.get('title');
      header.style.cssText = 'margin: 10px 20px;';
      header.style.color = model.get('textColor');
      var viewMain = document.createElement('div');
      var textarea = document.createElement('textarea');
      viewMain.style.cssText = 'display:block;width:100%;overflow:auto;';
      var optionToContent = model.get('optionToContent');
      var contentToOption = model.get('contentToOption');
      var result = getContentFromModel(ecModel);

      if (typeof optionToContent === 'function') {
        var htmlOrDom = optionToContent(api.getOption());

        if (typeof htmlOrDom === 'string') {
          viewMain.innerHTML = htmlOrDom;
        } else if (isDom(htmlOrDom)) {
          viewMain.appendChild(htmlOrDom);
        }
      } else {
        viewMain.appendChild(textarea);
        textarea.readOnly = model.get('readOnly');
        textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;';
        textarea.style.color = model.get('textColor');
        textarea.style.borderColor = model.get('textareaBorderColor');
        textarea.style.backgroundColor = model.get('textareaColor');
        textarea.value = result.value;
      }

      var blockMetaList = result.meta;
      var buttonContainer = document.createElement('div');
      buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;';
      var buttonStyle = 'float:right;margin-right:20px;border:none;' + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px';
      var closeButton = document.createElement('div');
      var refreshButton = document.createElement('div');
      buttonStyle += ';background-color:' + model.get('buttonColor');
      buttonStyle += ';color:' + model.get('buttonTextColor');
      var self = this;

      function close() {
        container.removeChild(root);
        self._dom = null;
      }

      addEventListener(closeButton, 'click', close);
      addEventListener(refreshButton, 'click', function () {
        if (contentToOption == null && optionToContent != null || contentToOption != null && optionToContent == null) {
          if (true) {
            console.warn('It seems you have just provided one of `contentToOption` and `optionToContent` functions but missed the other one. Data change is ignored.');
          }

          close();
          return;
        }

        var newOption;

        try {
          if (typeof contentToOption === 'function') {
            newOption = contentToOption(viewMain, api.getOption());
          } else {
            newOption = parseContents(textarea.value, blockMetaList);
          }
        } catch (e) {
          close();
          throw new Error('Data view format error ' + e);
        }

        if (newOption) {
          api.dispatchAction({
            type: 'changeDataView',
            newOption: newOption
          });
        }

        close();
      });
      closeButton.innerHTML = lang[1];
      refreshButton.innerHTML = lang[2];
      refreshButton.style.cssText = buttonStyle;
      closeButton.style.cssText = buttonStyle;
      !model.get('readOnly') && buttonContainer.appendChild(refreshButton);
      buttonContainer.appendChild(closeButton);
      root.appendChild(header);
      root.appendChild(viewMain);
      root.appendChild(buttonContainer);
      viewMain.style.height = container.clientHeight - 80 + 'px';
      container.appendChild(root);
      this._dom = root;
    };

    DataView.prototype.remove = function (ecModel, api) {
      this._dom && api.getDom().removeChild(this._dom);
    };

    DataView.prototype.dispose = function (ecModel, api) {
      this.remove(ecModel, api);
    };

    DataView.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        readOnly: false,
        optionToContent: null,
        contentToOption: null,
        icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28',
        title: ecModel.getLocale(['toolbox', 'dataView', 'title']),
        lang: ecModel.getLocale(['toolbox', 'dataView', 'lang']),
        backgroundColor: '#fff',
        textColor: '#000',
        textareaColor: '#fff',
        textareaBorderColor: '#333',
        buttonColor: '#c23531',
        buttonTextColor: '#fff'
      };
      return defaultOption;
    };

    return DataView;
  }(ToolboxFeature);

  function tryMergeDataOption(newData, originalData) {
    return map(newData, function (newVal, idx) {
      var original = originalData && originalData[idx];

      if (isObject(original) && !isArray(original)) {
        var newValIsObject = isObject(newVal) && !isArray(newVal);

        if (!newValIsObject) {
          newVal = {
            value: newVal
          };
        }

        var shouldDeleteName = original.name != null && newVal.name == null;
        newVal = defaults(newVal, original);
        shouldDeleteName && delete newVal.name;
        return newVal;
      } else {
        return newVal;
      }
    });
  }

  registerFeature('dataView', DataView);
  registerAction({
    type: 'changeDataView',
    event: 'dataViewChanged',
    update: 'prepareAndUpdate'
  }, function (payload, ecModel) {
    var newSeriesOptList = [];
    each(payload.newOption.series, function (seriesOpt) {
      var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0];

      if (!seriesModel) {
        newSeriesOptList.push(extend({
          type: 'scatter'
        }, seriesOpt));
      } else {
        var originalData = seriesModel.get('data');
        newSeriesOptList.push({
          name: seriesOpt.name,
          data: tryMergeDataOption(seriesOpt.data, originalData)
        });
      }
    });
    ecModel.mergeOption(defaults({
      series: newSeriesOptList
    }, payload.newOption));
  });
  var COORD_CONVERTS = ['dataToPoint', 'pointToData'];
  var INCLUDE_FINDER_MAIN_TYPES = ['grid', 'xAxis', 'yAxis', 'geo', 'graph', 'polar', 'radiusAxis', 'angleAxis', 'bmap'];

  var BrushTargetManager = function () {
    function BrushTargetManager(finder, ecModel, opt) {
      var _this = this;

      this._targetInfoList = [];
      var foundCpts = parseFinder$1(ecModel, finder);
      each(targetInfoBuilders, function (builder, type) {
        if (!opt || !opt.include || indexOf(opt.include, type) >= 0) {
          builder(foundCpts, _this._targetInfoList);
        }
      });
    }

    BrushTargetManager.prototype.setOutputRanges = function (areas, ecModel) {
      this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
        (area.coordRanges || (area.coordRanges = [])).push(coordRange);

        if (!area.coordRange) {
          area.coordRange = coordRange;
          var result = coordConvert[area.brushType](0, coordSys, coordRange);
          area.__rangeOffset = {
            offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]),
            xyMinMax: result.xyMinMax
          };
        }
      });
      return areas;
    };

    BrushTargetManager.prototype.matchOutputRanges = function (areas, ecModel, cb) {
      each(areas, function (area) {
        var targetInfo = this.findTargetInfo(area, ecModel);

        if (targetInfo && targetInfo !== true) {
          each(targetInfo.coordSyses, function (coordSys) {
            var result = coordConvert[area.brushType](1, coordSys, area.range);
            cb(area, result.values, coordSys, ecModel);
          });
        }
      }, this);
    };

    BrushTargetManager.prototype.setInputRanges = function (areas, ecModel) {
      each(areas, function (area) {
        var targetInfo = this.findTargetInfo(area, ecModel);

        if (true) {
          assert(!targetInfo || targetInfo === true || area.coordRange, 'coordRange must be specified when coord index specified.');
          assert(!targetInfo || targetInfo !== true || area.range, 'range must be specified in global brush.');
        }

        area.range = area.range || [];

        if (targetInfo && targetInfo !== true) {
          area.panelId = targetInfo.panelId;
          var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange);
          var rangeOffset = area.__rangeOffset;
          area.range = rangeOffset ? diffProcessor[area.brushType](result.values, rangeOffset.offset, getScales(result.xyMinMax, rangeOffset.xyMinMax)) : result.values;
        }
      }, this);
    };

    BrushTargetManager.prototype.makePanelOpts = function (api, getDefaultBrushType) {
      return map(this._targetInfoList, function (targetInfo) {
        var rect = targetInfo.getPanelRect();
        return {
          panelId: targetInfo.panelId,
          defaultBrushType: getDefaultBrushType ? getDefaultBrushType(targetInfo) : null,
          clipPath: makeRectPanelClipPath(rect),
          isTargetByCursor: makeRectIsTargetByCursor(rect, api, targetInfo.coordSysModel),
          getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect)
        };
      });
    };

    BrushTargetManager.prototype.controlSeries = function (area, seriesModel, ecModel) {
      var targetInfo = this.findTargetInfo(area, ecModel);
      return targetInfo === true || targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0;
    };

    BrushTargetManager.prototype.findTargetInfo = function (area, ecModel) {
      var targetInfoList = this._targetInfoList;
      var foundCpts = parseFinder$1(ecModel, area);

      for (var i = 0; i < targetInfoList.length; i++) {
        var targetInfo = targetInfoList[i];
        var areaPanelId = area.panelId;

        if (areaPanelId) {
          if (targetInfo.panelId === areaPanelId) {
            return targetInfo;
          }
        } else {
          for (var j = 0; j < targetInfoMatchers.length; j++) {
            if (targetInfoMatchers[j](foundCpts, targetInfo)) {
              return targetInfo;
            }
          }
        }
      }

      return true;
    };

    return BrushTargetManager;
  }();

  function formatMinMax(minMax) {
    minMax[0] > minMax[1] && minMax.reverse();
    return minMax;
  }

  function parseFinder$1(ecModel, finder) {
    return parseFinder(ecModel, finder, {
      includeMainTypes: INCLUDE_FINDER_MAIN_TYPES
    });
  }

  var targetInfoBuilders = {
    grid: function (foundCpts, targetInfoList) {
      var xAxisModels = foundCpts.xAxisModels;
      var yAxisModels = foundCpts.yAxisModels;
      var gridModels = foundCpts.gridModels;
      var gridModelMap = createHashMap();
      var xAxesHas = {};
      var yAxesHas = {};

      if (!xAxisModels && !yAxisModels && !gridModels) {
        return;
      }

      each(xAxisModels, function (axisModel) {
        var gridModel = axisModel.axis.grid.model;
        gridModelMap.set(gridModel.id, gridModel);
        xAxesHas[gridModel.id] = true;
      });
      each(yAxisModels, function (axisModel) {
        var gridModel = axisModel.axis.grid.model;
        gridModelMap.set(gridModel.id, gridModel);
        yAxesHas[gridModel.id] = true;
      });
      each(gridModels, function (gridModel) {
        gridModelMap.set(gridModel.id, gridModel);
        xAxesHas[gridModel.id] = true;
        yAxesHas[gridModel.id] = true;
      });
      gridModelMap.each(function (gridModel) {
        var grid = gridModel.coordinateSystem;
        var cartesians = [];
        each(grid.getCartesians(), function (cartesian, index) {
          if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0 || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0) {
            cartesians.push(cartesian);
          }
        });
        targetInfoList.push({
          panelId: 'grid--' + gridModel.id,
          gridModel: gridModel,
          coordSysModel: gridModel,
          coordSys: cartesians[0],
          coordSyses: cartesians,
          getPanelRect: panelRectBuilders.grid,
          xAxisDeclared: xAxesHas[gridModel.id],
          yAxisDeclared: yAxesHas[gridModel.id]
        });
      });
    },
    geo: function (foundCpts, targetInfoList) {
      each(foundCpts.geoModels, function (geoModel) {
        var coordSys = geoModel.coordinateSystem;
        targetInfoList.push({
          panelId: 'geo--' + geoModel.id,
          geoModel: geoModel,
          coordSysModel: geoModel,
          coordSys: coordSys,
          coordSyses: [coordSys],
          getPanelRect: panelRectBuilders.geo
        });
      });
    }
  };
  var targetInfoMatchers = [function (foundCpts, targetInfo) {
    var xAxisModel = foundCpts.xAxisModel;
    var yAxisModel = foundCpts.yAxisModel;
    var gridModel = foundCpts.gridModel;
    !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model);
    !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model);
    return gridModel && gridModel === targetInfo.gridModel;
  }, function (foundCpts, targetInfo) {
    var geoModel = foundCpts.geoModel;
    return geoModel && geoModel === targetInfo.geoModel;
  }];
  var panelRectBuilders = {
    grid: function () {
      return this.coordSys.master.getRect().clone();
    },
    geo: function () {
      var coordSys = this.coordSys;
      var rect = coordSys.getBoundingRect().clone();
      rect.applyTransform(getTransform(coordSys));
      return rect;
    }
  };
  var coordConvert = {
    lineX: curry(axisConvert, 0),
    lineY: curry(axisConvert, 1),
    rect: function (to, coordSys, rangeOrCoordRange) {
      var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]);
      var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]);
      var values = [formatMinMax([xminymin[0], xmaxymax[0]]), formatMinMax([xminymin[1], xmaxymax[1]])];
      return {
        values: values,
        xyMinMax: values
      };
    },
    polygon: function (to, coordSys, rangeOrCoordRange) {
      var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]];
      var values = map(rangeOrCoordRange, function (item) {
        var p = coordSys[COORD_CONVERTS[to]](item);
        xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]);
        xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]);
        xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]);
        xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]);
        return p;
      });
      return {
        values: values,
        xyMinMax: xyMinMax
      };
    }
  };

  function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) {
    if (true) {
      assert(coordSys.type === 'cartesian2d', 'lineX/lineY brush is available only in cartesian2d.');
    }

    var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]);
    var values = formatMinMax(map([0, 1], function (i) {
      return to ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i])) : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i]));
    }));
    var xyMinMax = [];
    xyMinMax[axisNameIndex] = values;
    xyMinMax[1 - axisNameIndex] = [NaN, NaN];
    return {
      values: values,
      xyMinMax: xyMinMax
    };
  }

  var diffProcessor = {
    lineX: curry(axisDiffProcessor, 0),
    lineY: curry(axisDiffProcessor, 1),
    rect: function (values, refer, scales) {
      return [[values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]];
    },
    polygon: function (values, refer, scales) {
      return map(values, function (item, idx) {
        return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]];
      });
    }
  };

  function axisDiffProcessor(axisNameIndex, values, refer, scales) {
    return [values[0] - scales[axisNameIndex] * refer[0], values[1] - scales[axisNameIndex] * refer[1]];
  }

  function getScales(xyMinMaxCurr, xyMinMaxOrigin) {
    var sizeCurr = getSize(xyMinMaxCurr);
    var sizeOrigin = getSize(xyMinMaxOrigin);
    var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]];
    isNaN(scales[0]) && (scales[0] = 1);
    isNaN(scales[1]) && (scales[1] = 1);
    return scales;
  }

  function getSize(xyMinMax) {
    return xyMinMax ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] : [NaN, NaN];
  }

  var each$9 = each;
  var inner$h = makeInner();

  function push(ecModel, newSnapshot) {
    var storedSnapshots = getStoreSnapshots(ecModel);
    each$9(newSnapshot, function (batchItem, dataZoomId) {
      var i = storedSnapshots.length - 1;

      for (; i >= 0; i--) {
        var snapshot = storedSnapshots[i];

        if (snapshot[dataZoomId]) {
          break;
        }
      }

      if (i < 0) {
        var dataZoomModel = ecModel.queryComponents({
          mainType: 'dataZoom',
          subType: 'select',
          id: dataZoomId
        })[0];

        if (dataZoomModel) {
          var percentRange = dataZoomModel.getPercentRange();
          storedSnapshots[0][dataZoomId] = {
            dataZoomId: dataZoomId,
            start: percentRange[0],
            end: percentRange[1]
          };
        }
      }
    });
    storedSnapshots.push(newSnapshot);
  }

  function pop(ecModel) {
    var storedSnapshots = getStoreSnapshots(ecModel);
    var head = storedSnapshots[storedSnapshots.length - 1];
    storedSnapshots.length > 1 && storedSnapshots.pop();
    var snapshot = {};
    each$9(head, function (batchItem, dataZoomId) {
      for (var i = storedSnapshots.length - 1; i >= 0; i--) {
        batchItem = storedSnapshots[i][dataZoomId];

        if (batchItem) {
          snapshot[dataZoomId] = batchItem;
          break;
        }
      }
    });
    return snapshot;
  }

  function clear$1(ecModel) {
    inner$h(ecModel).snapshots = null;
  }

  function count(ecModel) {
    return getStoreSnapshots(ecModel).length;
  }

  function getStoreSnapshots(ecModel) {
    var store = inner$h(ecModel);

    if (!store.snapshots) {
      store.snapshots = [{}];
    }

    return store.snapshots;
  }

  ComponentModel.registerSubTypeDefaulter('dataZoom', function () {
    return 'slider';
  });
  var DATA_ZOOM_AXIS_DIMENSIONS = ['x', 'y', 'radius', 'angle', 'single'];
  var SERIES_COORDS = ['cartesian2d', 'polar', 'singleAxis'];

  function isCoordSupported(seriesModel) {
    var coordType = seriesModel.get('coordinateSystem');
    return indexOf(SERIES_COORDS, coordType) >= 0;
  }

  function getAxisMainType(axisDim) {
    if (true) {
      assert(axisDim);
    }

    return axisDim + 'Axis';
  }

  function findEffectedDataZooms(ecModel, payload) {
    var axisRecords = createHashMap();
    var effectedModels = [];
    var effectedModelMap = createHashMap();
    ecModel.eachComponent({
      mainType: 'dataZoom',
      query: payload
    }, function (dataZoomModel) {
      if (!effectedModelMap.get(dataZoomModel.uid)) {
        addToEffected(dataZoomModel);
      }
    });
    var foundNewLink;

    do {
      foundNewLink = false;
      ecModel.eachComponent('dataZoom', processSingle);
    } while (foundNewLink);

    function processSingle(dataZoomModel) {
      if (!effectedModelMap.get(dataZoomModel.uid) && isLinked(dataZoomModel)) {
        addToEffected(dataZoomModel);
        foundNewLink = true;
      }
    }

    function addToEffected(dataZoom) {
      effectedModelMap.set(dataZoom.uid, true);
      effectedModels.push(dataZoom);
      markAxisControlled(dataZoom);
    }

    function isLinked(dataZoomModel) {
      var isLink = false;
      dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
        var axisIdxArr = axisRecords.get(axisDim);

        if (axisIdxArr && axisIdxArr[axisIndex]) {
          isLink = true;
        }
      });
      return isLink;
    }

    function markAxisControlled(dataZoomModel) {
      dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
        (axisRecords.get(axisDim) || axisRecords.set(axisDim, []))[axisIndex] = true;
      });
    }

    return effectedModels;
  }

  function collectReferCoordSysModelInfo(dataZoomModel) {
    var ecModel = dataZoomModel.ecModel;
    var coordSysInfoWrap = {
      infoList: [],
      infoMap: createHashMap()
    };
    dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
      var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex);

      if (!axisModel) {
        return;
      }

      var coordSysModel = axisModel.getCoordSysModel();

      if (!coordSysModel) {
        return;
      }

      var coordSysUid = coordSysModel.uid;
      var coordSysInfo = coordSysInfoWrap.infoMap.get(coordSysUid);

      if (!coordSysInfo) {
        coordSysInfo = {
          model: coordSysModel,
          axisModels: []
        };
        coordSysInfoWrap.infoList.push(coordSysInfo);
        coordSysInfoWrap.infoMap.set(coordSysUid, coordSysInfo);
      }

      coordSysInfo.axisModels.push(axisModel);
    });
    return coordSysInfoWrap;
  }

  var DataZoomAxisInfo = function () {
    function DataZoomAxisInfo() {
      this.indexList = [];
      this.indexMap = [];
    }

    DataZoomAxisInfo.prototype.add = function (axisCmptIdx) {
      if (!this.indexMap[axisCmptIdx]) {
        this.indexList.push(axisCmptIdx);
        this.indexMap[axisCmptIdx] = true;
      }
    };

    return DataZoomAxisInfo;
  }();

  var DataZoomModel = function (_super) {
    __extends(DataZoomModel, _super);

    function DataZoomModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = DataZoomModel.type;
      _this._autoThrottle = true;
      _this._noTarget = true;
      _this._rangePropMode = ['percent', 'percent'];
      return _this;
    }

    DataZoomModel.prototype.init = function (option, parentModel, ecModel) {
      var inputRawOption = retrieveRawOption(option);
      this.settledOption = inputRawOption;
      this.mergeDefaultAndTheme(option, ecModel);

      this._doInit(inputRawOption);
    };

    DataZoomModel.prototype.mergeOption = function (newOption) {
      var inputRawOption = retrieveRawOption(newOption);
      merge(this.option, newOption, true);
      merge(this.settledOption, inputRawOption, true);

      this._doInit(inputRawOption);
    };

    DataZoomModel.prototype._doInit = function (inputRawOption) {
      var thisOption = this.option;

      this._setDefaultThrottle(inputRawOption);

      this._updateRangeUse(inputRawOption);

      var settledOption = this.settledOption;
      each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
        if (this._rangePropMode[index] === 'value') {
          thisOption[names[0]] = settledOption[names[0]] = null;
        }
      }, this);

      this._resetTarget();
    };

    DataZoomModel.prototype._resetTarget = function () {
      var optionOrient = this.get('orient', true);
      var targetAxisIndexMap = this._targetAxisInfoMap = createHashMap();

      var hasAxisSpecified = this._fillSpecifiedTargetAxis(targetAxisIndexMap);

      if (hasAxisSpecified) {
        this._orient = optionOrient || this._makeAutoOrientByTargetAxis();
      } else {
        this._orient = optionOrient || 'horizontal';

        this._fillAutoTargetAxisByOrient(targetAxisIndexMap, this._orient);
      }

      this._noTarget = true;
      targetAxisIndexMap.each(function (axisInfo) {
        if (axisInfo.indexList.length) {
          this._noTarget = false;
        }
      }, this);
    };

    DataZoomModel.prototype._fillSpecifiedTargetAxis = function (targetAxisIndexMap) {
      var hasAxisSpecified = false;
      each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) {
        var refering = this.getReferringComponents(getAxisMainType(axisDim), MULTIPLE_REFERRING);

        if (!refering.specified) {
          return;
        }

        hasAxisSpecified = true;
        var axisInfo = new DataZoomAxisInfo();
        each(refering.models, function (axisModel) {
          axisInfo.add(axisModel.componentIndex);
        });
        targetAxisIndexMap.set(axisDim, axisInfo);
      }, this);
      return hasAxisSpecified;
    };

    DataZoomModel.prototype._fillAutoTargetAxisByOrient = function (targetAxisIndexMap, orient) {
      var ecModel = this.ecModel;
      var needAuto = true;

      if (needAuto) {
        var axisDim = orient === 'vertical' ? 'y' : 'x';
        var axisModels = ecModel.findComponents({
          mainType: axisDim + 'Axis'
        });
        setParallelAxis(axisModels, axisDim);
      }

      if (needAuto) {
        var axisModels = ecModel.findComponents({
          mainType: 'singleAxis',
          filter: function (axisModel) {
            return axisModel.get('orient', true) === orient;
          }
        });
        setParallelAxis(axisModels, 'single');
      }

      function setParallelAxis(axisModels, axisDim) {
        var axisModel = axisModels[0];

        if (!axisModel) {
          return;
        }

        var axisInfo = new DataZoomAxisInfo();
        axisInfo.add(axisModel.componentIndex);
        targetAxisIndexMap.set(axisDim, axisInfo);
        needAuto = false;

        if (axisDim === 'x' || axisDim === 'y') {
          var gridModel_1 = axisModel.getReferringComponents('grid', SINGLE_REFERRING).models[0];
          gridModel_1 && each(axisModels, function (axModel) {
            if (axisModel.componentIndex !== axModel.componentIndex && gridModel_1 === axModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]) {
              axisInfo.add(axModel.componentIndex);
            }
          });
        }
      }

      if (needAuto) {
        each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) {
          if (!needAuto) {
            return;
          }

          var axisModels = ecModel.findComponents({
            mainType: getAxisMainType(axisDim),
            filter: function (axisModel) {
              return axisModel.get('type', true) === 'category';
            }
          });

          if (axisModels[0]) {
            var axisInfo = new DataZoomAxisInfo();
            axisInfo.add(axisModels[0].componentIndex);
            targetAxisIndexMap.set(axisDim, axisInfo);
            needAuto = false;
          }
        }, this);
      }
    };

    DataZoomModel.prototype._makeAutoOrientByTargetAxis = function () {
      var dim;
      this.eachTargetAxis(function (axisDim) {
        !dim && (dim = axisDim);
      }, this);
      return dim === 'y' ? 'vertical' : 'horizontal';
    };

    DataZoomModel.prototype._setDefaultThrottle = function (inputRawOption) {
      if (inputRawOption.hasOwnProperty('throttle')) {
        this._autoThrottle = false;
      }

      if (this._autoThrottle) {
        var globalOption = this.ecModel.option;
        this.option.throttle = globalOption.animation && globalOption.animationDurationUpdate > 0 ? 100 : 20;
      }
    };

    DataZoomModel.prototype._updateRangeUse = function (inputRawOption) {
      var rangePropMode = this._rangePropMode;
      var rangeModeInOption = this.get('rangeMode');
      each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
        var percentSpecified = inputRawOption[names[0]] != null;
        var valueSpecified = inputRawOption[names[1]] != null;

        if (percentSpecified && !valueSpecified) {
          rangePropMode[index] = 'percent';
        } else if (!percentSpecified && valueSpecified) {
          rangePropMode[index] = 'value';
        } else if (rangeModeInOption) {
          rangePropMode[index] = rangeModeInOption[index];
        } else if (percentSpecified) {
          rangePropMode[index] = 'percent';
        }
      });
    };

    DataZoomModel.prototype.noTarget = function () {
      return this._noTarget;
    };

    DataZoomModel.prototype.getFirstTargetAxisModel = function () {
      var firstAxisModel;
      this.eachTargetAxis(function (axisDim, axisIndex) {
        if (firstAxisModel == null) {
          firstAxisModel = this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex);
        }
      }, this);
      return firstAxisModel;
    };

    DataZoomModel.prototype.eachTargetAxis = function (callback, context) {
      this._targetAxisInfoMap.each(function (axisInfo, axisDim) {
        each(axisInfo.indexList, function (axisIndex) {
          callback.call(context, axisDim, axisIndex);
        });
      });
    };

    DataZoomModel.prototype.getAxisProxy = function (axisDim, axisIndex) {
      var axisModel = this.getAxisModel(axisDim, axisIndex);

      if (axisModel) {
        return axisModel.__dzAxisProxy;
      }
    };

    DataZoomModel.prototype.getAxisModel = function (axisDim, axisIndex) {
      if (true) {
        assert(axisDim && axisIndex != null);
      }

      var axisInfo = this._targetAxisInfoMap.get(axisDim);

      if (axisInfo && axisInfo.indexMap[axisIndex]) {
        return this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex);
      }
    };

    DataZoomModel.prototype.setRawRange = function (opt) {
      var thisOption = this.option;
      var settledOption = this.settledOption;
      each([['start', 'startValue'], ['end', 'endValue']], function (names) {
        if (opt[names[0]] != null || opt[names[1]] != null) {
          thisOption[names[0]] = settledOption[names[0]] = opt[names[0]];
          thisOption[names[1]] = settledOption[names[1]] = opt[names[1]];
        }
      }, this);

      this._updateRangeUse(opt);
    };

    DataZoomModel.prototype.setCalculatedRange = function (opt) {
      var option = this.option;
      each(['start', 'startValue', 'end', 'endValue'], function (name) {
        option[name] = opt[name];
      });
    };

    DataZoomModel.prototype.getPercentRange = function () {
      var axisProxy = this.findRepresentativeAxisProxy();

      if (axisProxy) {
        return axisProxy.getDataPercentWindow();
      }
    };

    DataZoomModel.prototype.getValueRange = function (axisDim, axisIndex) {
      if (axisDim == null && axisIndex == null) {
        var axisProxy = this.findRepresentativeAxisProxy();

        if (axisProxy) {
          return axisProxy.getDataValueWindow();
        }
      } else {
        return this.getAxisProxy(axisDim, axisIndex).getDataValueWindow();
      }
    };

    DataZoomModel.prototype.findRepresentativeAxisProxy = function (axisModel) {
      if (axisModel) {
        return axisModel.__dzAxisProxy;
      }

      var firstProxy;

      var axisDimList = this._targetAxisInfoMap.keys();

      for (var i = 0; i < axisDimList.length; i++) {
        var axisDim = axisDimList[i];

        var axisInfo = this._targetAxisInfoMap.get(axisDim);

        for (var j = 0; j < axisInfo.indexList.length; j++) {
          var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]);

          if (proxy.hostedBy(this)) {
            return proxy;
          }

          if (!firstProxy) {
            firstProxy = proxy;
          }
        }
      }

      return firstProxy;
    };

    DataZoomModel.prototype.getRangePropMode = function () {
      return this._rangePropMode.slice();
    };

    DataZoomModel.prototype.getOrient = function () {
      if (true) {
        assert(this._orient);
      }

      return this._orient;
    };

    DataZoomModel.type = 'dataZoom';
    DataZoomModel.dependencies = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series', 'toolbox'];
    DataZoomModel.defaultOption = {
      zlevel: 0,
      z: 4,
      filterMode: 'filter',
      start: 0,
      end: 100
    };
    return DataZoomModel;
  }(ComponentModel);

  function retrieveRawOption(option) {
    var ret = {};
    each(['start', 'end', 'startValue', 'endValue', 'throttle'], function (name) {
      option.hasOwnProperty(name) && (ret[name] = option[name]);
    });
    return ret;
  }

  var DataZoomView = function (_super) {
    __extends(DataZoomView, _super);

    function DataZoomView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = DataZoomView.type;
      return _this;
    }

    DataZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) {
      this.dataZoomModel = dataZoomModel;
      this.ecModel = ecModel;
      this.api = api;
    };

    DataZoomView.type = 'dataZoom';
    return DataZoomView;
  }(ComponentView);

  ComponentView.registerClass(DataZoomView);

  var SelectDataZoomModel = function (_super) {
    __extends(SelectDataZoomModel, _super);

    function SelectDataZoomModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SelectDataZoomModel.type;
      return _this;
    }

    SelectDataZoomModel.type = 'dataZoom.select';
    return SelectDataZoomModel;
  }(DataZoomModel);

  ComponentModel.registerClass(SelectDataZoomModel);

  var SelectDataZoomView = function (_super) {
    __extends(SelectDataZoomView, _super);

    function SelectDataZoomView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SelectDataZoomView.type;
      return _this;
    }

    SelectDataZoomView.type = 'dataZoom.select';
    return SelectDataZoomView;
  }(DataZoomView);

  ComponentView.registerClass(SelectDataZoomView);
  var each$a = each;
  var asc$1 = asc;

  var AxisProxy = function () {
    function AxisProxy(dimName, axisIndex, dataZoomModel, ecModel) {
      this._dimName = dimName;
      this._axisIndex = axisIndex;
      this.ecModel = ecModel;
      this._dataZoomModel = dataZoomModel;
    }

    AxisProxy.prototype.hostedBy = function (dataZoomModel) {
      return this._dataZoomModel === dataZoomModel;
    };

    AxisProxy.prototype.getDataValueWindow = function () {
      return this._valueWindow.slice();
    };

    AxisProxy.prototype.getDataPercentWindow = function () {
      return this._percentWindow.slice();
    };

    AxisProxy.prototype.getTargetSeriesModels = function () {
      var seriesModels = [];
      this.ecModel.eachSeries(function (seriesModel) {
        if (isCoordSupported(seriesModel)) {
          var axisMainType = getAxisMainType(this._dimName);
          var axisModel = seriesModel.getReferringComponents(axisMainType, SINGLE_REFERRING).models[0];

          if (axisModel && this._axisIndex === axisModel.componentIndex) {
            seriesModels.push(seriesModel);
          }
        }
      }, this);
      return seriesModels;
    };

    AxisProxy.prototype.getAxisModel = function () {
      return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex);
    };

    AxisProxy.prototype.getMinMaxSpan = function () {
      return clone(this._minMaxSpan);
    };

    AxisProxy.prototype.calculateDataWindow = function (opt) {
      var dataExtent = this._dataExtent;
      var axisModel = this.getAxisModel();
      var scale = axisModel.axis.scale;

      var rangePropMode = this._dataZoomModel.getRangePropMode();

      var percentExtent = [0, 100];
      var percentWindow = [];
      var valueWindow = [];
      var hasPropModeValue;
      each$a(['start', 'end'], function (prop, idx) {
        var boundPercent = opt[prop];
        var boundValue = opt[prop + 'Value'];

        if (rangePropMode[idx] === 'percent') {
          boundPercent == null && (boundPercent = percentExtent[idx]);
          boundValue = scale.parse(linearMap(boundPercent, percentExtent, dataExtent));
        } else {
          hasPropModeValue = true;
          boundValue = boundValue == null ? dataExtent[idx] : scale.parse(boundValue);
          boundPercent = linearMap(boundValue, dataExtent, percentExtent);
        }

        valueWindow[idx] = boundValue;
        percentWindow[idx] = boundPercent;
      });
      asc$1(valueWindow);
      asc$1(percentWindow);
      var spans = this._minMaxSpan;
      hasPropModeValue ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false) : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true);

      function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) {
        var suffix = toValue ? 'Span' : 'ValueSpan';
        sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]);

        for (var i = 0; i < 2; i++) {
          toWindow[i] = linearMap(fromWindow[i], fromExtent, toExtent, true);
          toValue && (toWindow[i] = scale.parse(toWindow[i]));
        }
      }

      return {
        valueWindow: valueWindow,
        percentWindow: percentWindow
      };
    };

    AxisProxy.prototype.reset = function (dataZoomModel) {
      if (dataZoomModel !== this._dataZoomModel) {
        return;
      }

      var targetSeries = this.getTargetSeriesModels();
      this._dataExtent = calculateDataExtent(this, this._dimName, targetSeries);

      this._updateMinMaxSpan();

      var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption);
      this._valueWindow = dataWindow.valueWindow;
      this._percentWindow = dataWindow.percentWindow;

      this._setAxisModel();
    };

    AxisProxy.prototype.filterData = function (dataZoomModel, api) {
      if (dataZoomModel !== this._dataZoomModel) {
        return;
      }

      var axisDim = this._dimName;
      var seriesModels = this.getTargetSeriesModels();
      var filterMode = dataZoomModel.get('filterMode');
      var valueWindow = this._valueWindow;

      if (filterMode === 'none') {
        return;
      }

      each$a(seriesModels, function (seriesModel) {
        var seriesData = seriesModel.getData();
        var dataDims = seriesData.mapDimensionsAll(axisDim);

        if (!dataDims.length) {
          return;
        }

        if (filterMode === 'weakFilter') {
          seriesData.filterSelf(function (dataIndex) {
            var leftOut;
            var rightOut;
            var hasValue;

            for (var i = 0; i < dataDims.length; i++) {
              var value = seriesData.get(dataDims[i], dataIndex);
              var thisHasValue = !isNaN(value);
              var thisLeftOut = value < valueWindow[0];
              var thisRightOut = value > valueWindow[1];

              if (thisHasValue && !thisLeftOut && !thisRightOut) {
                return true;
              }

              thisHasValue && (hasValue = true);
              thisLeftOut && (leftOut = true);
              thisRightOut && (rightOut = true);
            }

            return hasValue && leftOut && rightOut;
          });
        } else {
          each$a(dataDims, function (dim) {
            if (filterMode === 'empty') {
              seriesModel.setData(seriesData = seriesData.map(dim, function (value) {
                return !isInWindow(value) ? NaN : value;
              }));
            } else {
              var range = {};
              range[dim] = valueWindow;
              seriesData.selectRange(range);
            }
          });
        }

        each$a(dataDims, function (dim) {
          seriesData.setApproximateExtent(valueWindow, dim);
        });
      });

      function isInWindow(value) {
        return value >= valueWindow[0] && value <= valueWindow[1];
      }
    };

    AxisProxy.prototype._updateMinMaxSpan = function () {
      var minMaxSpan = this._minMaxSpan = {};
      var dataZoomModel = this._dataZoomModel;
      var dataExtent = this._dataExtent;
      each$a(['min', 'max'], function (minMax) {
        var percentSpan = dataZoomModel.get(minMax + 'Span');
        var valueSpan = dataZoomModel.get(minMax + 'ValueSpan');
        valueSpan != null && (valueSpan = this.getAxisModel().axis.scale.parse(valueSpan));

        if (valueSpan != null) {
          percentSpan = linearMap(dataExtent[0] + valueSpan, dataExtent, [0, 100], true);
        } else if (percentSpan != null) {
          valueSpan = linearMap(percentSpan, [0, 100], dataExtent, true) - dataExtent[0];
        }

        minMaxSpan[minMax + 'Span'] = percentSpan;
        minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
      }, this);
    };

    AxisProxy.prototype._setAxisModel = function () {
      var axisModel = this.getAxisModel();
      var percentWindow = this._percentWindow;
      var valueWindow = this._valueWindow;

      if (!percentWindow) {
        return;
      }

      var precision = getPixelPrecision(valueWindow, [0, 500]);
      precision = Math.min(precision, 20);
      var rawExtentInfo = axisModel.axis.scale.rawExtentInfo;

      if (percentWindow[0] !== 0) {
        rawExtentInfo.setDeterminedMinMax('min', +valueWindow[0].toFixed(precision));
      }

      if (percentWindow[1] !== 100) {
        rawExtentInfo.setDeterminedMinMax('max', +valueWindow[1].toFixed(precision));
      }

      rawExtentInfo.freeze();
    };

    return AxisProxy;
  }();

  function calculateDataExtent(axisProxy, axisDim, seriesModels) {
    var dataExtent = [Infinity, -Infinity];
    each$a(seriesModels, function (seriesModel) {
      unionAxisExtentFromData(dataExtent, seriesModel.getData(), axisDim);
    });
    var axisModel = axisProxy.getAxisModel();
    var rawExtentResult = ensureScaleRawExtentInfo(axisModel.axis.scale, axisModel, dataExtent).calculate();
    return [rawExtentResult.min, rawExtentResult.max];
  }

  registerProcessor(PRIORITY.PROCESSOR.FILTER, {
    getTargetSeries: function (ecModel) {
      function eachAxisModel(cb) {
        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
          dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
            var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex);
            cb(axisDim, axisIndex, axisModel, dataZoomModel);
          });
        });
      }

      eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) {
        axisModel.__dzAxisProxy = null;
      });
      var proxyList = [];
      eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) {
        if (!axisModel.__dzAxisProxy) {
          axisModel.__dzAxisProxy = new AxisProxy(axisDim, axisIndex, dataZoomModel, ecModel);
          proxyList.push(axisModel.__dzAxisProxy);
        }
      });
      var seriesModelMap = createHashMap();
      each(proxyList, function (axisProxy) {
        each(axisProxy.getTargetSeriesModels(), function (seriesModel) {
          seriesModelMap.set(seriesModel.uid, seriesModel);
        });
      });
      return seriesModelMap;
    },
    overallReset: function (ecModel, api) {
      ecModel.eachComponent('dataZoom', function (dataZoomModel) {
        dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
          dataZoomModel.getAxisProxy(axisDim, axisIndex).reset(dataZoomModel);
        });
        dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
          dataZoomModel.getAxisProxy(axisDim, axisIndex).filterData(dataZoomModel, api);
        });
      });
      ecModel.eachComponent('dataZoom', function (dataZoomModel) {
        var axisProxy = dataZoomModel.findRepresentativeAxisProxy();

        if (axisProxy) {
          var percentRange = axisProxy.getDataPercentWindow();
          var valueRange = axisProxy.getDataValueWindow();
          dataZoomModel.setCalculatedRange({
            start: percentRange[0],
            end: percentRange[1],
            startValue: valueRange[0],
            endValue: valueRange[1]
          });
        }
      });
    }
  });
  registerAction('dataZoom', function (payload, ecModel) {
    var effectedModels = findEffectedDataZooms(ecModel, payload);
    each(effectedModels, function (dataZoomModel) {
      dataZoomModel.setRawRange({
        start: payload.start,
        end: payload.end,
        startValue: payload.startValue,
        endValue: payload.endValue
      });
    });
  });
  var each$b = each;
  var DATA_ZOOM_ID_BASE = makeInternalComponentId('toolbox-dataZoom_');

  var DataZoomFeature = function (_super) {
    __extends(DataZoomFeature, _super);

    function DataZoomFeature() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    DataZoomFeature.prototype.render = function (featureModel, ecModel, api, payload) {
      if (!this.brushController) {
        this.brushController = new BrushController(api.getZr());
        this.brushController.on('brush', bind(this._onBrush, this)).mount();
      }

      updateZoomBtnStatus(featureModel, ecModel, this, payload, api);
      updateBackBtnStatus(featureModel, ecModel);
    };

    DataZoomFeature.prototype.onclick = function (ecModel, api, type) {
      handlers$1[type].call(this);
    };

    DataZoomFeature.prototype.remove = function (ecModel, api) {
      this.brushController.unmount();
    };

    DataZoomFeature.prototype.dispose = function (ecModel, api) {
      this.brushController.dispose();
    };

    DataZoomFeature.prototype._onBrush = function (eventParam) {
      var areas = eventParam.areas;

      if (!eventParam.isEnd || !areas.length) {
        return;
      }

      var snapshot = {};
      var ecModel = this.ecModel;
      this.brushController.updateCovers([]);
      var brushTargetManager = new BrushTargetManager(makeAxisFinder(this.model), ecModel, {
        include: ['grid']
      });
      brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
        if (coordSys.type !== 'cartesian2d') {
          return;
        }

        var brushType = area.brushType;

        if (brushType === 'rect') {
          setBatch('x', coordSys, coordRange[0]);
          setBatch('y', coordSys, coordRange[1]);
        } else {
          setBatch({
            lineX: 'x',
            lineY: 'y'
          }[brushType], coordSys, coordRange);
        }
      });
      push(ecModel, snapshot);

      this._dispatchZoomAction(snapshot);

      function setBatch(dimName, coordSys, minMax) {
        var axis = coordSys.getAxis(dimName);
        var axisModel = axis.model;
        var dataZoomModel = findDataZoom(dimName, axisModel, ecModel);
        var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan();

        if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) {
          minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan);
        }

        dataZoomModel && (snapshot[dataZoomModel.id] = {
          dataZoomId: dataZoomModel.id,
          startValue: minMax[0],
          endValue: minMax[1]
        });
      }

      function findDataZoom(dimName, axisModel, ecModel) {
        var found;
        ecModel.eachComponent({
          mainType: 'dataZoom',
          subType: 'select'
        }, function (dzModel) {
          var has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
          has && (found = dzModel);
        });
        return found;
      }
    };

    DataZoomFeature.prototype._dispatchZoomAction = function (snapshot) {
      var batch = [];
      each$b(snapshot, function (batchItem, dataZoomId) {
        batch.push(clone(batchItem));
      });
      batch.length && this.api.dispatchAction({
        type: 'dataZoom',
        from: this.uid,
        batch: batch
      });
    };

    DataZoomFeature.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        filterMode: 'filter',
        icon: {
          zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
          back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
        },
        title: ecModel.getLocale(['toolbox', 'dataZoom', 'title']),
        brushStyle: {
          borderWidth: 0,
          color: 'rgba(210,219,238,0.2)'
        }
      };
      return defaultOption;
    };

    return DataZoomFeature;
  }(ToolboxFeature);

  var handlers$1 = {
    zoom: function () {
      var nextActive = !this.isZoomActive;
      this.api.dispatchAction({
        type: 'takeGlobalCursor',
        key: 'dataZoomSelect',
        dataZoomSelectActive: nextActive
      });
    },
    back: function () {
      this._dispatchZoomAction(pop(this.ecModel));
    }
  };

  function makeAxisFinder(dzFeatureModel) {
    var setting = {
      xAxisIndex: dzFeatureModel.get('xAxisIndex', true),
      yAxisIndex: dzFeatureModel.get('yAxisIndex', true),
      xAxisId: dzFeatureModel.get('xAxisId', true),
      yAxisId: dzFeatureModel.get('yAxisId', true)
    };

    if (setting.xAxisIndex == null && setting.xAxisId == null) {
      setting.xAxisIndex = 'all';
    }

    if (setting.yAxisIndex == null && setting.yAxisId == null) {
      setting.yAxisIndex = 'all';
    }

    return setting;
  }

  function updateBackBtnStatus(featureModel, ecModel) {
    featureModel.setIconStatus('back', count(ecModel) > 1 ? 'emphasis' : 'normal');
  }

  function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
    var zoomActive = view.isZoomActive;

    if (payload && payload.type === 'takeGlobalCursor') {
      zoomActive = payload.key === 'dataZoomSelect' ? payload.dataZoomSelectActive : false;
    }

    view.isZoomActive = zoomActive;
    featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal');
    var brushTargetManager = new BrushTargetManager(makeAxisFinder(featureModel), ecModel, {
      include: ['grid']
    });
    var panels = brushTargetManager.makePanelOpts(api, function (targetInfo) {
      return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect';
    });
    view.brushController.setPanels(panels).enableBrush(zoomActive && panels.length ? {
      brushType: 'auto',
      brushStyle: featureModel.getModel('brushStyle').getItemStyle()
    } : false);
  }

  registerFeature('dataZoom', DataZoomFeature);
  registerInternalOptionCreator('dataZoom', function (ecModel) {
    var toolboxModel = ecModel.getComponent('toolbox', 0);

    if (!toolboxModel) {
      return;
    }

    var dzFeatureModel = toolboxModel.getModel(['feature', 'dataZoom']);
    var dzOptions = [];
    var finder = makeAxisFinder(dzFeatureModel);
    var finderResult = parseFinder(ecModel, finder);
    each$b(finderResult.xAxisModels, function (axisModel) {
      return buildInternalOptions(axisModel, 'xAxis', 'xAxisIndex');
    });
    each$b(finderResult.yAxisModels, function (axisModel) {
      return buildInternalOptions(axisModel, 'yAxis', 'yAxisIndex');
    });

    function buildInternalOptions(axisModel, axisMainType, axisIndexPropName) {
      var axisIndex = axisModel.componentIndex;
      var newOpt = {
        type: 'select',
        $fromToolbox: true,
        filterMode: dzFeatureModel.get('filterMode', true) || 'filter',
        id: DATA_ZOOM_ID_BASE + axisMainType + axisIndex
      };
      newOpt[axisIndexPropName] = axisIndex;
      dzOptions.push(newOpt);
    }

    return dzOptions;
  });

  var RestoreOption = function (_super) {
    __extends(RestoreOption, _super);

    function RestoreOption() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    RestoreOption.prototype.onclick = function (ecModel, api) {
      clear$1(ecModel);
      api.dispatchAction({
        type: 'restore',
        from: this.uid
      });
    };

    RestoreOption.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5',
        title: ecModel.getLocale(['toolbox', 'restore', 'title'])
      };
      return defaultOption;
    };

    return RestoreOption;
  }(ToolboxFeature);

  registerFeature('restore', RestoreOption);
  registerAction({
    type: 'restore',
    event: 'restore',
    update: 'prepareAndUpdate'
  }, function (payload, ecModel) {
    ecModel.resetOption('recreate');
  });

  var TooltipModel = function (_super) {
    __extends(TooltipModel, _super);

    function TooltipModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TooltipModel.type;
      return _this;
    }

    TooltipModel.type = 'tooltip';
    TooltipModel.dependencies = ['axisPointer'];
    TooltipModel.defaultOption = {
      zlevel: 0,
      z: 60,
      show: true,
      showContent: true,
      trigger: 'item',
      triggerOn: 'mousemove|click',
      alwaysShowContent: false,
      displayMode: 'single',
      renderMode: 'auto',
      confine: null,
      showDelay: 0,
      hideDelay: 100,
      transitionDuration: 0.4,
      enterable: false,
      backgroundColor: '#fff',
      shadowBlur: 10,
      shadowColor: 'rgba(0, 0, 0, .2)',
      shadowOffsetX: 1,
      shadowOffsetY: 2,
      borderColor: '#333',
      borderRadius: 4,
      borderWidth: 1,
      padding: null,
      extraCssText: '',
      axisPointer: {
        type: 'line',
        axis: 'auto',
        animation: 'auto',
        animationDurationUpdate: 200,
        animationEasingUpdate: 'exponentialOut',
        crossStyle: {
          color: '#999',
          width: 1,
          type: 'dashed',
          textStyle: {}
        }
      },
      textStyle: {
        color: '#666',
        fontSize: 14
      }
    };
    return TooltipModel;
  }(ComponentModel);

  ComponentModel.registerClass(TooltipModel);

  function shouldTooltipConfine(tooltipModel) {
    var confineOption = tooltipModel.get('confine');
    return confineOption != null ? !!confineOption : tooltipModel.get('renderMode') === 'richText';
  }

  var vendors = ['-ms-', '-moz-', '-o-', '-webkit-', ''];
  var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';

  function mirrorPos(pos) {
    pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top';
    return pos;
  }

  function assembleArrow(backgroundColor, borderColor, arrowPosition) {
    if (!isString(arrowPosition) || arrowPosition === 'inside') {
      return '';
    }

    borderColor = convertToColorString(borderColor);
    var arrowPos = mirrorPos(arrowPosition);
    var positionStyle = '';
    var transformStyle = '';

    if (indexOf(['left', 'right'], arrowPos) > -1) {
      positionStyle = arrowPos + ":-6px;top:50%;";
      transformStyle = "translateY(-50%) rotate(" + (arrowPos === 'left' ? -225 : -45) + "deg)";
    } else {
      positionStyle = arrowPos + ":-6px;left:50%;";
      transformStyle = "translateX(-50%) rotate(" + (arrowPos === 'top' ? 225 : 45) + "deg)";
    }

    transformStyle = map(vendors, function (vendorPrefix) {
      return vendorPrefix + 'transform:' + transformStyle;
    }).join(';');
    var styleCss = ['position:absolute;width:10px;height:10px;', "" + positionStyle + transformStyle + ";", "border-bottom: " + borderColor + " solid 1px;", "border-right: " + borderColor + " solid 1px;", "background-color: " + backgroundColor + ";", 'box-shadow: 8px 8px 16px -3px #000;'];
    return "<div style=\"" + styleCss.join('') + "\"></div>";
  }

  function assembleTransition(duration, onlyFade) {
    var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)';
    var transitionText = 'opacity ' + duration / 2 + 's ' + transitionCurve + ',' + 'visibility ' + duration / 2 + 's ' + transitionCurve;

    if (!onlyFade) {
      transitionText += ',left ' + duration + 's ' + transitionCurve + ',top ' + duration + 's ' + transitionCurve;
    }

    return map(vendors, function (vendorPrefix) {
      return vendorPrefix + 'transition:' + transitionText;
    }).join(';');
  }

  function assembleFont(textStyleModel) {
    var cssText = [];
    var fontSize = textStyleModel.get('fontSize');
    var color = textStyleModel.getTextColor();
    color && cssText.push('color:' + color);
    cssText.push('font:' + textStyleModel.getFont());
    fontSize && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
    var shadowColor = textStyleModel.get('textShadowColor');
    var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
    var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
    var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
    shadowColor && shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor);
    each(['decoration', 'align'], function (name) {
      var val = textStyleModel.get(name);
      val && cssText.push('text-' + name + ':' + val);
    });
    return cssText.join(';');
  }

  function assembleCssText(tooltipModel, enableTransition, onlyFade) {
    var cssText = [];
    var transitionDuration = tooltipModel.get('transitionDuration');
    var backgroundColor = tooltipModel.get('backgroundColor');
    var shadowBlur = tooltipModel.get('shadowBlur');
    var shadowColor = tooltipModel.get('shadowColor');
    var shadowOffsetX = tooltipModel.get('shadowOffsetX');
    var shadowOffsetY = tooltipModel.get('shadowOffsetY');
    var textStyleModel = tooltipModel.getModel('textStyle');
    var padding = getPaddingFromTooltipModel(tooltipModel, 'html');
    var boxShadow = shadowOffsetX + "px " + shadowOffsetY + "px " + shadowBlur + "px " + shadowColor;
    cssText.push('box-shadow:' + boxShadow);
    enableTransition && transitionDuration && cssText.push(assembleTransition(transitionDuration, onlyFade));

    if (backgroundColor) {
      if (env.canvasSupported) {
        cssText.push('background-Color:' + backgroundColor);
      } else {
        cssText.push('background-Color:#' + toHex(backgroundColor));
        cssText.push('filter:alpha(opacity=70)');
      }
    }

    each(['width', 'color', 'radius'], function (name) {
      var borderName = 'border-' + name;
      var camelCase = toCamelCase(borderName);
      var val = tooltipModel.get(camelCase);
      val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px'));
    });
    cssText.push(assembleFont(textStyleModel));

    if (padding != null) {
      cssText.push('padding:' + normalizeCssArray$1(padding).join('px ') + 'px');
    }

    return cssText.join(';') + ';';
  }

  function makeStyleCoord(out, zr, appendToBody, zrX, zrY) {
    var zrPainter = zr && zr.painter;

    if (appendToBody) {
      var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();

      if (zrViewportRoot) {
        transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
      }
    } else {
      out[0] = zrX;
      out[1] = zrY;
      var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();

      if (viewportRootOffset) {
        out[0] += viewportRootOffset.offsetLeft;
        out[1] += viewportRootOffset.offsetTop;
      }
    }

    out[2] = out[0] / zr.getWidth();
    out[3] = out[1] / zr.getHeight();
  }

  var TooltipHTMLContent = function () {
    function TooltipHTMLContent(container, api, opt) {
      this._show = false;
      this._styleCoord = [0, 0, 0, 0];
      this._enterable = true;
      this._firstShow = true;
      this._longHide = true;

      if (env.wxa) {
        return null;
      }

      var el = document.createElement('div');
      el.domBelongToZr = true;
      this.el = el;
      var zr = this._zr = api.getZr();
      var appendToBody = this._appendToBody = opt && opt.appendToBody;
      makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);

      if (appendToBody) {
        document.body.appendChild(el);
      } else {
        container.appendChild(el);
      }

      this._container = container;
      var self = this;

      el.onmouseenter = function () {
        if (self._enterable) {
          clearTimeout(self._hideTimeout);
          self._show = true;
        }

        self._inContent = true;
      };

      el.onmousemove = function (e) {
        e = e || window.event;

        if (!self._enterable) {
          var handler = zr.handler;
          var zrViewportRoot = zr.painter.getViewportRoot();
          normalizeEvent(zrViewportRoot, e, true);
          handler.dispatch('mousemove', e);
        }
      };

      el.onmouseleave = function () {
        self._inContent = false;

        if (self._enterable) {
          if (self._show) {
            self.hideLater(self._hideDelay);
          }
        }
      };
    }

    TooltipHTMLContent.prototype.update = function (tooltipModel) {
      var container = this._container;
      var stl = container.currentStyle || document.defaultView.getComputedStyle(container);
      var domStyle = container.style;

      if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
        domStyle.position = 'relative';
      }

      var alwaysShowContent = tooltipModel.get('alwaysShowContent');
      alwaysShowContent && this._moveIfResized();
      this.el.className = tooltipModel.get('className') || '';
    };

    TooltipHTMLContent.prototype.show = function (tooltipModel, nearPointColor) {
      clearTimeout(this._hideTimeout);
      clearTimeout(this._longHideTimeout);
      var el = this.el;
      var styleCoord = this._styleCoord;
      var offset = el.offsetHeight / 2;
      nearPointColor = convertToColorString(nearPointColor);
      el.style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) + ';left:' + styleCoord[0] + 'px;top:' + (styleCoord[1] - offset) + 'px;' + ("border-color: " + nearPointColor + ";") + (tooltipModel.get('extraCssText') || '');
      el.style.display = el.innerHTML ? 'block' : 'none';
      el.style.pointerEvents = this._enterable ? 'auto' : 'none';
      this._show = true;
      this._firstShow = false;
      this._longHide = false;
    };

    TooltipHTMLContent.prototype.setContent = function (content, markers, tooltipModel, borderColor, arrowPosition) {
      if (content == null) {
        return;
      }

      var el = this.el;

      if (isString(arrowPosition) && tooltipModel.get('trigger') === 'item' && !shouldTooltipConfine(tooltipModel)) {
        content += assembleArrow(tooltipModel.get('backgroundColor'), borderColor, arrowPosition);
      }

      if (isString(content)) {
        el.innerHTML = content;
      } else if (content) {
        el.innerHTML = '';

        if (!isArray(content)) {
          content = [content];
        }

        for (var i = 0; i < content.length; i++) {
          if (isDom(content[i]) && content[i].parentNode !== el) {
            el.appendChild(content[i]);
          }
        }
      }
    };

    TooltipHTMLContent.prototype.setEnterable = function (enterable) {
      this._enterable = enterable;
    };

    TooltipHTMLContent.prototype.getSize = function () {
      var el = this.el;
      return [el.clientWidth, el.clientHeight];
    };

    TooltipHTMLContent.prototype.moveTo = function (zrX, zrY) {
      var styleCoord = this._styleCoord;
      makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY);

      if (styleCoord[0] != null && styleCoord[1] != null) {
        var style = this.el.style;
        style.left = styleCoord[0].toFixed(0) + 'px';
        style.top = styleCoord[1].toFixed(0) + 'px';
      }
    };

    TooltipHTMLContent.prototype._moveIfResized = function () {
      var ratioX = this._styleCoord[2];
      var ratioY = this._styleCoord[3];
      this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight());
    };

    TooltipHTMLContent.prototype.hide = function () {
      var _this = this;

      this.el.style.visibility = 'hidden';
      this.el.style.opacity = '0';
      this._show = false;
      this._longHideTimeout = setTimeout(function () {
        return _this._longHide = true;
      }, 500);
    };

    TooltipHTMLContent.prototype.hideLater = function (time) {
      if (this._show && !(this._inContent && this._enterable)) {
        if (time) {
          this._hideDelay = time;
          this._show = false;
          this._hideTimeout = setTimeout(bind(this.hide, this), time);
        } else {
          this.hide();
        }
      }
    };

    TooltipHTMLContent.prototype.isShow = function () {
      return this._show;
    };

    TooltipHTMLContent.prototype.dispose = function () {
      this.el.parentNode.removeChild(this.el);
    };

    TooltipHTMLContent.prototype.getOuterSize = function () {
      var width = this.el.clientWidth;
      var height = this.el.clientHeight;

      if (document.defaultView && document.defaultView.getComputedStyle) {
        var stl = document.defaultView.getComputedStyle(this.el);

        if (stl) {
          width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
          height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
        }
      }

      return {
        width: width,
        height: height
      };
    };

    return TooltipHTMLContent;
  }();

  var TooltipRichContent = function () {
    function TooltipRichContent(api) {
      this._show = false;
      this._styleCoord = [0, 0, 0, 0];
      this._enterable = true;
      this._zr = api.getZr();
      makeStyleCoord$1(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2);
    }

    TooltipRichContent.prototype.update = function (tooltipModel) {
      var alwaysShowContent = tooltipModel.get('alwaysShowContent');
      alwaysShowContent && this._moveIfResized();
    };

    TooltipRichContent.prototype.show = function () {
      if (this._hideTimeout) {
        clearTimeout(this._hideTimeout);
      }

      this.el.show();
      this._show = true;
    };

    TooltipRichContent.prototype.setContent = function (content, markupStyleCreator, tooltipModel, borderColor, arrowPosition) {
      if (isObject(content)) {
        throwError(true ? 'Passing DOM nodes as content is not supported in richText tooltip!' : '');
      }

      if (this.el) {
        this._zr.remove(this.el);
      }

      var textStyleModel = tooltipModel.getModel('textStyle');
      this.el = new ZRText({
        style: {
          rich: markupStyleCreator.richTextStyles,
          text: content,
          lineHeight: 22,
          backgroundColor: tooltipModel.get('backgroundColor'),
          borderRadius: tooltipModel.get('borderRadius'),
          borderWidth: 1,
          borderColor: borderColor,
          shadowColor: tooltipModel.get('shadowColor'),
          shadowBlur: tooltipModel.get('shadowBlur'),
          shadowOffsetX: tooltipModel.get('shadowOffsetX'),
          shadowOffsetY: tooltipModel.get('shadowOffsetY'),
          textShadowColor: textStyleModel.get('textShadowColor'),
          textShadowBlur: textStyleModel.get('textShadowBlur') || 0,
          textShadowOffsetX: textStyleModel.get('textShadowOffsetX') || 0,
          textShadowOffsetY: textStyleModel.get('textShadowOffsetY') || 0,
          fill: tooltipModel.get(['textStyle', 'color']),
          padding: getPaddingFromTooltipModel(tooltipModel, 'richText'),
          verticalAlign: 'top',
          align: 'left'
        },
        z: tooltipModel.get('z')
      });

      this._zr.add(this.el);

      var self = this;
      this.el.on('mouseover', function () {
        if (self._enterable) {
          clearTimeout(self._hideTimeout);
          self._show = true;
        }

        self._inContent = true;
      });
      this.el.on('mouseout', function () {
        if (self._enterable) {
          if (self._show) {
            self.hideLater(self._hideDelay);
          }
        }

        self._inContent = false;
      });
    };

    TooltipRichContent.prototype.setEnterable = function (enterable) {
      this._enterable = enterable;
    };

    TooltipRichContent.prototype.getSize = function () {
      var el = this.el;
      var bounding = this.el.getBoundingRect();
      var shadowOuterSize = calcShadowOuterSize(el.style);
      return [bounding.width + shadowOuterSize.left + shadowOuterSize.right, bounding.height + shadowOuterSize.top + shadowOuterSize.bottom];
    };

    TooltipRichContent.prototype.moveTo = function (x, y) {
      var el = this.el;

      if (el) {
        var styleCoord = this._styleCoord;
        makeStyleCoord$1(styleCoord, this._zr, x, y);
        x = styleCoord[0];
        y = styleCoord[1];
        var style = el.style;
        var borderWidth = mathMaxWith0(style.borderWidth || 0);
        var shadowOuterSize = calcShadowOuterSize(style);
        el.x = x + borderWidth + shadowOuterSize.left;
        el.y = y + borderWidth + shadowOuterSize.top;
        el.markRedraw();
      }
    };

    TooltipRichContent.prototype._moveIfResized = function () {
      var ratioX = this._styleCoord[2];
      var ratioY = this._styleCoord[3];
      this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight());
    };

    TooltipRichContent.prototype.hide = function () {
      if (this.el) {
        this.el.hide();
      }

      this._show = false;
    };

    TooltipRichContent.prototype.hideLater = function (time) {
      if (this._show && !(this._inContent && this._enterable)) {
        if (time) {
          this._hideDelay = time;
          this._show = false;
          this._hideTimeout = setTimeout(bind(this.hide, this), time);
        } else {
          this.hide();
        }
      }
    };

    TooltipRichContent.prototype.isShow = function () {
      return this._show;
    };

    TooltipRichContent.prototype.getOuterSize = function () {
      var size = this.getSize();
      return {
        width: size[0],
        height: size[1]
      };
    };

    TooltipRichContent.prototype.dispose = function () {
      this._zr.remove(this.el);
    };

    return TooltipRichContent;
  }();

  function mathMaxWith0(val) {
    return Math.max(0, val);
  }

  function calcShadowOuterSize(style) {
    var shadowBlur = mathMaxWith0(style.shadowBlur || 0);
    var shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0);
    var shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0);
    return {
      left: mathMaxWith0(shadowBlur - shadowOffsetX),
      right: mathMaxWith0(shadowBlur + shadowOffsetX),
      top: mathMaxWith0(shadowBlur - shadowOffsetY),
      bottom: mathMaxWith0(shadowBlur + shadowOffsetY)
    };
  }

  function makeStyleCoord$1(out, zr, zrX, zrY) {
    out[0] = zrX;
    out[1] = zrY;
    out[2] = out[0] / zr.getWidth();
    out[3] = out[1] / zr.getHeight();
  }

  var bind$2 = bind;
  var each$c = each;
  var parsePercent$3 = parsePercent$2;
  var proxyRect = new Rect({
    shape: {
      x: -1,
      y: -1,
      width: 2,
      height: 2
    }
  });

  var TooltipView = function (_super) {
    __extends(TooltipView, _super);

    function TooltipView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TooltipView.type;
      return _this;
    }

    TooltipView.prototype.init = function (ecModel, api) {
      if (env.node) {
        return;
      }

      var tooltipModel = ecModel.getComponent('tooltip');
      var renderMode = tooltipModel.get('renderMode');
      this._renderMode = getTooltipRenderMode(renderMode);
      this._tooltipContent = this._renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api.getDom(), api, {
        appendToBody: tooltipModel.get('appendToBody', true)
      });
    };

    TooltipView.prototype.render = function (tooltipModel, ecModel, api) {
      if (env.node) {
        return;
      }

      this.group.removeAll();
      this._tooltipModel = tooltipModel;
      this._ecModel = ecModel;
      this._api = api;
      this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
      var tooltipContent = this._tooltipContent;
      tooltipContent.update(tooltipModel);
      tooltipContent.setEnterable(tooltipModel.get('enterable'));

      this._initGlobalListener();

      this._keepShow();
    };

    TooltipView.prototype._initGlobalListener = function () {
      var tooltipModel = this._tooltipModel;
      var triggerOn = tooltipModel.get('triggerOn');
      register('itemTooltip', this._api, bind$2(function (currTrigger, e, dispatchAction) {
        if (triggerOn !== 'none') {
          if (triggerOn.indexOf(currTrigger) >= 0) {
            this._tryShow(e, dispatchAction);
          } else if (currTrigger === 'leave') {
            this._hide(dispatchAction);
          }
        }
      }, this));
    };

    TooltipView.prototype._keepShow = function () {
      var tooltipModel = this._tooltipModel;
      var ecModel = this._ecModel;
      var api = this._api;

      if (this._lastX != null && this._lastY != null && tooltipModel.get('triggerOn') !== 'none') {
        var self_1 = this;
        clearTimeout(this._refreshUpdateTimeout);
        this._refreshUpdateTimeout = setTimeout(function () {
          !api.isDisposed() && self_1.manuallyShowTip(tooltipModel, ecModel, api, {
            x: self_1._lastX,
            y: self_1._lastY,
            dataByCoordSys: self_1._lastDataByCoordSys
          });
        });
      }
    };

    TooltipView.prototype.manuallyShowTip = function (tooltipModel, ecModel, api, payload) {
      if (payload.from === this.uid || env.node) {
        return;
      }

      var dispatchAction = makeDispatchAction$1(payload, api);
      this._ticket = '';
      var dataByCoordSys = payload.dataByCoordSys;

      if (payload.tooltip && payload.x != null && payload.y != null) {
        var el = proxyRect;
        el.x = payload.x;
        el.y = payload.y;
        el.update();
        el.tooltip = payload.tooltip;

        this._tryShow({
          offsetX: payload.x,
          offsetY: payload.y,
          target: el
        }, dispatchAction);
      } else if (dataByCoordSys) {
        this._tryShow({
          offsetX: payload.x,
          offsetY: payload.y,
          position: payload.position,
          dataByCoordSys: dataByCoordSys,
          tooltipOption: payload.tooltipOption
        }, dispatchAction);
      } else if (payload.seriesIndex != null) {
        if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) {
          return;
        }

        var pointInfo = findPointFromSeries(payload, ecModel);
        var cx = pointInfo.point[0];
        var cy = pointInfo.point[1];

        if (cx != null && cy != null) {
          this._tryShow({
            offsetX: cx,
            offsetY: cy,
            position: payload.position,
            target: pointInfo.el
          }, dispatchAction);
        }
      } else if (payload.x != null && payload.y != null) {
        api.dispatchAction({
          type: 'updateAxisPointer',
          x: payload.x,
          y: payload.y
        });

        this._tryShow({
          offsetX: payload.x,
          offsetY: payload.y,
          position: payload.position,
          target: api.getZr().findHover(payload.x, payload.y).target
        }, dispatchAction);
      }
    };

    TooltipView.prototype.manuallyHideTip = function (tooltipModel, ecModel, api, payload) {
      var tooltipContent = this._tooltipContent;

      if (!this._alwaysShowContent && this._tooltipModel) {
        tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));
      }

      this._lastX = this._lastY = this._lastDataByCoordSys = null;

      if (payload.from !== this.uid) {
        this._hide(makeDispatchAction$1(payload, api));
      }
    };

    TooltipView.prototype._manuallyAxisShowTip = function (tooltipModel, ecModel, api, payload) {
      var seriesIndex = payload.seriesIndex;
      var dataIndex = payload.dataIndex;
      var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

      if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) {
        return;
      }

      var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

      if (!seriesModel) {
        return;
      }

      var data = seriesModel.getData();
      var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model, tooltipModel]);

      if (tooltipCascadedModel.get('trigger') !== 'axis') {
        return;
      }

      api.dispatchAction({
        type: 'updateAxisPointer',
        seriesIndex: seriesIndex,
        dataIndex: dataIndex,
        position: payload.position
      });
      return true;
    };

    TooltipView.prototype._tryShow = function (e, dispatchAction) {
      var el = e.target;
      var tooltipModel = this._tooltipModel;

      if (!tooltipModel) {
        return;
      }

      this._lastX = e.offsetX;
      this._lastY = e.offsetY;
      var dataByCoordSys = e.dataByCoordSys;

      if (dataByCoordSys && dataByCoordSys.length) {
        this._showAxisTooltip(dataByCoordSys, e);
      } else if (el && findEventDispatcher(el, function (target) {
        return getECData(target).dataIndex != null;
      })) {
        this._lastDataByCoordSys = null;

        this._showSeriesItemTooltip(e, el, dispatchAction);
      } else if (el && el.tooltip) {
        this._lastDataByCoordSys = null;

        this._showComponentItemTooltip(e, el, dispatchAction);
      } else {
        this._lastDataByCoordSys = null;

        this._hide(dispatchAction);
      }
    };

    TooltipView.prototype._showOrMove = function (tooltipModel, cb) {
      var delay = tooltipModel.get('showDelay');
      cb = bind(cb, this);
      clearTimeout(this._showTimout);
      delay > 0 ? this._showTimout = setTimeout(cb, delay) : cb();
    };

    TooltipView.prototype._showAxisTooltip = function (dataByCoordSys, e) {
      var ecModel = this._ecModel;
      var globalTooltipModel = this._tooltipModel;
      var point = [e.offsetX, e.offsetY];
      var singleTooltipModel = buildTooltipModel([e.tooltipOption, globalTooltipModel]);
      var renderMode = this._renderMode;
      var cbParamsList = [];
      var articleMarkup = createTooltipMarkup('section', {
        blocks: [],
        noHeader: true
      });
      var markupTextArrLegacy = [];
      var markupStyleCreator = new TooltipMarkupStyleCreator();
      each$c(dataByCoordSys, function (itemCoordSys) {
        each$c(itemCoordSys.dataByAxis, function (axisItem) {
          var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex);
          var axisValue = axisItem.value;

          if (!axisModel || axisValue == null) {
            return;
          }

          var axisValueLabel = getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt);
          var axisSectionMarkup = createTooltipMarkup('section', {
            header: axisValueLabel,
            noHeader: !trim(axisValueLabel),
            sortBlocks: true,
            blocks: []
          });
          articleMarkup.blocks.push(axisSectionMarkup);
          each(axisItem.seriesDataIndices, function (idxItem) {
            var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
            var dataIndex = idxItem.dataIndexInside;
            var cbParams = series.getDataParams(dataIndex);
            cbParams.axisDim = axisItem.axisDim;
            cbParams.axisIndex = axisItem.axisIndex;
            cbParams.axisType = axisItem.axisType;
            cbParams.axisId = axisItem.axisId;
            cbParams.axisValue = getAxisRawValue(axisModel.axis, {
              value: axisValue
            });
            cbParams.axisValueLabel = axisValueLabel;
            cbParams.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(cbParams.color), renderMode);
            var seriesTooltipResult = normalizeTooltipFormatResult(series.formatTooltip(dataIndex, true, null));

            if (seriesTooltipResult.markupFragment) {
              axisSectionMarkup.blocks.push(seriesTooltipResult.markupFragment);
            }

            if (seriesTooltipResult.markupText) {
              markupTextArrLegacy.push(seriesTooltipResult.markupText);
            }

            cbParamsList.push(cbParams);
          });
        });
      });
      articleMarkup.blocks.reverse();
      markupTextArrLegacy.reverse();
      var positionExpr = e.position;
      var orderMode = singleTooltipModel.get('order');
      var builtMarkupText = buildTooltipMarkup(articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'));
      builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText);
      var blockBreak = renderMode === 'richText' ? '\n\n' : '<br/>';
      var allMarkupText = markupTextArrLegacy.join(blockBreak);

      this._showOrMove(singleTooltipModel, function () {
        if (this._updateContentNotChangedOnAxis(dataByCoordSys)) {
          this._updatePosition(singleTooltipModel, positionExpr, point[0], point[1], this._tooltipContent, cbParamsList);
        } else {
          this._showTooltipContent(singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '', point[0], point[1], positionExpr, null, markupStyleCreator);
        }
      });
    };

    TooltipView.prototype._showSeriesItemTooltip = function (e, el, dispatchAction) {
      var dispatcher = findEventDispatcher(el, function (target) {
        return getECData(target).dataIndex != null;
      });
      var ecModel = this._ecModel;
      var ecData = getECData(dispatcher);
      var seriesIndex = ecData.seriesIndex;
      var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
      var dataModel = ecData.dataModel || seriesModel;
      var dataIndex = ecData.dataIndex;
      var dataType = ecData.dataType;
      var data = dataModel.getData(dataType);
      var renderMode = this._renderMode;
      var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model, this._tooltipModel]);
      var tooltipTrigger = tooltipModel.get('trigger');

      if (tooltipTrigger != null && tooltipTrigger !== 'item') {
        return;
      }

      var params = dataModel.getDataParams(dataIndex, dataType);
      var markupStyleCreator = new TooltipMarkupStyleCreator();
      params.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(params.color), renderMode);
      var seriesTooltipResult = normalizeTooltipFormatResult(dataModel.formatTooltip(dataIndex, false, dataType));
      var orderMode = tooltipModel.get('order');
      var markupText = seriesTooltipResult.markupFragment ? buildTooltipMarkup(seriesTooltipResult.markupFragment, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC')) : seriesTooltipResult.markupText;
      var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;

      this._showOrMove(tooltipModel, function () {
        this._showTooltipContent(tooltipModel, markupText, params, asyncTicket, e.offsetX, e.offsetY, e.position, e.target, markupStyleCreator);
      });

      dispatchAction({
        type: 'showTip',
        dataIndexInside: dataIndex,
        dataIndex: data.getRawIndex(dataIndex),
        seriesIndex: seriesIndex,
        from: this.uid
      });
    };

    TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) {
      var tooltipOpt = el.tooltip;

      if (isString(tooltipOpt)) {
        var content = tooltipOpt;
        tooltipOpt = {
          content: content,
          formatter: content
        };
      }

      var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel);
      var defaultHtml = subTooltipModel.get('content');
      var asyncTicket = Math.random() + '';
      var markupStyleCreator = new TooltipMarkupStyleCreator();

      this._showOrMove(subTooltipModel, function () {
        this._showTooltipContent(subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {}, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator);
      });

      dispatchAction({
        type: 'showTip',
        from: this.uid
      });
    };

    TooltipView.prototype._showTooltipContent = function (tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markupStyleCreator) {
      this._ticket = '';

      if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) {
        return;
      }

      var tooltipContent = this._tooltipContent;
      var formatter = tooltipModel.get('formatter');
      positionExpr = positionExpr || tooltipModel.get('position');
      var html = defaultHtml;

      var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'));

      if (formatter && isString(formatter)) {
        var useUTC = tooltipModel.ecModel.get('useUTC');
        var params0 = isArray(params) ? params[0] : params;
        var isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0;
        html = formatter;

        if (isTimeAxis) {
          html = format(params0.axisValue, html, useUTC);
        }

        html = formatTpl(html, params, true);
      } else if (isFunction(formatter)) {
        var callback = bind$2(function (cbTicket, html) {
          if (cbTicket === this._ticket) {
            tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr);

            this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
          }
        }, this);
        this._ticket = asyncTicket;
        html = formatter(params, asyncTicket, callback);
      }

      tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr);
      tooltipContent.show(tooltipModel, nearPoint.color);

      this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
    };

    TooltipView.prototype._getNearestPoint = function (point, tooltipDataParams, trigger) {
      if (trigger === 'axis' || isArray(tooltipDataParams)) {
        return {
          color: this._renderMode === 'html' ? '#fff' : 'none'
        };
      }

      if (!isArray(tooltipDataParams)) {
        return {
          color: tooltipDataParams.color || tooltipDataParams.borderColor
        };
      }
    };

    TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, y, content, params, el) {
      var viewWidth = this._api.getWidth();

      var viewHeight = this._api.getHeight();

      positionExpr = positionExpr || tooltipModel.get('position');
      var contentSize = content.getSize();
      var align = tooltipModel.get('align');
      var vAlign = tooltipModel.get('verticalAlign');
      var rect = el && el.getBoundingRect().clone();
      el && rect.applyTransform(el.transform);

      if (isFunction(positionExpr)) {
        positionExpr = positionExpr([x, y], params, content.el, rect, {
          viewSize: [viewWidth, viewHeight],
          contentSize: contentSize.slice()
        });
      }

      if (isArray(positionExpr)) {
        x = parsePercent$3(positionExpr[0], viewWidth);
        y = parsePercent$3(positionExpr[1], viewHeight);
      } else if (isObject(positionExpr)) {
        var boxLayoutPosition = positionExpr;
        boxLayoutPosition.width = contentSize[0];
        boxLayoutPosition.height = contentSize[1];
        var layoutRect = getLayoutRect(boxLayoutPosition, {
          width: viewWidth,
          height: viewHeight
        });
        x = layoutRect.x;
        y = layoutRect.y;
        align = null;
        vAlign = null;
      } else if (isString(positionExpr) && el) {
        var pos = calcTooltipPosition(positionExpr, rect, contentSize);
        x = pos[0];
        y = pos[1];
      } else {
        var pos = refixTooltipPosition(x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20);
        x = pos[0];
        y = pos[1];
      }

      align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0);
      vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0);

      if (shouldTooltipConfine(tooltipModel)) {
        var pos = confineTooltipPosition(x, y, content, viewWidth, viewHeight);
        x = pos[0];
        y = pos[1];
      }

      content.moveTo(x, y);
    };

    TooltipView.prototype._updateContentNotChangedOnAxis = function (dataByCoordSys) {
      var lastCoordSys = this._lastDataByCoordSys;
      var contentNotChanged = !!lastCoordSys && lastCoordSys.length === dataByCoordSys.length;
      contentNotChanged && each$c(lastCoordSys, function (lastItemCoordSys, indexCoordSys) {
        var lastDataByAxis = lastItemCoordSys.dataByAxis || [];
        var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {};
        var thisDataByAxis = thisItemCoordSys.dataByAxis || [];
        contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length;
        contentNotChanged && each$c(lastDataByAxis, function (lastItem, indexAxis) {
          var thisItem = thisDataByAxis[indexAxis] || {};
          var lastIndices = lastItem.seriesDataIndices || [];
          var newIndices = thisItem.seriesDataIndices || [];
          contentNotChanged = contentNotChanged && lastItem.value === thisItem.value && lastItem.axisType === thisItem.axisType && lastItem.axisId === thisItem.axisId && lastIndices.length === newIndices.length;
          contentNotChanged && each$c(lastIndices, function (lastIdxItem, j) {
            var newIdxItem = newIndices[j];
            contentNotChanged = contentNotChanged && lastIdxItem.seriesIndex === newIdxItem.seriesIndex && lastIdxItem.dataIndex === newIdxItem.dataIndex;
          });
        });
      });
      this._lastDataByCoordSys = dataByCoordSys;
      return !!contentNotChanged;
    };

    TooltipView.prototype._hide = function (dispatchAction) {
      this._lastDataByCoordSys = null;
      dispatchAction({
        type: 'hideTip',
        from: this.uid
      });
    };

    TooltipView.prototype.dispose = function (ecModel, api) {
      if (env.node) {
        return;
      }

      this._tooltipContent.dispose();

      unregister('itemTooltip', api);
    };

    TooltipView.type = 'tooltip';
    return TooltipView;
  }(ComponentView);

  function buildTooltipModel(modelCascade) {
    var resultModel = modelCascade.pop();

    while (modelCascade.length) {
      var tooltipOpt = modelCascade.pop();

      if (tooltipOpt) {
        if (tooltipOpt instanceof Model) {
          tooltipOpt = tooltipOpt.get('tooltip', true);
        }

        if (isString(tooltipOpt)) {
          tooltipOpt = {
            formatter: tooltipOpt
          };
        }

        resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel);
      }
    }

    return resultModel;
  }

  function makeDispatchAction$1(payload, api) {
    return payload.dispatchAction || bind(api.dispatchAction, api);
  }

  function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) {
    var size = content.getOuterSize();
    var width = size.width;
    var height = size.height;

    if (gapH != null) {
      if (x + width + gapH + 2 > viewWidth) {
        x -= width + gapH;
      } else {
        x += gapH;
      }
    }

    if (gapV != null) {
      if (y + height + gapV > viewHeight) {
        y -= height + gapV;
      } else {
        y += gapV;
      }
    }

    return [x, y];
  }

  function confineTooltipPosition(x, y, content, viewWidth, viewHeight) {
    var size = content.getOuterSize();
    var width = size.width;
    var height = size.height;
    x = Math.min(x + width, viewWidth) - width;
    y = Math.min(y + height, viewHeight) - height;
    x = Math.max(x, 0);
    y = Math.max(y, 0);
    return [x, y];
  }

  function calcTooltipPosition(position, rect, contentSize) {
    var domWidth = contentSize[0];
    var domHeight = contentSize[1];
    var gap = 10;
    var offset = 5;
    var x = 0;
    var y = 0;
    var rectWidth = rect.width;
    var rectHeight = rect.height;

    switch (position) {
      case 'inside':
        x = rect.x + rectWidth / 2 - domWidth / 2;
        y = rect.y + rectHeight / 2 - domHeight / 2;
        break;

      case 'top':
        x = rect.x + rectWidth / 2 - domWidth / 2;
        y = rect.y - domHeight - gap;
        break;

      case 'bottom':
        x = rect.x + rectWidth / 2 - domWidth / 2;
        y = rect.y + rectHeight + gap;
        break;

      case 'left':
        x = rect.x - domWidth - gap - offset;
        y = rect.y + rectHeight / 2 - domHeight / 2;
        break;

      case 'right':
        x = rect.x + rectWidth + gap + offset;
        y = rect.y + rectHeight / 2 - domHeight / 2;
    }

    return [x, y];
  }

  function isCenterAlign(align) {
    return align === 'center' || align === 'middle';
  }

  ComponentView.registerClass(TooltipView);
  registerAction({
    type: 'showTip',
    event: 'showTip',
    update: 'tooltip:manuallyShowTip'
  }, function () {});
  registerAction({
    type: 'hideTip',
    event: 'hideTip',
    update: 'tooltip:manuallyHideTip'
  }, function () {});
  var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear'];

  function brushPreprocessor(option, isNew) {
    var brushComponents = normalizeToArray(option ? option.brush : []);

    if (!brushComponents.length) {
      return;
    }

    var brushComponentSpecifiedBtns = [];
    each(brushComponents, function (brushOpt) {
      var tbs = brushOpt.hasOwnProperty('toolbox') ? brushOpt.toolbox : [];

      if (tbs instanceof Array) {
        brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs);
      }
    });
    var toolbox = option && option.toolbox;

    if (isArray(toolbox)) {
      toolbox = toolbox[0];
    }

    if (!toolbox) {
      toolbox = {
        feature: {}
      };
      option.toolbox = [toolbox];
    }

    var toolboxFeature = toolbox.feature || (toolbox.feature = {});
    var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {});
    var brushTypes = toolboxBrush.type || (toolboxBrush.type = []);
    brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns);
    removeDuplicate(brushTypes);

    if (isNew && !brushTypes.length) {
      brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS);
    }
  }

  function removeDuplicate(arr) {
    var map = {};
    each(arr, function (val) {
      map[val] = 1;
    });
    arr.length = 0;
    each(map, function (flag, val) {
      arr.push(val);
    });
  }

  var each$d = each;

  function hasKeys(obj) {
    if (obj) {
      for (var name_1 in obj) {
        if (obj.hasOwnProperty(name_1)) {
          return true;
        }
      }
    }
  }

  function createVisualMappings(option, stateList, supplementVisualOption) {
    var visualMappings = {};
    each$d(stateList, function (state) {
      var mappings = visualMappings[state] = createMappings();
      each$d(option[state], function (visualData, visualType) {
        if (!VisualMapping.isValidType(visualType)) {
          return;
        }

        var mappingOption = {
          type: visualType,
          visual: visualData
        };
        supplementVisualOption && supplementVisualOption(mappingOption, state);
        mappings[visualType] = new VisualMapping(mappingOption);

        if (visualType === 'opacity') {
          mappingOption = clone(mappingOption);
          mappingOption.type = 'colorAlpha';
          mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption);
        }
      });
    });
    return visualMappings;

    function createMappings() {
      var Creater = function () {};

      Creater.prototype.__hidden = Creater.prototype;
      var obj = new Creater();
      return obj;
    }
  }

  function replaceVisualOption(thisOption, newOption, keys) {
    var has;
    each(keys, function (key) {
      if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
        has = true;
      }
    });
    has && each(keys, function (key) {
      if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
        thisOption[key] = clone(newOption[key]);
      } else {
        delete thisOption[key];
      }
    });
  }

  function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) {
    var visualTypesMap = {};
    each(stateList, function (state) {
      var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
      visualTypesMap[state] = visualTypes;
    });
    var dataIndex;

    function getVisual(key) {
      return getItemVisualFromData(data, dataIndex, key);
    }

    function setVisual(key, value) {
      setItemVisualFromData(data, dataIndex, key, value);
    }

    if (dimension == null) {
      data.each(eachItem);
    } else {
      data.each([dimension], eachItem);
    }

    function eachItem(valueOrIndex, index) {
      dataIndex = dimension == null ? valueOrIndex : index;
      var rawDataItem = data.getRawDataItem(dataIndex);

      if (rawDataItem && rawDataItem.visualMap === false) {
        return;
      }

      var valueState = getValueState.call(scope, valueOrIndex);
      var mappings = visualMappings[valueState];
      var visualTypes = visualTypesMap[valueState];

      for (var i = 0, len = visualTypes.length; i < len; i++) {
        var type = visualTypes[i];
        mappings[type] && mappings[type].applyVisual(valueOrIndex, getVisual, setVisual);
      }
    }
  }

  function incrementalApplyVisual(stateList, visualMappings, getValueState, dim) {
    var visualTypesMap = {};
    each(stateList, function (state) {
      var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
      visualTypesMap[state] = visualTypes;
    });
    return {
      progress: function progress(params, data) {
        var dimName;

        if (dim != null) {
          dimName = data.getDimension(dim);
        }

        function getVisual(key) {
          return getItemVisualFromData(data, dataIndex, key);
        }

        function setVisual(key, value) {
          setItemVisualFromData(data, dataIndex, key, value);
        }

        var dataIndex;

        while ((dataIndex = params.next()) != null) {
          var rawDataItem = data.getRawDataItem(dataIndex);

          if (rawDataItem && rawDataItem.visualMap === false) {
            continue;
          }

          var value = dim != null ? data.get(dimName, dataIndex) : dataIndex;
          var valueState = getValueState(value);
          var mappings = visualMappings[valueState];
          var visualTypes = visualTypesMap[valueState];

          for (var i = 0, len = visualTypes.length; i < len; i++) {
            var type = visualTypes[i];
            mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual);
          }
        }
      }
    };
  }

  function makeBrushCommonSelectorForSeries(area) {
    var brushType = area.brushType;
    var selectors = {
      point: function (itemLayout) {
        return selector[brushType].point(itemLayout, selectors, area);
      },
      rect: function (itemLayout) {
        return selector[brushType].rect(itemLayout, selectors, area);
      }
    };
    return selectors;
  }

  var selector = {
    lineX: getLineSelectors(0),
    lineY: getLineSelectors(1),
    rect: {
      point: function (itemLayout, selectors, area) {
        return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]);
      },
      rect: function (itemLayout, selectors, area) {
        return itemLayout && area.boundingRect.intersect(itemLayout);
      }
    },
    polygon: {
      point: function (itemLayout, selectors, area) {
        return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]) && contain$2(area.range, itemLayout[0], itemLayout[1]);
      },
      rect: function (itemLayout, selectors, area) {
        var points = area.range;

        if (!itemLayout || points.length <= 1) {
          return false;
        }

        var x = itemLayout.x;
        var y = itemLayout.y;
        var width = itemLayout.width;
        var height = itemLayout.height;
        var p = points[0];

        if (contain$2(points, x, y) || contain$2(points, x + width, y) || contain$2(points, x, y + height) || contain$2(points, x + width, y + height) || BoundingRect.create(itemLayout).contain(p[0], p[1]) || linePolygonIntersect(x, y, x + width, y, points) || linePolygonIntersect(x, y, x, y + height, points) || linePolygonIntersect(x + width, y, x + width, y + height, points) || linePolygonIntersect(x, y + height, x + width, y + height, points)) {
          return true;
        }
      }
    }
  };

  function getLineSelectors(xyIndex) {
    var xy = ['x', 'y'];
    var wh = ['width', 'height'];
    return {
      point: function (itemLayout, selectors, area) {
        if (itemLayout) {
          var range = area.range;
          var p = itemLayout[xyIndex];
          return inLineRange(p, range);
        }
      },
      rect: function (itemLayout, selectors, area) {
        if (itemLayout) {
          var range = area.range;
          var layoutRange = [itemLayout[xy[xyIndex]], itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]]];
          layoutRange[1] < layoutRange[0] && layoutRange.reverse();
          return inLineRange(layoutRange[0], range) || inLineRange(layoutRange[1], range) || inLineRange(range[0], layoutRange) || inLineRange(range[1], layoutRange);
        }
      }
    };
  }

  function inLineRange(p, range) {
    return range[0] <= p && p <= range[1];
  }

  var STATE_LIST = ['inBrush', 'outOfBrush'];
  var DISPATCH_METHOD = '__ecBrushSelect';
  var DISPATCH_FLAG = '__ecInBrushSelectEvent';
  var PRIORITY_BRUSH = PRIORITY.VISUAL.BRUSH;

  function layoutCovers(ecModel) {
    ecModel.eachComponent({
      mainType: 'brush'
    }, function (brushModel) {
      var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);
      brushTargetManager.setInputRanges(brushModel.areas, ecModel);
    });
  }

  registerVisual(PRIORITY_BRUSH, function (ecModel, api, payload) {
    var brushSelected = [];
    var throttleType;
    var throttleDelay;
    ecModel.eachComponent({
      mainType: 'brush'
    }, function (brushModel) {
      payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : {
        brushType: false
      });
    });
    layoutCovers(ecModel);
    ecModel.eachComponent({
      mainType: 'brush'
    }, function (brushModel, brushIndex) {
      var thisBrushSelected = {
        brushId: brushModel.id,
        brushIndex: brushIndex,
        brushName: brushModel.name,
        areas: clone(brushModel.areas),
        selected: []
      };
      brushSelected.push(thisBrushSelected);
      var brushOption = brushModel.option;
      var brushLink = brushOption.brushLink;
      var linkedSeriesMap = [];
      var selectedDataIndexForLink = [];
      var rangeInfoBySeries = [];
      var hasBrushExists = false;

      if (!brushIndex) {
        throttleType = brushOption.throttleType;
        throttleDelay = brushOption.throttleDelay;
      }

      var areas = map(brushModel.areas, function (area) {
        var builder = boundingRectBuilders[area.brushType];
        var selectableArea = defaults({
          boundingRect: builder ? builder(area) : void 0
        }, area);
        selectableArea.selectors = makeBrushCommonSelectorForSeries(selectableArea);
        return selectableArea;
      });
      var visualMappings = createVisualMappings(brushModel.option, STATE_LIST, function (mappingOption) {
        mappingOption.mappingMethod = 'fixed';
      });
      isArray(brushLink) && each(brushLink, function (seriesIndex) {
        linkedSeriesMap[seriesIndex] = 1;
      });

      function linkOthers(seriesIndex) {
        return brushLink === 'all' || !!linkedSeriesMap[seriesIndex];
      }

      function brushed(rangeInfoList) {
        return !!rangeInfoList.length;
      }

      ecModel.eachSeries(function (seriesModel, seriesIndex) {
        var rangeInfoList = rangeInfoBySeries[seriesIndex] = [];
        seriesModel.subType === 'parallel' ? stepAParallel(seriesModel, seriesIndex) : stepAOthers(seriesModel, seriesIndex, rangeInfoList);
      });

      function stepAParallel(seriesModel, seriesIndex) {
        var coordSys = seriesModel.coordinateSystem;
        hasBrushExists = hasBrushExists || coordSys.hasAxisBrushed();
        linkOthers(seriesIndex) && coordSys.eachActiveState(seriesModel.getData(), function (activeState, dataIndex) {
          activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1);
        });
      }

      function stepAOthers(seriesModel, seriesIndex, rangeInfoList) {
        if (!seriesModel.brushSelector || brushModelNotControll(brushModel, seriesIndex)) {
          return;
        }

        each(areas, function (area) {
          if (brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)) {
            rangeInfoList.push(area);
          }

          hasBrushExists = hasBrushExists || brushed(rangeInfoList);
        });

        if (linkOthers(seriesIndex) && brushed(rangeInfoList)) {
          var data_1 = seriesModel.getData();
          data_1.each(function (dataIndex) {
            if (checkInRange(seriesModel, rangeInfoList, data_1, dataIndex)) {
              selectedDataIndexForLink[dataIndex] = 1;
            }
          });
        }
      }

      ecModel.eachSeries(function (seriesModel, seriesIndex) {
        var seriesBrushSelected = {
          seriesId: seriesModel.id,
          seriesIndex: seriesIndex,
          seriesName: seriesModel.name,
          dataIndex: []
        };
        thisBrushSelected.selected.push(seriesBrushSelected);
        var rangeInfoList = rangeInfoBySeries[seriesIndex];
        var data = seriesModel.getData();
        var getValueState = linkOthers(seriesIndex) ? function (dataIndex) {
          return selectedDataIndexForLink[dataIndex] ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush';
        } : function (dataIndex) {
          return checkInRange(seriesModel, rangeInfoList, data, dataIndex) ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush';
        };
        (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) && applyVisual(STATE_LIST, visualMappings, data, getValueState);
      });
    });
    dispatchAction(api, throttleType, throttleDelay, brushSelected, payload);
  });

  function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) {
    if (!payload) {
      return;
    }

    var zr = api.getZr();

    if (zr[DISPATCH_FLAG]) {
      return;
    }

    if (!zr[DISPATCH_METHOD]) {
      zr[DISPATCH_METHOD] = doDispatch;
    }

    var fn = createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType);
    fn(api, brushSelected);
  }

  function doDispatch(api, brushSelected) {
    if (!api.isDisposed()) {
      var zr = api.getZr();
      zr[DISPATCH_FLAG] = true;
      api.dispatchAction({
        type: 'brushSelect',
        batch: brushSelected
      });
      zr[DISPATCH_FLAG] = false;
    }
  }

  function checkInRange(seriesModel, rangeInfoList, data, dataIndex) {
    for (var i = 0, len = rangeInfoList.length; i < len; i++) {
      var area = rangeInfoList[i];

      if (seriesModel.brushSelector(dataIndex, data, area.selectors, area)) {
        return true;
      }
    }
  }

  function brushModelNotControll(brushModel, seriesIndex) {
    var seriesIndices = brushModel.option.seriesIndex;
    return seriesIndices != null && seriesIndices !== 'all' && (isArray(seriesIndices) ? indexOf(seriesIndices, seriesIndex) < 0 : seriesIndex !== seriesIndices);
  }

  var boundingRectBuilders = {
    rect: function (area) {
      return getBoundingRectFromMinMax(area.range);
    },
    polygon: function (area) {
      var minMax;
      var range = area.range;

      for (var i = 0, len = range.length; i < len; i++) {
        minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]];
        var rg = range[i];
        rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]);
        rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]);
        rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]);
        rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]);
      }

      return minMax && getBoundingRectFromMinMax(minMax);
    }
  };

  function getBoundingRectFromMinMax(minMax) {
    return new BoundingRect(minMax[0][0], minMax[1][0], minMax[0][1] - minMax[0][0], minMax[1][1] - minMax[1][0]);
  }

  var DEFAULT_OUT_OF_BRUSH_COLOR = '#ddd';

  var BrushModel = function (_super) {
    __extends(BrushModel, _super);

    function BrushModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BrushModel.type;
      _this.areas = [];
      _this.brushOption = {};
      return _this;
    }

    BrushModel.prototype.optionUpdated = function (newOption, isInit) {
      var thisOption = this.option;
      !isInit && replaceVisualOption(thisOption, newOption, ['inBrush', 'outOfBrush']);
      var inBrush = thisOption.inBrush = thisOption.inBrush || {};
      thisOption.outOfBrush = thisOption.outOfBrush || {
        color: DEFAULT_OUT_OF_BRUSH_COLOR
      };

      if (!inBrush.hasOwnProperty('liftZ')) {
        inBrush.liftZ = 5;
      }
    };

    BrushModel.prototype.setAreas = function (areas) {
      if (true) {
        assert(isArray(areas));
        each(areas, function (area) {
          assert(area.brushType, 'Illegal areas');
        });
      }

      if (!areas) {
        return;
      }

      this.areas = map(areas, function (area) {
        return generateBrushOption(this.option, area);
      }, this);
    };

    BrushModel.prototype.setBrushOption = function (brushOption) {
      this.brushOption = generateBrushOption(this.option, brushOption);
      this.brushType = this.brushOption.brushType;
    };

    BrushModel.type = 'brush';
    BrushModel.dependencies = ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'];
    BrushModel.defaultOption = {
      seriesIndex: 'all',
      brushType: 'rect',
      brushMode: 'single',
      transformable: true,
      brushStyle: {
        borderWidth: 1,
        color: 'rgba(210,219,238,0.3)',
        borderColor: '#D2DBEE'
      },
      throttleType: 'fixRate',
      throttleDelay: 0,
      removeOnClick: true,
      z: 10000
    };
    return BrushModel;
  }(ComponentModel);

  ComponentModel.registerClass(BrushModel);

  function generateBrushOption(option, brushOption) {
    return merge({
      brushType: option.brushType,
      brushMode: option.brushMode,
      transformable: option.transformable,
      brushStyle: new Model(option.brushStyle).getItemStyle(),
      removeOnClick: option.removeOnClick,
      z: option.z
    }, brushOption, true);
  }

  var BrushView = function (_super) {
    __extends(BrushView, _super);

    function BrushView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = BrushView.type;
      return _this;
    }

    BrushView.prototype.init = function (ecModel, api) {
      this.ecModel = ecModel;
      this.api = api;
      this.model;
      (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this)).mount();
    };

    BrushView.prototype.render = function (brushModel, ecModel, api, payload) {
      this.model = brushModel;

      this._updateController(brushModel, ecModel, api, payload);
    };

    BrushView.prototype.updateTransform = function (brushModel, ecModel, api, payload) {
      layoutCovers(ecModel);

      this._updateController(brushModel, ecModel, api, payload);
    };

    BrushView.prototype.updateVisual = function (brushModel, ecModel, api, payload) {
      this.updateTransform(brushModel, ecModel, api, payload);
    };

    BrushView.prototype.updateView = function (brushModel, ecModel, api, payload) {
      this._updateController(brushModel, ecModel, api, payload);
    };

    BrushView.prototype._updateController = function (brushModel, ecModel, api, payload) {
      (!payload || payload.$from !== brushModel.id) && this._brushController.setPanels(brushModel.brushTargetManager.makePanelOpts(api)).enableBrush(brushModel.brushOption).updateCovers(brushModel.areas.slice());
    };

    BrushView.prototype.dispose = function () {
      this._brushController.dispose();
    };

    BrushView.prototype._onBrush = function (eventParam) {
      var modelId = this.model.id;
      var areas = this.model.brushTargetManager.setOutputRanges(eventParam.areas, this.ecModel);
      (!eventParam.isEnd || eventParam.removeOnClick) && this.api.dispatchAction({
        type: 'brush',
        brushId: modelId,
        areas: clone(areas),
        $from: modelId
      });
      eventParam.isEnd && this.api.dispatchAction({
        type: 'brushEnd',
        brushId: modelId,
        areas: clone(areas),
        $from: modelId
      });
    };

    BrushView.type = 'brush';
    return BrushView;
  }(ComponentView);

  ComponentView.registerClass(BrushView);
  registerAction({
    type: 'brush',
    event: 'brush',
    update: 'updateVisual'
  }, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'brush',
      query: payload
    }, function (brushModel) {
      brushModel.setAreas(payload.areas);
    });
  });
  registerAction({
    type: 'brushSelect',
    event: 'brushSelected',
    update: 'none'
  }, function () {});
  registerAction({
    type: 'brushEnd',
    event: 'brushEnd',
    update: 'none'
  }, function () {});
  var ICON_TYPES = ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'];

  var BrushFeature = function (_super) {
    __extends(BrushFeature, _super);

    function BrushFeature() {
      return _super !== null && _super.apply(this, arguments) || this;
    }

    BrushFeature.prototype.render = function (featureModel, ecModel, api) {
      var brushType;
      var brushMode;
      var isBrushed;
      ecModel.eachComponent({
        mainType: 'brush'
      }, function (brushModel) {
        brushType = brushModel.brushType;
        brushMode = brushModel.brushOption.brushMode || 'single';
        isBrushed = isBrushed || !!brushModel.areas.length;
      });
      this._brushType = brushType;
      this._brushMode = brushMode;
      each(featureModel.get('type', true), function (type) {
        featureModel.setIconStatus(type, (type === 'keep' ? brushMode === 'multiple' : type === 'clear' ? isBrushed : type === brushType) ? 'emphasis' : 'normal');
      });
    };

    BrushFeature.prototype.updateView = function (featureModel, ecModel, api) {
      this.render(featureModel, ecModel, api);
    };

    BrushFeature.prototype.getIcons = function () {
      var model = this.model;
      var availableIcons = model.get('icon', true);
      var icons = {};
      each(model.get('type', true), function (type) {
        if (availableIcons[type]) {
          icons[type] = availableIcons[type];
        }
      });
      return icons;
    };

    BrushFeature.prototype.onclick = function (ecModel, api, type) {
      var brushType = this._brushType;
      var brushMode = this._brushMode;

      if (type === 'clear') {
        api.dispatchAction({
          type: 'axisAreaSelect',
          intervals: []
        });
        api.dispatchAction({
          type: 'brush',
          command: 'clear',
          areas: []
        });
      } else {
        api.dispatchAction({
          type: 'takeGlobalCursor',
          key: 'brush',
          brushOption: {
            brushType: type === 'keep' ? brushType : brushType === type ? false : type,
            brushMode: type === 'keep' ? brushMode === 'multiple' ? 'single' : 'multiple' : brushMode
          }
        });
      }
    };

    BrushFeature.getDefaultOption = function (ecModel) {
      var defaultOption = {
        show: true,
        type: ICON_TYPES.slice(),
        icon: {
          rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13',
          polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2',
          lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4',
          lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4',
          keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z',
          clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2'
        },
        title: ecModel.getLocale(['toolbox', 'brush', 'title'])
      };
      return defaultOption;
    };

    return BrushFeature;
  }(ToolboxFeature);

  registerFeature('brush', BrushFeature);
  registerPreprocessor(brushPreprocessor);

  var TitleModel = function (_super) {
    __extends(TitleModel, _super);

    function TitleModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TitleModel.type;
      _this.layoutMode = {
        type: 'box',
        ignoreSize: true
      };
      return _this;
    }

    TitleModel.type = 'title';
    TitleModel.defaultOption = {
      zlevel: 0,
      z: 6,
      show: true,
      text: '',
      target: 'blank',
      subtext: '',
      subtarget: 'blank',
      left: 0,
      top: 0,
      backgroundColor: 'rgba(0,0,0,0)',
      borderColor: '#ccc',
      borderWidth: 0,
      padding: 5,
      itemGap: 10,
      textStyle: {
        fontSize: 18,
        fontWeight: 'bold',
        color: '#464646'
      },
      subtextStyle: {
        fontSize: 12,
        color: '#6E7079'
      }
    };
    return TitleModel;
  }(ComponentModel);

  ComponentModel.registerClass(TitleModel);

  var TitleView = function (_super) {
    __extends(TitleView, _super);

    function TitleView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TitleView.type;
      return _this;
    }

    TitleView.prototype.render = function (titleModel, ecModel, api) {
      this.group.removeAll();

      if (!titleModel.get('show')) {
        return;
      }

      var group = this.group;
      var textStyleModel = titleModel.getModel('textStyle');
      var subtextStyleModel = titleModel.getModel('subtextStyle');
      var textAlign = titleModel.get('textAlign');
      var textVerticalAlign = retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign'));
      var textEl = new ZRText({
        style: createTextStyle(textStyleModel, {
          text: titleModel.get('text'),
          fill: textStyleModel.getTextColor()
        }, {
          disableBox: true
        }),
        z2: 10
      });
      var textRect = textEl.getBoundingRect();
      var subText = titleModel.get('subtext');
      var subTextEl = new ZRText({
        style: createTextStyle(subtextStyleModel, {
          text: subText,
          fill: subtextStyleModel.getTextColor(),
          y: textRect.height + titleModel.get('itemGap'),
          verticalAlign: 'top'
        }, {
          disableBox: true
        }),
        z2: 10
      });
      var link = titleModel.get('link');
      var sublink = titleModel.get('sublink');
      var triggerEvent = titleModel.get('triggerEvent', true);
      textEl.silent = !link && !triggerEvent;
      subTextEl.silent = !sublink && !triggerEvent;

      if (link) {
        textEl.on('click', function () {
          windowOpen(link, '_' + titleModel.get('target'));
        });
      }

      if (sublink) {
        subTextEl.on('click', function () {
          windowOpen(sublink, '_' + titleModel.get('subtarget'));
        });
      }

      getECData(textEl).eventData = getECData(subTextEl).eventData = triggerEvent ? {
        componentType: 'title',
        componentIndex: titleModel.componentIndex
      } : null;
      group.add(textEl);
      subText && group.add(subTextEl);
      var groupRect = group.getBoundingRect();
      var layoutOption = titleModel.getBoxLayoutParams();
      layoutOption.width = groupRect.width;
      layoutOption.height = groupRect.height;
      var layoutRect = getLayoutRect(layoutOption, {
        width: api.getWidth(),
        height: api.getHeight()
      }, titleModel.get('padding'));

      if (!textAlign) {
        textAlign = titleModel.get('left') || titleModel.get('right');

        if (textAlign === 'middle') {
          textAlign = 'center';
        }

        if (textAlign === 'right') {
          layoutRect.x += layoutRect.width;
        } else if (textAlign === 'center') {
          layoutRect.x += layoutRect.width / 2;
        }
      }

      if (!textVerticalAlign) {
        textVerticalAlign = titleModel.get('top') || titleModel.get('bottom');

        if (textVerticalAlign === 'center') {
          textVerticalAlign = 'middle';
        }

        if (textVerticalAlign === 'bottom') {
          layoutRect.y += layoutRect.height;
        } else if (textVerticalAlign === 'middle') {
          layoutRect.y += layoutRect.height / 2;
        }

        textVerticalAlign = textVerticalAlign || 'top';
      }

      group.x = layoutRect.x;
      group.y = layoutRect.y;
      group.markRedraw();
      var alignStyle = {
        align: textAlign,
        verticalAlign: textVerticalAlign
      };
      textEl.setStyle(alignStyle);
      subTextEl.setStyle(alignStyle);
      groupRect = group.getBoundingRect();
      var padding = layoutRect.margin;
      var style = titleModel.getItemStyle(['color', 'opacity']);
      style.fill = titleModel.get('backgroundColor');
      var rect = new Rect({
        shape: {
          x: groupRect.x - padding[3],
          y: groupRect.y - padding[0],
          width: groupRect.width + padding[1] + padding[3],
          height: groupRect.height + padding[0] + padding[2],
          r: titleModel.get('borderRadius')
        },
        style: style,
        subPixelOptimize: true,
        silent: true
      });
      group.add(rect);
    };

    TitleView.type = 'title';
    return TitleView;
  }(ComponentView);

  ComponentView.registerClass(TitleView);

  function timelinePreprocessor(option) {
    var timelineOpt = option && option.timeline;

    if (!isArray(timelineOpt)) {
      timelineOpt = timelineOpt ? [timelineOpt] : [];
    }

    each(timelineOpt, function (opt) {
      if (!opt) {
        return;
      }

      compatibleEC2(opt);
    });
  }

  function compatibleEC2(opt) {
    var type = opt.type;
    var ec2Types = {
      'number': 'value',
      'time': 'time'
    };

    if (ec2Types[type]) {
      opt.axisType = ec2Types[type];
      delete opt.type;
    }

    transferItem(opt);

    if (has(opt, 'controlPosition')) {
      var controlStyle = opt.controlStyle || (opt.controlStyle = {});

      if (!has(controlStyle, 'position')) {
        controlStyle.position = opt.controlPosition;
      }

      if (controlStyle.position === 'none' && !has(controlStyle, 'show')) {
        controlStyle.show = false;
        delete controlStyle.position;
      }

      delete opt.controlPosition;
    }

    each(opt.data || [], function (dataItem) {
      if (isObject(dataItem) && !isArray(dataItem)) {
        if (!has(dataItem, 'value') && has(dataItem, 'name')) {
          dataItem.value = dataItem.name;
        }

        transferItem(dataItem);
      }
    });
  }

  function transferItem(opt) {
    var itemStyle = opt.itemStyle || (opt.itemStyle = {});
    var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {});
    var label = opt.label || opt.label || {};
    var labelNormal = label.normal || (label.normal = {});
    var excludeLabelAttr = {
      normal: 1,
      emphasis: 1
    };
    each(label, function (value, name) {
      if (!excludeLabelAttr[name] && !has(labelNormal, name)) {
        labelNormal[name] = value;
      }
    });

    if (itemStyleEmphasis.label && !has(label, 'emphasis')) {
      label.emphasis = itemStyleEmphasis.label;
      delete itemStyleEmphasis.label;
    }
  }

  function has(obj, attr) {
    return obj.hasOwnProperty(attr);
  }

  ComponentModel.registerSubTypeDefaulter('timeline', function () {
    return 'slider';
  });
  registerAction({
    type: 'timelineChange',
    event: 'timelineChanged',
    update: 'prepareAndUpdate'
  }, function (payload, ecModel) {
    var timelineModel = ecModel.getComponent('timeline');

    if (timelineModel && payload.currentIndex != null) {
      timelineModel.setCurrentIndex(payload.currentIndex);

      if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) {
        timelineModel.setPlayState(false);
      }
    }

    ecModel.resetOption('timeline', {
      replaceMerge: timelineModel.get('replaceMerge', true)
    });
    return defaults({
      currentIndex: timelineModel.option.currentIndex
    }, payload);
  });
  registerAction({
    type: 'timelinePlayChange',
    event: 'timelinePlayChanged',
    update: 'update'
  }, function (payload, ecModel) {
    var timelineModel = ecModel.getComponent('timeline');

    if (timelineModel && payload.playState != null) {
      timelineModel.setPlayState(payload.playState);
    }
  });

  var TimelineModel = function (_super) {
    __extends(TimelineModel, _super);

    function TimelineModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TimelineModel.type;
      _this.layoutMode = 'box';
      return _this;
    }

    TimelineModel.prototype.init = function (option, parentModel, ecModel) {
      this.mergeDefaultAndTheme(option, ecModel);

      this._initData();
    };

    TimelineModel.prototype.mergeOption = function (option) {
      _super.prototype.mergeOption.apply(this, arguments);

      this._initData();
    };

    TimelineModel.prototype.setCurrentIndex = function (currentIndex) {
      if (currentIndex == null) {
        currentIndex = this.option.currentIndex;
      }

      var count = this._data.count();

      if (this.option.loop) {
        currentIndex = (currentIndex % count + count) % count;
      } else {
        currentIndex >= count && (currentIndex = count - 1);
        currentIndex < 0 && (currentIndex = 0);
      }

      this.option.currentIndex = currentIndex;
    };

    TimelineModel.prototype.getCurrentIndex = function () {
      return this.option.currentIndex;
    };

    TimelineModel.prototype.isIndexMax = function () {
      return this.getCurrentIndex() >= this._data.count() - 1;
    };

    TimelineModel.prototype.setPlayState = function (state) {
      this.option.autoPlay = !!state;
    };

    TimelineModel.prototype.getPlayState = function () {
      return !!this.option.autoPlay;
    };

    TimelineModel.prototype._initData = function () {
      var thisOption = this.option;
      var dataArr = thisOption.data || [];
      var axisType = thisOption.axisType;
      var names = this._names = [];
      var processedDataArr;

      if (axisType === 'category') {
        processedDataArr = [];
        each(dataArr, function (item, index) {
          var value = convertOptionIdName(getDataItemValue(item), '');
          var newItem;

          if (isObject(item)) {
            newItem = clone(item);
            newItem.value = index;
          } else {
            newItem = index;
          }

          processedDataArr.push(newItem);
          names.push(value);
        });
      } else {
        processedDataArr = dataArr;
      }

      var dimType = {
        category: 'ordinal',
        time: 'time',
        value: 'number'
      }[axisType] || 'number';
      var data = this._data = new List([{
        name: 'value',
        type: dimType
      }], this);
      data.initData(processedDataArr, names);
    };

    TimelineModel.prototype.getData = function () {
      return this._data;
    };

    TimelineModel.prototype.getCategories = function () {
      if (this.get('axisType') === 'category') {
        return this._names.slice();
      }
    };

    TimelineModel.type = 'timeline';
    TimelineModel.defaultOption = {
      zlevel: 0,
      z: 4,
      show: true,
      axisType: 'time',
      realtime: true,
      left: '20%',
      top: null,
      right: '20%',
      bottom: 0,
      width: null,
      height: 40,
      padding: 5,
      controlPosition: 'left',
      autoPlay: false,
      rewind: false,
      loop: true,
      playInterval: 2000,
      currentIndex: 0,
      itemStyle: {},
      label: {
        color: '#000'
      },
      data: []
    };
    return TimelineModel;
  }(ComponentModel);

  ComponentModel.registerClass(TimelineModel);

  var SliderTimelineModel = function (_super) {
    __extends(SliderTimelineModel, _super);

    function SliderTimelineModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SliderTimelineModel.type;
      return _this;
    }

    SliderTimelineModel.type = 'timeline.slider';
    SliderTimelineModel.defaultOption = inheritDefaultOption(TimelineModel.defaultOption, {
      backgroundColor: 'rgba(0,0,0,0)',
      borderColor: '#ccc',
      borderWidth: 0,
      orient: 'horizontal',
      inverse: false,
      tooltip: {
        trigger: 'item'
      },
      symbol: 'circle',
      symbolSize: 12,
      lineStyle: {
        show: true,
        width: 2,
        color: '#DAE1F5'
      },
      label: {
        position: 'auto',
        show: true,
        interval: 'auto',
        rotate: 0,
        color: '#A4B1D7'
      },
      itemStyle: {
        color: '#A4B1D7',
        borderWidth: 1
      },
      checkpointStyle: {
        symbol: 'circle',
        symbolSize: 15,
        color: '#316bf3',
        borderColor: '#fff',
        borderWidth: 2,
        shadowBlur: 2,
        shadowOffsetX: 1,
        shadowOffsetY: 1,
        shadowColor: 'rgba(0, 0, 0, 0.3)',
        animation: true,
        animationDuration: 300,
        animationEasing: 'quinticInOut'
      },
      controlStyle: {
        show: true,
        showPlayBtn: true,
        showPrevBtn: true,
        showNextBtn: true,
        itemSize: 24,
        itemGap: 12,
        position: 'left',
        playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z',
        stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z',
        nextIcon: 'M2,18.5A1.52,1.52,0,0,1,.92,18a1.49,1.49,0,0,1,0-2.12L7.81,9.36,1,3.11A1.5,1.5,0,1,1,3,.89l8,7.34a1.48,1.48,0,0,1,.49,1.09,1.51,1.51,0,0,1-.46,1.1L3,18.08A1.5,1.5,0,0,1,2,18.5Z',
        prevIcon: 'M10,.5A1.52,1.52,0,0,1,11.08,1a1.49,1.49,0,0,1,0,2.12L4.19,9.64,11,15.89a1.5,1.5,0,1,1-2,2.22L1,10.77A1.48,1.48,0,0,1,.5,9.68,1.51,1.51,0,0,1,1,8.58L9,.92A1.5,1.5,0,0,1,10,.5Z',
        prevBtnSize: 18,
        nextBtnSize: 18,
        color: '#A4B1D7',
        borderColor: '#A4B1D7',
        borderWidth: 1
      },
      emphasis: {
        label: {
          show: true,
          color: '#6f778d'
        },
        itemStyle: {
          color: '#316BF3'
        },
        controlStyle: {
          color: '#316BF3',
          borderColor: '#316BF3',
          borderWidth: 2
        }
      },
      progress: {
        lineStyle: {
          color: '#316BF3'
        },
        itemStyle: {
          color: '#316BF3'
        },
        label: {
          color: '#6f778d'
        }
      },
      data: []
    });
    return SliderTimelineModel;
  }(TimelineModel);

  mixin(SliderTimelineModel, DataFormatMixin.prototype);
  ComponentModel.registerClass(SliderTimelineModel);

  var TimelineView = function (_super) {
    __extends(TimelineView, _super);

    function TimelineView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = TimelineView.type;
      return _this;
    }

    TimelineView.type = 'timeline';
    return TimelineView;
  }(ComponentView);

  var TimelineAxis = function (_super) {
    __extends(TimelineAxis, _super);

    function TimelineAxis(dim, scale, coordExtent, axisType) {
      var _this = _super.call(this, dim, scale, coordExtent) || this;

      _this.type = axisType || 'value';
      return _this;
    }

    TimelineAxis.prototype.getLabelModel = function () {
      return this.model.getModel('label');
    };

    TimelineAxis.prototype.isHorizontal = function () {
      return this.model.get('orient') === 'horizontal';
    };

    return TimelineAxis;
  }(Axis);

  var PI$9 = Math.PI;
  var labelDataIndexStore = makeInner();

  var SliderTimelineView = function (_super) {
    __extends(SliderTimelineView, _super);

    function SliderTimelineView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SliderTimelineView.type;
      return _this;
    }

    SliderTimelineView.prototype.init = function (ecModel, api) {
      this.api = api;
    };

    SliderTimelineView.prototype.render = function (timelineModel, ecModel, api) {
      this.model = timelineModel;
      this.api = api;
      this.ecModel = ecModel;
      this.group.removeAll();

      if (timelineModel.get('show', true)) {
        var layoutInfo_1 = this._layout(timelineModel, api);

        var mainGroup_1 = this._createGroup('_mainGroup');

        var labelGroup = this._createGroup('_labelGroup');

        var axis_1 = this._axis = this._createAxis(layoutInfo_1, timelineModel);

        timelineModel.formatTooltip = function (dataIndex) {
          var name = axis_1.scale.getLabel({
            value: dataIndex
          });
          return createTooltipMarkup('nameValue', {
            noName: true,
            value: name
          });
        };

        each(['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], function (name) {
          this['_render' + name](layoutInfo_1, mainGroup_1, axis_1, timelineModel);
        }, this);

        this._renderAxisLabel(layoutInfo_1, labelGroup, axis_1, timelineModel);

        this._position(layoutInfo_1, timelineModel);
      }

      this._doPlayStop();

      this._updateTicksStatus();
    };

    SliderTimelineView.prototype.remove = function () {
      this._clearTimer();

      this.group.removeAll();
    };

    SliderTimelineView.prototype.dispose = function () {
      this._clearTimer();
    };

    SliderTimelineView.prototype._layout = function (timelineModel, api) {
      var labelPosOpt = timelineModel.get(['label', 'position']);
      var orient = timelineModel.get('orient');
      var viewRect = getViewRect$5(timelineModel, api);
      var parsedLabelPos;

      if (labelPosOpt == null || labelPosOpt === 'auto') {
        parsedLabelPos = orient === 'horizontal' ? viewRect.y + viewRect.height / 2 < api.getHeight() / 2 ? '-' : '+' : viewRect.x + viewRect.width / 2 < api.getWidth() / 2 ? '+' : '-';
      } else if (isString(labelPosOpt)) {
        parsedLabelPos = {
          horizontal: {
            top: '-',
            bottom: '+'
          },
          vertical: {
            left: '-',
            right: '+'
          }
        }[orient][labelPosOpt];
      } else {
        parsedLabelPos = labelPosOpt;
      }

      var labelAlignMap = {
        horizontal: 'center',
        vertical: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'left' : 'right'
      };
      var labelBaselineMap = {
        horizontal: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'top' : 'bottom',
        vertical: 'middle'
      };
      var rotationMap = {
        horizontal: 0,
        vertical: PI$9 / 2
      };
      var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width;
      var controlModel = timelineModel.getModel('controlStyle');
      var showControl = controlModel.get('show', true);
      var controlSize = showControl ? controlModel.get('itemSize') : 0;
      var controlGap = showControl ? controlModel.get('itemGap') : 0;
      var sizePlusGap = controlSize + controlGap;
      var labelRotation = timelineModel.get(['label', 'rotate']) || 0;
      labelRotation = labelRotation * PI$9 / 180;
      var playPosition;
      var prevBtnPosition;
      var nextBtnPosition;
      var controlPosition = controlModel.get('position', true);
      var showPlayBtn = showControl && controlModel.get('showPlayBtn', true);
      var showPrevBtn = showControl && controlModel.get('showPrevBtn', true);
      var showNextBtn = showControl && controlModel.get('showNextBtn', true);
      var xLeft = 0;
      var xRight = mainLength;

      if (controlPosition === 'left' || controlPosition === 'bottom') {
        showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap);
        showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap);
        showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
      } else {
        showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
        showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap);
        showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
      }

      var axisExtent = [xLeft, xRight];

      if (timelineModel.get('inverse')) {
        axisExtent.reverse();
      }

      return {
        viewRect: viewRect,
        mainLength: mainLength,
        orient: orient,
        rotation: rotationMap[orient],
        labelRotation: labelRotation,
        labelPosOpt: parsedLabelPos,
        labelAlign: timelineModel.get(['label', 'align']) || labelAlignMap[orient],
        labelBaseline: timelineModel.get(['label', 'verticalAlign']) || timelineModel.get(['label', 'baseline']) || labelBaselineMap[orient],
        playPosition: playPosition,
        prevBtnPosition: prevBtnPosition,
        nextBtnPosition: nextBtnPosition,
        axisExtent: axisExtent,
        controlSize: controlSize,
        controlGap: controlGap
      };
    };

    SliderTimelineView.prototype._position = function (layoutInfo, timelineModel) {
      var mainGroup = this._mainGroup;
      var labelGroup = this._labelGroup;
      var viewRect = layoutInfo.viewRect;

      if (layoutInfo.orient === 'vertical') {
        var m = create$1();
        var rotateOriginX = viewRect.x;
        var rotateOriginY = viewRect.y + viewRect.height;
        translate(m, m, [-rotateOriginX, -rotateOriginY]);
        rotate(m, m, -PI$9 / 2);
        translate(m, m, [rotateOriginX, rotateOriginY]);
        viewRect = viewRect.clone();
        viewRect.applyTransform(m);
      }

      var viewBound = getBound(viewRect);
      var mainBound = getBound(mainGroup.getBoundingRect());
      var labelBound = getBound(labelGroup.getBoundingRect());
      var mainPosition = [mainGroup.x, mainGroup.y];
      var labelsPosition = [labelGroup.x, labelGroup.y];
      labelsPosition[0] = mainPosition[0] = viewBound[0][0];
      var labelPosOpt = layoutInfo.labelPosOpt;

      if (labelPosOpt == null || isString(labelPosOpt)) {
        var mainBoundIdx = labelPosOpt === '+' ? 0 : 1;
        toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
        toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx);
      } else {
        var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1;
        toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
        labelsPosition[1] = mainPosition[1] + labelPosOpt;
      }

      mainGroup.setPosition(mainPosition);
      labelGroup.setPosition(labelsPosition);
      mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation;
      setOrigin(mainGroup);
      setOrigin(labelGroup);

      function setOrigin(targetGroup) {
        targetGroup.originX = viewBound[0][0] - targetGroup.x;
        targetGroup.originY = viewBound[1][0] - targetGroup.y;
      }

      function getBound(rect) {
        return [[rect.x, rect.x + rect.width], [rect.y, rect.y + rect.height]];
      }

      function toBound(fromPos, from, to, dimIdx, boundIdx) {
        fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx];
      }
    };

    SliderTimelineView.prototype._createAxis = function (layoutInfo, timelineModel) {
      var data = timelineModel.getData();
      var axisType = timelineModel.get('axisType');
      var scale = createScaleByModel$1(timelineModel, axisType);

      scale.getTicks = function () {
        return data.mapArray(['value'], function (value) {
          return {
            value: value
          };
        });
      };

      var dataExtent = data.getDataExtent('value');
      scale.setExtent(dataExtent[0], dataExtent[1]);
      scale.niceTicks();
      var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType);
      axis.model = timelineModel;
      return axis;
    };

    SliderTimelineView.prototype._createGroup = function (key) {
      var newGroup = this[key] = new Group();
      this.group.add(newGroup);
      return newGroup;
    };

    SliderTimelineView.prototype._renderAxisLine = function (layoutInfo, group, axis, timelineModel) {
      var axisExtent = axis.getExtent();

      if (!timelineModel.get(['lineStyle', 'show'])) {
        return;
      }

      var line = new Line({
        shape: {
          x1: axisExtent[0],
          y1: 0,
          x2: axisExtent[1],
          y2: 0
        },
        style: extend({
          lineCap: 'round'
        }, timelineModel.getModel('lineStyle').getLineStyle()),
        silent: true,
        z2: 1
      });
      group.add(line);
      var progressLine = this._progressLine = new Line({
        shape: {
          x1: axisExtent[0],
          x2: this._currentPointer ? this._currentPointer.x : axisExtent[0],
          y1: 0,
          y2: 0
        },
        style: defaults({
          lineCap: 'round',
          lineWidth: line.style.lineWidth
        }, timelineModel.getModel(['progress', 'lineStyle']).getLineStyle()),
        silent: true,
        z2: 1
      });
      group.add(progressLine);
    };

    SliderTimelineView.prototype._renderAxisTick = function (layoutInfo, group, axis, timelineModel) {
      var _this = this;

      var data = timelineModel.getData();
      var ticks = axis.scale.getTicks();
      this._tickSymbols = [];
      each(ticks, function (tick) {
        var tickCoord = axis.dataToCoord(tick.value);
        var itemModel = data.getItemModel(tick.value);
        var itemStyleModel = itemModel.getModel('itemStyle');
        var hoverStyleModel = itemModel.getModel(['emphasis', 'itemStyle']);
        var progressStyleModel = itemModel.getModel(['progress', 'itemStyle']);
        var symbolOpt = {
          x: tickCoord,
          y: 0,
          onclick: bind(_this._changeTimeline, _this, tick.value)
        };
        var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
        el.ensureState('emphasis').style = hoverStyleModel.getItemStyle();
        el.ensureState('progress').style = progressStyleModel.getItemStyle();
        enableHoverEmphasis(el);
        var ecData = getECData(el);

        if (itemModel.get('tooltip')) {
          ecData.dataIndex = tick.value;
          ecData.dataModel = timelineModel;
        } else {
          ecData.dataIndex = ecData.dataModel = null;
        }

        _this._tickSymbols.push(el);
      });
    };

    SliderTimelineView.prototype._renderAxisLabel = function (layoutInfo, group, axis, timelineModel) {
      var _this = this;

      var labelModel = axis.getLabelModel();

      if (!labelModel.get('show')) {
        return;
      }

      var data = timelineModel.getData();
      var labels = axis.getViewLabels();
      this._tickLabels = [];
      each(labels, function (labelItem) {
        var dataIndex = labelItem.tickValue;
        var itemModel = data.getItemModel(dataIndex);
        var normalLabelModel = itemModel.getModel('label');
        var hoverLabelModel = itemModel.getModel(['emphasis', 'label']);
        var progressLabelModel = itemModel.getModel(['progress', 'label']);
        var tickCoord = axis.dataToCoord(labelItem.tickValue);
        var textEl = new ZRText({
          x: tickCoord,
          y: 0,
          rotation: layoutInfo.labelRotation - layoutInfo.rotation,
          onclick: bind(_this._changeTimeline, _this, dataIndex),
          silent: false,
          style: createTextStyle(normalLabelModel, {
            text: labelItem.formattedLabel,
            align: layoutInfo.labelAlign,
            verticalAlign: layoutInfo.labelBaseline
          })
        });
        textEl.ensureState('emphasis').style = createTextStyle(hoverLabelModel);
        textEl.ensureState('progress').style = createTextStyle(progressLabelModel);
        group.add(textEl);
        enableHoverEmphasis(textEl);
        labelDataIndexStore(textEl).dataIndex = dataIndex;

        _this._tickLabels.push(textEl);
      });
    };

    SliderTimelineView.prototype._renderControl = function (layoutInfo, group, axis, timelineModel) {
      var controlSize = layoutInfo.controlSize;
      var rotation = layoutInfo.rotation;
      var itemStyle = timelineModel.getModel('controlStyle').getItemStyle();
      var hoverStyle = timelineModel.getModel(['emphasis', 'controlStyle']).getItemStyle();
      var playState = timelineModel.getPlayState();
      var inverse = timelineModel.get('inverse', true);
      makeBtn(layoutInfo.nextBtnPosition, 'next', bind(this._changeTimeline, this, inverse ? '-' : '+'));
      makeBtn(layoutInfo.prevBtnPosition, 'prev', bind(this._changeTimeline, this, inverse ? '+' : '-'));
      makeBtn(layoutInfo.playPosition, playState ? 'stop' : 'play', bind(this._handlePlayClick, this, !playState), true);

      function makeBtn(position, iconName, onclick, willRotate) {
        if (!position) {
          return;
        }

        var iconSize = parsePercent(retrieve2(timelineModel.get(['controlStyle', iconName + 'BtnSize']), controlSize), controlSize);
        var rect = [0, -iconSize / 2, iconSize, iconSize];
        var opt = {
          position: position,
          origin: [controlSize / 2, 0],
          rotation: willRotate ? -rotation : 0,
          rectHover: true,
          style: itemStyle,
          onclick: onclick
        };
        var btn = makeControlIcon(timelineModel, iconName + 'Icon', rect, opt);
        btn.ensureState('emphasis').style = hoverStyle;
        group.add(btn);
        enableHoverEmphasis(btn);
      }
    };

    SliderTimelineView.prototype._renderCurrentPointer = function (layoutInfo, group, axis, timelineModel) {
      var data = timelineModel.getData();
      var currentIndex = timelineModel.getCurrentIndex();
      var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle');
      var me = this;
      var callback = {
        onCreate: function (pointer) {
          pointer.draggable = true;
          pointer.drift = bind(me._handlePointerDrag, me);
          pointer.ondragend = bind(me._handlePointerDragend, me);
          pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel, true);
        },
        onUpdate: function (pointer) {
          pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel);
        }
      };
      this._currentPointer = giveSymbol(pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback);
    };

    SliderTimelineView.prototype._handlePlayClick = function (nextState) {
      this._clearTimer();

      this.api.dispatchAction({
        type: 'timelinePlayChange',
        playState: nextState,
        from: this.uid
      });
    };

    SliderTimelineView.prototype._handlePointerDrag = function (dx, dy, e) {
      this._clearTimer();

      this._pointerChangeTimeline([e.offsetX, e.offsetY]);
    };

    SliderTimelineView.prototype._handlePointerDragend = function (e) {
      this._pointerChangeTimeline([e.offsetX, e.offsetY], true);
    };

    SliderTimelineView.prototype._pointerChangeTimeline = function (mousePos, trigger) {
      var toCoord = this._toAxisCoord(mousePos)[0];

      var axis = this._axis;
      var axisExtent = asc(axis.getExtent().slice());
      toCoord > axisExtent[1] && (toCoord = axisExtent[1]);
      toCoord < axisExtent[0] && (toCoord = axisExtent[0]);
      this._currentPointer.x = toCoord;

      this._currentPointer.markRedraw();

      this._progressLine.shape.x2 = toCoord;

      this._progressLine.dirty();

      var targetDataIndex = this._findNearestTick(toCoord);

      var timelineModel = this.model;

      if (trigger || targetDataIndex !== timelineModel.getCurrentIndex() && timelineModel.get('realtime')) {
        this._changeTimeline(targetDataIndex);
      }
    };

    SliderTimelineView.prototype._doPlayStop = function () {
      var _this = this;

      this._clearTimer();

      if (this.model.getPlayState()) {
        this._timer = setTimeout(function () {
          var timelineModel = _this.model;

          _this._changeTimeline(timelineModel.getCurrentIndex() + (timelineModel.get('rewind', true) ? -1 : 1));
        }, this.model.get('playInterval'));
      }
    };

    SliderTimelineView.prototype._toAxisCoord = function (vertex) {
      var trans = this._mainGroup.getLocalTransform();

      return applyTransform$1(vertex, trans, true);
    };

    SliderTimelineView.prototype._findNearestTick = function (axisCoord) {
      var data = this.model.getData();
      var dist = Infinity;
      var targetDataIndex;
      var axis = this._axis;
      data.each(['value'], function (value, dataIndex) {
        var coord = axis.dataToCoord(value);
        var d = Math.abs(coord - axisCoord);

        if (d < dist) {
          dist = d;
          targetDataIndex = dataIndex;
        }
      });
      return targetDataIndex;
    };

    SliderTimelineView.prototype._clearTimer = function () {
      if (this._timer) {
        clearTimeout(this._timer);
        this._timer = null;
      }
    };

    SliderTimelineView.prototype._changeTimeline = function (nextIndex) {
      var currentIndex = this.model.getCurrentIndex();

      if (nextIndex === '+') {
        nextIndex = currentIndex + 1;
      } else if (nextIndex === '-') {
        nextIndex = currentIndex - 1;
      }

      this.api.dispatchAction({
        type: 'timelineChange',
        currentIndex: nextIndex,
        from: this.uid
      });
    };

    SliderTimelineView.prototype._updateTicksStatus = function () {
      var currentIndex = this.model.getCurrentIndex();
      var tickSymbols = this._tickSymbols;
      var tickLabels = this._tickLabels;

      if (tickSymbols) {
        for (var i = 0; i < tickSymbols.length; i++) {
          tickSymbols && tickSymbols[i] && tickSymbols[i].toggleState('progress', i < currentIndex);
        }
      }

      if (tickLabels) {
        for (var i = 0; i < tickLabels.length; i++) {
          tickLabels && tickLabels[i] && tickLabels[i].toggleState('progress', labelDataIndexStore(tickLabels[i]).dataIndex <= currentIndex);
        }
      }
    };

    SliderTimelineView.type = 'timeline.slider';
    return SliderTimelineView;
  }(TimelineView);

  function createScaleByModel$1(model, axisType) {
    axisType = axisType || model.get('type');

    if (axisType) {
      switch (axisType) {
        case 'category':
          return new OrdinalScale({
            ordinalMeta: model.getCategories(),
            extent: [Infinity, -Infinity]
          });

        case 'time':
          return new TimeScale({
            locale: model.ecModel.getLocaleModel(),
            useUTC: model.ecModel.get('useUTC')
          });

        default:
          return new IntervalScale();
      }
    }
  }

  function getViewRect$5(model, api) {
    return getLayoutRect(model.getBoxLayoutParams(), {
      width: api.getWidth(),
      height: api.getHeight()
    }, model.get('padding'));
  }

  function makeControlIcon(timelineModel, objPath, rect, opts) {
    var style = opts.style;
    var icon = createIcon(timelineModel.get(['controlStyle', objPath]), opts || {}, new BoundingRect(rect[0], rect[1], rect[2], rect[3]));

    if (style) {
      icon.setStyle(style);
    }

    return icon;
  }

  function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) {
    var color = itemStyleModel.get('color');

    if (!symbol) {
      var symbolType = hostModel.get('symbol');
      symbol = createSymbol(symbolType, -1, -1, 2, 2, color);
      symbol.setStyle('strokeNoScale', true);
      group.add(symbol);
      callback && callback.onCreate(symbol);
    } else {
      symbol.setColor(color);
      group.add(symbol);
      callback && callback.onUpdate(symbol);
    }

    var itemStyle = itemStyleModel.getItemStyle(['color']);
    symbol.setStyle(itemStyle);
    opt = merge({
      rectHover: true,
      z2: 100
    }, opt, true);
    var symbolSize = hostModel.get('symbolSize');
    symbolSize = symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize];
    opt.scaleX = symbolSize[0] / 2;
    opt.scaleY = symbolSize[1] / 2;
    var symbolOffset = hostModel.get('symbolOffset');

    if (symbolOffset) {
      opt.x = opt.x || 0;
      opt.y = opt.y || 0;
      opt.x += parsePercent$2(symbolOffset[0], symbolSize[0]);
      opt.y += parsePercent$2(symbolOffset[1], symbolSize[1]);
    }

    var symbolRotate = hostModel.get('symbolRotate');
    opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
    symbol.attr(opt);
    symbol.updateTransform();
    return symbol;
  }

  function pointerMoveTo(pointer, progressLine, dataIndex, axis, timelineModel, noAnimation) {
    if (pointer.dragging) {
      return;
    }

    var pointerModel = timelineModel.getModel('checkpointStyle');
    var toCoord = axis.dataToCoord(timelineModel.getData().get('value', dataIndex));

    if (noAnimation || !pointerModel.get('animation', true)) {
      pointer.attr({
        x: toCoord,
        y: 0
      });
      progressLine && progressLine.attr({
        shape: {
          x2: toCoord
        }
      });
    } else {
      var animationCfg = {
        duration: pointerModel.get('animationDuration', true),
        easing: pointerModel.get('animationEasing', true)
      };
      pointer.stopAnimation(null, true);
      pointer.animateTo({
        x: toCoord,
        y: 0
      }, animationCfg);
      progressLine && progressLine.animateTo({
        shape: {
          x2: toCoord
        }
      }, animationCfg);
    }
  }

  ComponentView.registerClass(SliderTimelineView);
  registerPreprocessor(timelinePreprocessor);

  function fillLabel(opt) {
    defaultEmphasis(opt, 'label', ['show']);
  }

  var inner$i = makeInner();

  var MarkerModel = function (_super) {
    __extends(MarkerModel, _super);

    function MarkerModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkerModel.type;
      _this.createdBySelf = false;
      return _this;
    }

    MarkerModel.prototype.init = function (option, parentModel, ecModel) {
      if (true) {
        if (this.type === 'marker') {
          throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.');
        }
      }

      this.mergeDefaultAndTheme(option, ecModel);

      this._mergeOption(option, ecModel, false, true);
    };

    MarkerModel.prototype.isAnimationEnabled = function () {
      if (env.node) {
        return false;
      }

      var hostSeries = this.__hostSeries;
      return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled();
    };

    MarkerModel.prototype.mergeOption = function (newOpt, ecModel) {
      this._mergeOption(newOpt, ecModel, false, false);
    };

    MarkerModel.prototype._mergeOption = function (newOpt, ecModel, createdBySelf, isInit) {
      var componentType = this.mainType;

      if (!createdBySelf) {
        ecModel.eachSeries(function (seriesModel) {
          var markerOpt = seriesModel.get(this.mainType, true);
          var markerModel = inner$i(seriesModel)[componentType];

          if (!markerOpt || !markerOpt.data) {
            inner$i(seriesModel)[componentType] = null;
            return;
          }

          if (!markerModel) {
            if (isInit) {
              fillLabel(markerOpt);
            }

            each(markerOpt.data, function (item) {
              if (item instanceof Array) {
                fillLabel(item[0]);
                fillLabel(item[1]);
              } else {
                fillLabel(item);
              }
            });
            markerModel = this.createMarkerModelFromSeries(markerOpt, this, ecModel);
            extend(markerModel, {
              mainType: this.mainType,
              seriesIndex: seriesModel.seriesIndex,
              name: seriesModel.name,
              createdBySelf: true
            });
            markerModel.__hostSeries = seriesModel;
          } else {
            markerModel._mergeOption(markerOpt, ecModel, true);
          }

          inner$i(seriesModel)[componentType] = markerModel;
        }, this);
      }
    };

    MarkerModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
      var data = this.getData();
      var value = this.getRawValue(dataIndex);
      var itemName = data.getName(dataIndex);
      return createTooltipMarkup('section', {
        header: this.name,
        blocks: [createTooltipMarkup('nameValue', {
          name: itemName,
          value: value,
          noName: !itemName,
          noValue: value == null
        })]
      });
    };

    MarkerModel.prototype.getData = function () {
      return this._data;
    };

    MarkerModel.prototype.setData = function (data) {
      this._data = data;
    };

    MarkerModel.getMarkerModelFromSeries = function (seriesModel, componentType) {
      return inner$i(seriesModel)[componentType];
    };

    MarkerModel.type = 'marker';
    MarkerModel.dependencies = ['series', 'grid', 'polar', 'geo'];
    return MarkerModel;
  }(ComponentModel);

  mixin(MarkerModel, DataFormatMixin.prototype);

  var MarkPointModel = function (_super) {
    __extends(MarkPointModel, _super);

    function MarkPointModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkPointModel.type;
      return _this;
    }

    MarkPointModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) {
      return new MarkPointModel(markerOpt, masterMarkerModel, ecModel);
    };

    MarkPointModel.type = 'markPoint';
    MarkPointModel.defaultOption = {
      zlevel: 0,
      z: 5,
      symbol: 'pin',
      symbolSize: 50,
      tooltip: {
        trigger: 'item'
      },
      label: {
        show: true,
        position: 'inside'
      },
      itemStyle: {
        borderWidth: 2
      },
      emphasis: {
        label: {
          show: true
        }
      }
    };
    return MarkPointModel;
  }(MarkerModel);

  ComponentModel.registerClass(MarkPointModel);

  function hasXOrY(item) {
    return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
  }

  function hasXAndY(item) {
    return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
  }

  function markerTypeCalculatorWithExtent(markerType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex) {
    var coordArr = [];
    var stacked = isDimensionStacked(data, targetDataDim);
    var calcDataDim = stacked ? data.getCalculationInfo('stackResultDimension') : targetDataDim;
    var value = numCalculate(data, calcDataDim, markerType);
    var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
    coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
    coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex);
    var coordArrValue = data.get(targetDataDim, dataIndex);
    var precision = getPrecision(data.get(targetDataDim, dataIndex));
    precision = Math.min(precision, 20);

    if (precision >= 0) {
      coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
    }

    return [coordArr, coordArrValue];
  }

  var markerTypeCalculator = {
    min: curry(markerTypeCalculatorWithExtent, 'min'),
    max: curry(markerTypeCalculatorWithExtent, 'max'),
    average: curry(markerTypeCalculatorWithExtent, 'average'),
    median: curry(markerTypeCalculatorWithExtent, 'median')
  };

  function dataTransform(seriesModel, item) {
    var data = seriesModel.getData();
    var coordSys = seriesModel.coordinateSystem;

    if (item && !hasXAndY(item) && !isArray(item.coord) && coordSys) {
      var dims = coordSys.dimensions;
      var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel);
      item = clone(item);

      if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) {
        var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
        var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);
        var coordInfo = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex);
        item.coord = coordInfo[0];
        item.value = coordInfo[1];
      } else {
        var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis];

        for (var i = 0; i < 2; i++) {
          if (markerTypeCalculator[coord[i]]) {
            coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]);
          }
        }

        item.coord = coord;
      }
    }

    return item;
  }

  function getAxisInfo$1(item, data, coordSys, seriesModel) {
    var ret = {};

    if (item.valueIndex != null || item.valueDim != null) {
      ret.valueDataDim = item.valueIndex != null ? data.getDimension(item.valueIndex) : item.valueDim;
      ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim));
      ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
      ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
    } else {
      ret.baseAxis = seriesModel.getBaseAxis();
      ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
      ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
      ret.valueDataDim = data.mapDimension(ret.valueAxis.dim);
    }

    return ret;
  }

  function dataDimToCoordDim(seriesModel, dataDim) {
    var data = seriesModel.getData();
    var dimensions = data.dimensions;
    dataDim = data.getDimension(dataDim);

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

      if (dimItem.name === dataDim) {
        return dimItem.coordDim;
      }
    }
  }

  function dataFilter$1(coordSys, item) {
    return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
  }

  function dimValueGetter(item, dimName, dataIndex, dimIndex) {
    if (dimIndex < 2) {
      return item.coord && item.coord[dimIndex];
    }

    return item.value;
  }

  function numCalculate(data, valueDataDim, type) {
    if (type === 'average') {
      var sum_1 = 0;
      var count_1 = 0;
      data.each(valueDataDim, function (val, idx) {
        if (!isNaN(val)) {
          sum_1 += val;
          count_1++;
        }
      });
      return sum_1 / count_1;
    } else if (type === 'median') {
      return data.getMedian(valueDataDim);
    } else {
      return data.getDataExtent(valueDataDim)[type === 'max' ? 1 : 0];
    }
  }

  var inner$j = makeInner();

  var MarkerView = function (_super) {
    __extends(MarkerView, _super);

    function MarkerView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkerView.type;
      return _this;
    }

    MarkerView.prototype.init = function () {
      this.markerGroupMap = createHashMap();
    };

    MarkerView.prototype.render = function (markerModel, ecModel, api) {
      var _this = this;

      var markerGroupMap = this.markerGroupMap;
      markerGroupMap.each(function (item) {
        inner$j(item).keep = false;
      });
      ecModel.eachSeries(function (seriesModel) {
        var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type);
        markerModel && _this.renderSeries(seriesModel, markerModel, ecModel, api);
      });
      markerGroupMap.each(function (item) {
        !inner$j(item).keep && _this.group.remove(item.group);
      });
    };

    MarkerView.prototype.markKeep = function (drawGroup) {
      inner$j(drawGroup).keep = true;
    };

    MarkerView.prototype.blurSeries = function (seriesModelList) {
      var _this = this;

      each(seriesModelList, function (seriesModel) {
        var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type);

        if (markerModel) {
          var data = markerModel.getData();
          data.eachItemGraphicEl(function (el) {
            if (el) {
              enterBlur(el);
            }
          });
        }
      });
    };

    MarkerView.type = 'marker';
    return MarkerView;
  }(ComponentView);

  function updateMarkerLayout(mpData, seriesModel, api) {
    var coordSys = seriesModel.coordinateSystem;
    mpData.each(function (idx) {
      var itemModel = mpData.getItemModel(idx);
      var point;
      var xPx = parsePercent$2(itemModel.get('x'), api.getWidth());
      var yPx = parsePercent$2(itemModel.get('y'), api.getHeight());

      if (!isNaN(xPx) && !isNaN(yPx)) {
        point = [xPx, yPx];
      } else if (seriesModel.getMarkerPosition) {
        point = seriesModel.getMarkerPosition(mpData.getValues(mpData.dimensions, idx));
      } else if (coordSys) {
        var x = mpData.get(coordSys.dimensions[0], idx);
        var y = mpData.get(coordSys.dimensions[1], idx);
        point = coordSys.dataToPoint([x, y]);
      }

      if (!isNaN(xPx)) {
        point[0] = xPx;
      }

      if (!isNaN(yPx)) {
        point[1] = yPx;
      }

      mpData.setItemLayout(idx, point);
    });
  }

  var MarkPointView = function (_super) {
    __extends(MarkPointView, _super);

    function MarkPointView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkPointView.type;
      return _this;
    }

    MarkPointView.prototype.updateTransform = function (markPointModel, ecModel, api) {
      ecModel.eachSeries(function (seriesModel) {
        var mpModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markPoint');

        if (mpModel) {
          updateMarkerLayout(mpModel.getData(), seriesModel, api);
          this.markerGroupMap.get(seriesModel.id).updateLayout();
        }
      }, this);
    };

    MarkPointView.prototype.renderSeries = function (seriesModel, mpModel, ecModel, api) {
      var coordSys = seriesModel.coordinateSystem;
      var seriesId = seriesModel.id;
      var seriesData = seriesModel.getData();
      var symbolDrawMap = this.markerGroupMap;
      var symbolDraw = symbolDrawMap.get(seriesId) || symbolDrawMap.set(seriesId, new SymbolDraw());
      var mpData = createList$1(coordSys, seriesModel, mpModel);
      mpModel.setData(mpData);
      updateMarkerLayout(mpModel.getData(), seriesModel, api);
      mpData.each(function (idx) {
        var itemModel = mpData.getItemModel(idx);
        var symbol = itemModel.getShallow('symbol');
        var symbolSize = itemModel.getShallow('symbolSize');
        var symbolRotate = itemModel.getShallow('symbolRotate');

        if (isFunction(symbol) || isFunction(symbolSize) || isFunction(symbolRotate)) {
          var rawIdx = mpModel.getRawValue(idx);
          var dataParams = mpModel.getDataParams(idx);

          if (isFunction(symbol)) {
            symbol = symbol(rawIdx, dataParams);
          }

          if (isFunction(symbolSize)) {
            symbolSize = symbolSize(rawIdx, dataParams);
          }

          if (isFunction(symbolRotate)) {
            symbolRotate = symbolRotate(rawIdx, dataParams);
          }
        }

        var style = itemModel.getModel('itemStyle').getItemStyle();
        var color = getVisualFromData(seriesData, 'color');

        if (!style.fill) {
          style.fill = color;
        }

        mpData.setItemVisual(idx, {
          symbol: symbol,
          symbolSize: symbolSize,
          symbolRotate: symbolRotate,
          style: style
        });
      });
      symbolDraw.updateData(mpData);
      this.group.add(symbolDraw.group);
      mpData.eachItemGraphicEl(function (el) {
        el.traverse(function (child) {
          getECData(child).dataModel = mpModel;
        });
      });
      this.markKeep(symbolDraw);
      symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent');
    };

    MarkPointView.type = 'markPoint';
    return MarkPointView;
  }(MarkerView);

  function createList$1(coordSys, seriesModel, mpModel) {
    var coordDimsInfos;

    if (coordSys) {
      coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
        var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {};
        return defaults({
          name: coordDim
        }, info);
      });
    } else {
      coordDimsInfos = [{
        name: 'value',
        type: 'float'
      }];
    }

    var mpData = new List(coordDimsInfos, mpModel);
    var dataOpt = map(mpModel.get('data'), curry(dataTransform, seriesModel));

    if (coordSys) {
      dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys));
    }

    mpData.initData(dataOpt, null, coordSys ? dimValueGetter : function (item) {
      return item.value;
    });
    return mpData;
  }

  ComponentView.registerClass(MarkPointView);
  registerPreprocessor(function (opt) {
    opt.markPoint = opt.markPoint || {};
  });

  var MarkLineModel = function (_super) {
    __extends(MarkLineModel, _super);

    function MarkLineModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkLineModel.type;
      return _this;
    }

    MarkLineModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) {
      return new MarkLineModel(markerOpt, masterMarkerModel, ecModel);
    };

    MarkLineModel.type = 'markLine';
    MarkLineModel.defaultOption = {
      zlevel: 0,
      z: 5,
      symbol: ['circle', 'arrow'],
      symbolSize: [8, 16],
      precision: 2,
      tooltip: {
        trigger: 'item'
      },
      label: {
        show: true,
        position: 'end',
        distance: 5
      },
      lineStyle: {
        type: 'dashed'
      },
      emphasis: {
        label: {
          show: true
        },
        lineStyle: {
          width: 3
        }
      },
      animationEasing: 'linear'
    };
    return MarkLineModel;
  }(MarkerModel);

  ComponentModel.registerClass(MarkLineModel);
  var inner$k = makeInner();

  var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
    var data = seriesModel.getData();
    var itemArray;

    if (!isArray(item)) {
      var mlType = item.type;

      if (mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median' || item.xAxis != null || item.yAxis != null) {
        var valueAxis = void 0;
        var value = void 0;

        if (item.yAxis != null || item.xAxis != null) {
          valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x');
          value = retrieve(item.yAxis, item.xAxis);
        } else {
          var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel);
          valueAxis = axisInfo.valueAxis;
          var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim);
          value = numCalculate(data, valueDataDim, mlType);
        }

        var valueIndex = valueAxis.dim === 'x' ? 0 : 1;
        var baseIndex = 1 - valueIndex;
        var mlFrom = clone(item);
        var mlTo = {
          coord: []
        };
        mlFrom.type = null;
        mlFrom.coord = [];
        mlFrom.coord[baseIndex] = -Infinity;
        mlTo.coord[baseIndex] = Infinity;
        var precision = mlModel.get('precision');

        if (precision >= 0 && typeof value === 'number') {
          value = +value.toFixed(Math.min(precision, 20));
        }

        mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value;
        itemArray = [mlFrom, mlTo, {
          type: mlType,
          valueIndex: item.valueIndex,
          value: value
        }];
      } else {
        if (true) {
          logError('Invalid markLine data.');
        }

        itemArray = [];
      }
    } else {
      itemArray = item;
    }

    var normalizedItem = [dataTransform(seriesModel, itemArray[0]), dataTransform(seriesModel, itemArray[1]), extend({}, itemArray[2])];
    normalizedItem[2].type = normalizedItem[2].type || null;
    merge(normalizedItem[2], normalizedItem[0]);
    merge(normalizedItem[2], normalizedItem[1]);
    return normalizedItem;
  };

  function isInifinity(val) {
    return !isNaN(val) && !isFinite(val);
  }

  function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
    var otherDimIndex = 1 - dimIndex;
    var dimName = coordSys.dimensions[dimIndex];
    return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]) && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]);
  }

  function markLineFilter(coordSys, item) {
    if (coordSys.type === 'cartesian2d') {
      var fromCoord = item[0].coord;
      var toCoord = item[1].coord;

      if (fromCoord && toCoord && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))) {
        return true;
      }
    }

    return dataFilter$1(coordSys, item[0]) && dataFilter$1(coordSys, item[1]);
  }

  function updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api) {
    var coordSys = seriesModel.coordinateSystem;
    var itemModel = data.getItemModel(idx);
    var point;
    var xPx = parsePercent$2(itemModel.get('x'), api.getWidth());
    var yPx = parsePercent$2(itemModel.get('y'), api.getHeight());

    if (!isNaN(xPx) && !isNaN(yPx)) {
      point = [xPx, yPx];
    } else {
      if (seriesModel.getMarkerPosition) {
        point = seriesModel.getMarkerPosition(data.getValues(data.dimensions, idx));
      } else {
        var dims = coordSys.dimensions;
        var x = data.get(dims[0], idx);
        var y = data.get(dims[1], idx);
        point = coordSys.dataToPoint([x, y]);
      }

      if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
        var xAxis = coordSys.getAxis('x');
        var yAxis = coordSys.getAxis('y');
        var dims = coordSys.dimensions;

        if (isInifinity(data.get(dims[0], idx))) {
          point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]);
        } else if (isInifinity(data.get(dims[1], idx))) {
          point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]);
        }
      }

      if (!isNaN(xPx)) {
        point[0] = xPx;
      }

      if (!isNaN(yPx)) {
        point[1] = yPx;
      }
    }

    data.setItemLayout(idx, point);
  }

  var MarkLineView = function (_super) {
    __extends(MarkLineView, _super);

    function MarkLineView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkLineView.type;
      return _this;
    }

    MarkLineView.prototype.updateTransform = function (markLineModel, ecModel, api) {
      ecModel.eachSeries(function (seriesModel) {
        var mlModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markLine');

        if (mlModel) {
          var mlData_1 = mlModel.getData();
          var fromData_1 = inner$k(mlModel).from;
          var toData_1 = inner$k(mlModel).to;
          fromData_1.each(function (idx) {
            updateSingleMarkerEndLayout(fromData_1, idx, true, seriesModel, api);
            updateSingleMarkerEndLayout(toData_1, idx, false, seriesModel, api);
          });
          mlData_1.each(function (idx) {
            mlData_1.setItemLayout(idx, [fromData_1.getItemLayout(idx), toData_1.getItemLayout(idx)]);
          });
          this.markerGroupMap.get(seriesModel.id).updateLayout();
        }
      }, this);
    };

    MarkLineView.prototype.renderSeries = function (seriesModel, mlModel, ecModel, api) {
      var coordSys = seriesModel.coordinateSystem;
      var seriesId = seriesModel.id;
      var seriesData = seriesModel.getData();
      var lineDrawMap = this.markerGroupMap;
      var lineDraw = lineDrawMap.get(seriesId) || lineDrawMap.set(seriesId, new LineDraw());
      this.group.add(lineDraw.group);
      var mlData = createList$2(coordSys, seriesModel, mlModel);
      var fromData = mlData.from;
      var toData = mlData.to;
      var lineData = mlData.line;
      inner$k(mlModel).from = fromData;
      inner$k(mlModel).to = toData;
      mlModel.setData(lineData);
      var symbolType = mlModel.get('symbol');
      var symbolSize = mlModel.get('symbolSize');

      if (!isArray(symbolType)) {
        symbolType = [symbolType, symbolType];
      }

      if (!isArray(symbolSize)) {
        symbolSize = [symbolSize, symbolSize];
      }

      mlData.from.each(function (idx) {
        updateDataVisualAndLayout(fromData, idx, true);
        updateDataVisualAndLayout(toData, idx, false);
      });
      lineData.each(function (idx) {
        var lineStyle = lineData.getItemModel(idx).getModel('lineStyle').getLineStyle();
        lineData.setItemLayout(idx, [fromData.getItemLayout(idx), toData.getItemLayout(idx)]);

        if (lineStyle.stroke == null) {
          lineStyle.stroke = fromData.getItemVisual(idx, 'style').fill;
        }

        lineData.setItemVisual(idx, {
          fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'),
          fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize'),
          fromSymbol: fromData.getItemVisual(idx, 'symbol'),
          toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'),
          toSymbolSize: toData.getItemVisual(idx, 'symbolSize'),
          toSymbol: toData.getItemVisual(idx, 'symbol'),
          style: lineStyle
        });
      });
      lineDraw.updateData(lineData);
      mlData.line.eachItemGraphicEl(function (el, idx) {
        el.traverse(function (child) {
          getECData(child).dataModel = mlModel;
        });
      });

      function updateDataVisualAndLayout(data, idx, isFrom) {
        var itemModel = data.getItemModel(idx);
        updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api);
        var style = itemModel.getModel('itemStyle').getItemStyle();

        if (style.fill == null) {
          style.fill = getVisualFromData(seriesData, 'color');
        }

        data.setItemVisual(idx, {
          symbolRotate: itemModel.get('symbolRotate'),
          symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
          symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
          style: style
        });
      }

      this.markKeep(lineDraw);
      lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent');
    };

    MarkLineView.type = 'markLine';
    return MarkLineView;
  }(MarkerView);

  function createList$2(coordSys, seriesModel, mlModel) {
    var coordDimsInfos;

    if (coordSys) {
      coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
        var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {};
        return defaults({
          name: coordDim
        }, info);
      });
    } else {
      coordDimsInfos = [{
        name: 'value',
        type: 'float'
      }];
    }

    var fromData = new List(coordDimsInfos, mlModel);
    var toData = new List(coordDimsInfos, mlModel);
    var lineData = new List([], mlModel);
    var optData = map(mlModel.get('data'), curry(markLineTransform, seriesModel, coordSys, mlModel));

    if (coordSys) {
      optData = filter(optData, curry(markLineFilter, coordSys));
    }

    var dimValueGetter$1 = coordSys ? dimValueGetter : function (item) {
      return item.value;
    };
    fromData.initData(map(optData, function (item) {
      return item[0];
    }), null, dimValueGetter$1);
    toData.initData(map(optData, function (item) {
      return item[1];
    }), null, dimValueGetter$1);
    lineData.initData(map(optData, function (item) {
      return item[2];
    }));
    lineData.hasItemOption = true;
    return {
      from: fromData,
      to: toData,
      line: lineData
    };
  }

  ComponentView.registerClass(MarkLineView);
  registerPreprocessor(function (opt) {
    opt.markLine = opt.markLine || {};
  });

  var MarkAreaModel = function (_super) {
    __extends(MarkAreaModel, _super);

    function MarkAreaModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkAreaModel.type;
      return _this;
    }

    MarkAreaModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) {
      return new MarkAreaModel(markerOpt, masterMarkerModel, ecModel);
    };

    MarkAreaModel.type = 'markArea';
    MarkAreaModel.defaultOption = {
      zlevel: 0,
      z: 1,
      tooltip: {
        trigger: 'item'
      },
      animation: false,
      label: {
        show: true,
        position: 'top'
      },
      itemStyle: {
        borderWidth: 0
      },
      emphasis: {
        label: {
          show: true,
          position: 'top'
        }
      }
    };
    return MarkAreaModel;
  }(MarkerModel);

  ComponentModel.registerClass(MarkAreaModel);
  var inner$l = makeInner();

  var markAreaTransform = function (seriesModel, coordSys, maModel, item) {
    var lt = dataTransform(seriesModel, item[0]);
    var rb = dataTransform(seriesModel, item[1]);
    var ltCoord = lt.coord;
    var rbCoord = rb.coord;
    ltCoord[0] = retrieve(ltCoord[0], -Infinity);
    ltCoord[1] = retrieve(ltCoord[1], -Infinity);
    rbCoord[0] = retrieve(rbCoord[0], Infinity);
    rbCoord[1] = retrieve(rbCoord[1], Infinity);
    var result = mergeAll([{}, lt, rb]);
    result.coord = [lt.coord, rb.coord];
    result.x0 = lt.x;
    result.y0 = lt.y;
    result.x1 = rb.x;
    result.y1 = rb.y;
    return result;
  };

  function isInifinity$1(val) {
    return !isNaN(val) && !isFinite(val);
  }

  function ifMarkAreaHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
    var otherDimIndex = 1 - dimIndex;
    return isInifinity$1(fromCoord[otherDimIndex]) && isInifinity$1(toCoord[otherDimIndex]);
  }

  function markAreaFilter(coordSys, item) {
    var fromCoord = item.coord[0];
    var toCoord = item.coord[1];

    if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
      if (fromCoord && toCoord && (ifMarkAreaHasOnlyDim(1, fromCoord, toCoord) || ifMarkAreaHasOnlyDim(0, fromCoord, toCoord))) {
        return true;
      }
    }

    return dataFilter$1(coordSys, {
      coord: fromCoord,
      x: item.x0,
      y: item.y0
    }) || dataFilter$1(coordSys, {
      coord: toCoord,
      x: item.x1,
      y: item.y1
    });
  }

  function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) {
    var coordSys = seriesModel.coordinateSystem;
    var itemModel = data.getItemModel(idx);
    var point;
    var xPx = parsePercent$2(itemModel.get(dims[0]), api.getWidth());
    var yPx = parsePercent$2(itemModel.get(dims[1]), api.getHeight());

    if (!isNaN(xPx) && !isNaN(yPx)) {
      point = [xPx, yPx];
    } else {
      if (seriesModel.getMarkerPosition) {
        point = seriesModel.getMarkerPosition(data.getValues(dims, idx));
      } else {
        var x = data.get(dims[0], idx);
        var y = data.get(dims[1], idx);
        var pt = [x, y];
        coordSys.clampData && coordSys.clampData(pt, pt);
        point = coordSys.dataToPoint(pt, true);
      }

      if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
        var xAxis = coordSys.getAxis('x');
        var yAxis = coordSys.getAxis('y');
        var x = data.get(dims[0], idx);
        var y = data.get(dims[1], idx);

        if (isInifinity$1(x)) {
          point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]);
        } else if (isInifinity$1(y)) {
          point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]);
        }
      }

      if (!isNaN(xPx)) {
        point[0] = xPx;
      }

      if (!isNaN(yPx)) {
        point[1] = yPx;
      }
    }

    return point;
  }

  var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']];

  var MarkAreaView = function (_super) {
    __extends(MarkAreaView, _super);

    function MarkAreaView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = MarkAreaView.type;
      return _this;
    }

    MarkAreaView.prototype.updateTransform = function (markAreaModel, ecModel, api) {
      ecModel.eachSeries(function (seriesModel) {
        var maModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markArea');

        if (maModel) {
          var areaData_1 = maModel.getData();
          areaData_1.each(function (idx) {
            var points = map(dimPermutations, function (dim) {
              return getSingleMarkerEndPoint(areaData_1, idx, dim, seriesModel, api);
            });
            areaData_1.setItemLayout(idx, points);
            var el = areaData_1.getItemGraphicEl(idx);
            el.setShape('points', points);
          });
        }
      }, this);
    };

    MarkAreaView.prototype.renderSeries = function (seriesModel, maModel, ecModel, api) {
      var coordSys = seriesModel.coordinateSystem;
      var seriesId = seriesModel.id;
      var seriesData = seriesModel.getData();
      var areaGroupMap = this.markerGroupMap;
      var polygonGroup = areaGroupMap.get(seriesId) || areaGroupMap.set(seriesId, {
        group: new Group()
      });
      this.group.add(polygonGroup.group);
      this.markKeep(polygonGroup);
      var areaData = createList$3(coordSys, seriesModel, maModel);
      maModel.setData(areaData);
      areaData.each(function (idx) {
        var points = map(dimPermutations, function (dim) {
          return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
        });
        var allClipped = true;
        each(dimPermutations, function (dim) {
          if (!allClipped) {
            return;
          }

          var xValue = areaData.get(dim[0], idx);
          var yValue = areaData.get(dim[1], idx);

          if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue)) && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))) {
            allClipped = false;
          }
        });
        areaData.setItemLayout(idx, {
          points: points,
          allClipped: allClipped
        });
        var style = areaData.getItemModel(idx).getModel('itemStyle').getItemStyle();
        var color$1 = getVisualFromData(seriesData, 'color');

        if (!style.fill) {
          style.fill = color$1;

          if (typeof style.fill === 'string') {
            style.fill = modifyAlpha(style.fill, 0.4);
          }
        }

        if (!style.stroke) {
          style.stroke = color$1;
        }

        areaData.setItemVisual(idx, 'style', style);
      });
      areaData.diff(inner$l(polygonGroup).data).add(function (idx) {
        var layout = areaData.getItemLayout(idx);

        if (!layout.allClipped) {
          var polygon = new Polygon({
            shape: {
              points: layout.points
            }
          });
          areaData.setItemGraphicEl(idx, polygon);
          polygonGroup.group.add(polygon);
        }
      }).update(function (newIdx, oldIdx) {
        var polygon = inner$l(polygonGroup).data.getItemGraphicEl(oldIdx);
        var layout = areaData.getItemLayout(newIdx);

        if (!layout.allClipped) {
          if (polygon) {
            updateProps(polygon, {
              shape: {
                points: layout.points
              }
            }, maModel, newIdx);
          } else {
            polygon = new Polygon({
              shape: {
                points: layout.points
              }
            });
          }

          areaData.setItemGraphicEl(newIdx, polygon);
          polygonGroup.group.add(polygon);
        } else if (polygon) {
          polygonGroup.group.remove(polygon);
        }
      }).remove(function (idx) {
        var polygon = inner$l(polygonGroup).data.getItemGraphicEl(idx);
        polygonGroup.group.remove(polygon);
      }).execute();
      areaData.eachItemGraphicEl(function (polygon, idx) {
        var itemModel = areaData.getItemModel(idx);
        var style = areaData.getItemVisual(idx, 'style');
        polygon.useStyle(areaData.getItemVisual(idx, 'style'));
        setLabelStyle(polygon, getLabelStatesModels(itemModel), {
          labelFetcher: maModel,
          labelDataIndex: idx,
          defaultText: areaData.getName(idx) || '',
          inheritColor: typeof style.fill === 'string' ? modifyAlpha(style.fill, 1) : '#000'
        });
        setStatesStylesFromModel(polygon, itemModel);
        enableHoverEmphasis(polygon);
        getECData(polygon).dataModel = maModel;
      });
      inner$l(polygonGroup).data = areaData;
      polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent');
    };

    MarkAreaView.type = 'markArea';
    return MarkAreaView;
  }(MarkerView);

  function createList$3(coordSys, seriesModel, maModel) {
    var coordDimsInfos;
    var areaData;
    var dims = ['x0', 'y0', 'x1', 'y1'];

    if (coordSys) {
      coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
        var data = seriesModel.getData();
        var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {};
        return defaults({
          name: coordDim
        }, info);
      });
      areaData = new List(map(dims, function (dim, idx) {
        return {
          name: dim,
          type: coordDimsInfos[idx % 2].type
        };
      }), maModel);
    } else {
      coordDimsInfos = [{
        name: 'value',
        type: 'float'
      }];
      areaData = new List(coordDimsInfos, maModel);
    }

    var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel));

    if (coordSys) {
      optData = filter(optData, curry(markAreaFilter, coordSys));
    }

    var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
      return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
    } : function (item) {
      return item.value;
    };
    areaData.initData(optData, null, dimValueGetter);
    areaData.hasItemOption = true;
    return areaData;
  }

  ComponentView.registerClass(MarkAreaView);
  registerPreprocessor(function (opt) {
    opt.markArea = opt.markArea || {};
  });

  var getDefaultSelectorOptions = function (ecModel, type) {
    if (type === 'all') {
      return {
        type: 'all',
        title: ecModel.getLocale(['legend', 'selector', 'all'])
      };
    } else if (type === 'inverse') {
      return {
        type: 'inverse',
        title: ecModel.getLocale(['legend', 'selector', 'inverse'])
      };
    }
  };

  var LegendModel = function (_super) {
    __extends(LegendModel, _super);

    function LegendModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = LegendModel.type;
      _this.layoutMode = {
        type: 'box',
        ignoreSize: true
      };
      return _this;
    }

    LegendModel.prototype.init = function (option, parentModel, ecModel) {
      this.mergeDefaultAndTheme(option, ecModel);
      option.selected = option.selected || {};

      this._updateSelector(option);
    };

    LegendModel.prototype.mergeOption = function (option, ecModel) {
      _super.prototype.mergeOption.call(this, option, ecModel);

      this._updateSelector(option);
    };

    LegendModel.prototype._updateSelector = function (option) {
      var selector = option.selector;
      var ecModel = this.ecModel;

      if (selector === true) {
        selector = option.selector = ['all', 'inverse'];
      }

      if (isArray(selector)) {
        each(selector, function (item, index) {
          isString(item) && (item = {
            type: item
          });
          selector[index] = merge(item, getDefaultSelectorOptions(ecModel, item.type));
        });
      }
    };

    LegendModel.prototype.optionUpdated = function () {
      this._updateData(this.ecModel);

      var legendData = this._data;

      if (legendData[0] && this.get('selectedMode') === 'single') {
        var hasSelected = false;

        for (var i = 0; i < legendData.length; i++) {
          var name_1 = legendData[i].get('name');

          if (this.isSelected(name_1)) {
            this.select(name_1);
            hasSelected = true;
            break;
          }
        }

        !hasSelected && this.select(legendData[0].get('name'));
      }
    };

    LegendModel.prototype._updateData = function (ecModel) {
      var potentialData = [];
      var availableNames = [];
      ecModel.eachRawSeries(function (seriesModel) {
        var seriesName = seriesModel.name;
        availableNames.push(seriesName);
        var isPotential;

        if (seriesModel.legendVisualProvider) {
          var provider = seriesModel.legendVisualProvider;
          var names = provider.getAllNames();

          if (!ecModel.isSeriesFiltered(seriesModel)) {
            availableNames = availableNames.concat(names);
          }

          if (names.length) {
            potentialData = potentialData.concat(names);
          } else {
            isPotential = true;
          }
        } else {
          isPotential = true;
        }

        if (isPotential && isNameSpecified(seriesModel)) {
          potentialData.push(seriesModel.name);
        }
      });
      this._availableNames = availableNames;
      var rawData = this.get('data') || potentialData;
      var legendData = map(rawData, function (dataItem) {
        if (typeof dataItem === 'string' || typeof dataItem === 'number') {
          dataItem = {
            name: dataItem
          };
        }

        return new Model(dataItem, this, this.ecModel);
      }, this);
      this._data = legendData;
    };

    LegendModel.prototype.getData = function () {
      return this._data;
    };

    LegendModel.prototype.select = function (name) {
      var selected = this.option.selected;
      var selectedMode = this.get('selectedMode');

      if (selectedMode === 'single') {
        var data = this._data;
        each(data, function (dataItem) {
          selected[dataItem.get('name')] = false;
        });
      }

      selected[name] = true;
    };

    LegendModel.prototype.unSelect = function (name) {
      if (this.get('selectedMode') !== 'single') {
        this.option.selected[name] = false;
      }
    };

    LegendModel.prototype.toggleSelected = function (name) {
      var selected = this.option.selected;

      if (!selected.hasOwnProperty(name)) {
        selected[name] = true;
      }

      this[selected[name] ? 'unSelect' : 'select'](name);
    };

    LegendModel.prototype.allSelect = function () {
      var data = this._data;
      var selected = this.option.selected;
      each(data, function (dataItem) {
        selected[dataItem.get('name', true)] = true;
      });
    };

    LegendModel.prototype.inverseSelect = function () {
      var data = this._data;
      var selected = this.option.selected;
      each(data, function (dataItem) {
        var name = dataItem.get('name', true);

        if (!selected.hasOwnProperty(name)) {
          selected[name] = true;
        }

        selected[name] = !selected[name];
      });
    };

    LegendModel.prototype.isSelected = function (name) {
      var selected = this.option.selected;
      return !(selected.hasOwnProperty(name) && !selected[name]) && indexOf(this._availableNames, name) >= 0;
    };

    LegendModel.prototype.getOrient = function () {
      return this.get('orient') === 'vertical' ? {
        index: 1,
        name: 'vertical'
      } : {
        index: 0,
        name: 'horizontal'
      };
    };

    LegendModel.type = 'legend.plain';
    LegendModel.dependencies = ['series'];
    LegendModel.defaultOption = {
      zlevel: 0,
      z: 4,
      show: true,
      orient: 'horizontal',
      left: 'center',
      top: 0,
      align: 'auto',
      backgroundColor: 'rgba(0,0,0,0)',
      borderColor: '#ccc',
      borderRadius: 0,
      borderWidth: 0,
      padding: 5,
      itemGap: 10,
      itemWidth: 25,
      itemHeight: 14,
      inactiveColor: '#ccc',
      inactiveBorderColor: '#ccc',
      itemStyle: {
        borderWidth: 0
      },
      textStyle: {
        color: '#333'
      },
      selectedMode: true,
      selector: false,
      selectorLabel: {
        show: true,
        borderRadius: 10,
        padding: [3, 5, 3, 5],
        fontSize: 12,
        fontFamily: ' sans-serif',
        color: '#666',
        borderWidth: 1,
        borderColor: '#666'
      },
      emphasis: {
        selectorLabel: {
          show: true,
          color: '#eee',
          backgroundColor: '#666'
        }
      },
      selectorPosition: 'auto',
      selectorItemGap: 7,
      selectorButtonGap: 10,
      tooltip: {
        show: false
      }
    };
    return LegendModel;
  }(ComponentModel);

  ComponentModel.registerClass(LegendModel);

  function legendSelectActionHandler(methodName, payload, ecModel) {
    var selectedMap = {};
    var isToggleSelect = methodName === 'toggleSelected';
    var isSelected;
    ecModel.eachComponent('legend', function (legendModel) {
      if (isToggleSelect && isSelected != null) {
        legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
      } else if (methodName === 'allSelect' || methodName === 'inverseSelect') {
        legendModel[methodName]();
      } else {
        legendModel[methodName](payload.name);
        isSelected = legendModel.isSelected(payload.name);
      }

      var legendData = legendModel.getData();
      each(legendData, function (model) {
        var name = model.get('name');

        if (name === '\n' || name === '') {
          return;
        }

        var isItemSelected = legendModel.isSelected(name);

        if (selectedMap.hasOwnProperty(name)) {
          selectedMap[name] = selectedMap[name] && isItemSelected;
        } else {
          selectedMap[name] = isItemSelected;
        }
      });
    });
    return methodName === 'allSelect' || methodName === 'inverseSelect' ? {
      selected: selectedMap
    } : {
      name: payload.name,
      selected: selectedMap
    };
  }

  registerAction('legendToggleSelect', 'legendselectchanged', curry(legendSelectActionHandler, 'toggleSelected'));
  registerAction('legendAllSelect', 'legendselectall', curry(legendSelectActionHandler, 'allSelect'));
  registerAction('legendInverseSelect', 'legendinverseselect', curry(legendSelectActionHandler, 'inverseSelect'));
  registerAction('legendSelect', 'legendselected', curry(legendSelectActionHandler, 'select'));
  registerAction('legendUnSelect', 'legendunselected', curry(legendSelectActionHandler, 'unSelect'));
  var curry$1 = curry;
  var each$e = each;
  var Group$2 = Group;

  var LegendView = function (_super) {
    __extends(LegendView, _super);

    function LegendView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = LegendView.type;
      _this.newlineDisabled = false;
      return _this;
    }

    LegendView.prototype.init = function () {
      this.group.add(this._contentGroup = new Group$2());
      this.group.add(this._selectorGroup = new Group$2());
      this._isFirstRender = true;
    };

    LegendView.prototype.getContentGroup = function () {
      return this._contentGroup;
    };

    LegendView.prototype.getSelectorGroup = function () {
      return this._selectorGroup;
    };

    LegendView.prototype.render = function (legendModel, ecModel, api) {
      var isFirstRender = this._isFirstRender;
      this._isFirstRender = false;
      this.resetInner();

      if (!legendModel.get('show', true)) {
        return;
      }

      var itemAlign = legendModel.get('align');
      var orient = legendModel.get('orient');

      if (!itemAlign || itemAlign === 'auto') {
        itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left';
      }

      var selector = legendModel.get('selector', true);
      var selectorPosition = legendModel.get('selectorPosition', true);

      if (selector && (!selectorPosition || selectorPosition === 'auto')) {
        selectorPosition = orient === 'horizontal' ? 'end' : 'start';
      }

      this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);
      var positionInfo = legendModel.getBoxLayoutParams();
      var viewportSize = {
        width: api.getWidth(),
        height: api.getHeight()
      };
      var padding = legendModel.get('padding');
      var maxSize = getLayoutRect(positionInfo, viewportSize, padding);
      var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition);
      var layoutRect = getLayoutRect(defaults({
        width: mainRect.width,
        height: mainRect.height
      }, positionInfo), viewportSize, padding);
      this.group.x = layoutRect.x - mainRect.x;
      this.group.y = layoutRect.y - mainRect.y;
      this.group.markRedraw();
      this.group.add(this._backgroundEl = makeBackground(mainRect, legendModel));
    };

    LegendView.prototype.resetInner = function () {
      this.getContentGroup().removeAll();
      this._backgroundEl && this.group.remove(this._backgroundEl);
      this.getSelectorGroup().removeAll();
    };

    LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
      var contentGroup = this.getContentGroup();
      var legendDrawnMap = createHashMap();
      var selectMode = legendModel.get('selectedMode');
      var excludeSeriesId = [];
      ecModel.eachRawSeries(function (seriesModel) {
        !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id);
      });
      each$e(legendModel.getData(), function (itemModel, dataIndex) {
        var name = itemModel.get('name');

        if (!this.newlineDisabled && (name === '' || name === '\n')) {
          var g = new Group$2();
          g.newline = true;
          contentGroup.add(g);
          return;
        }

        var seriesModel = ecModel.getSeriesByName(name)[0];

        if (legendDrawnMap.get(name)) {
          return;
        }

        if (seriesModel) {
          var data = seriesModel.getData();
          var style = data.getVisual('style');
          var color = style[data.getVisual('drawType')] || style.fill;
          var borderColor = style.stroke;
          var decal = style.decal;
          var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
          var symbolType = data.getVisual('symbol');

          var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode);

          itemGroup.on('click', curry$1(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
          legendDrawnMap.set(name, true);
        } else {
          ecModel.eachRawSeries(function (seriesModel) {
            if (legendDrawnMap.get(name)) {
              return;
            }

            if (seriesModel.legendVisualProvider) {
              var provider = seriesModel.legendVisualProvider;

              if (!provider.containName(name)) {
                return;
              }

              var idx = provider.indexOfName(name);
              var style = provider.getItemVisual(idx, 'style');
              var borderColor = style.stroke;
              var decal = style.decal;
              var color = style.fill;
              var colorArr = parse(style.fill);

              if (colorArr && colorArr[3] === 0) {
                colorArr[3] = 0.2;
                color = stringify(colorArr, 'rgba');
              }

              var legendSymbolType = 'roundRect';

              var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, null, itemAlign, color, borderColor, decal, selectMode);

              itemGroup.on('click', curry$1(dispatchSelectAction, null, name, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, null, name, api, excludeSeriesId));
              legendDrawnMap.set(name, true);
            }
          }, this);
        }

        if (true) {
          if (!legendDrawnMap.get(name)) {
            console.warn(name + ' series not exists. Legend data should be same with series name or data name.');
          }
        }
      }, this);

      if (selector) {
        this._createSelector(selector, legendModel, api, orient, selectorPosition);
      }
    };

    LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) {
      var selectorGroup = this.getSelectorGroup();
      each$e(selector, function createSelectorButton(selectorItem) {
        var type = selectorItem.type;
        var labelText = new ZRText({
          style: {
            x: 0,
            y: 0,
            align: 'center',
            verticalAlign: 'middle'
          },
          onclick: function () {
            api.dispatchAction({
              type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect'
            });
          }
        });
        selectorGroup.add(labelText);
        var labelModel = legendModel.getModel('selectorLabel');
        var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']);
        setLabelStyle(labelText, {
          normal: labelModel,
          emphasis: emphasisLabelModel
        }, {
          defaultText: selectorItem.title
        });
        enableHoverEmphasis(labelText);
      });
    };

    LegendView.prototype._createItem = function (name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode) {
      var itemWidth = legendModel.get('itemWidth');
      var itemHeight = legendModel.get('itemHeight');
      var inactiveColor = legendModel.get('inactiveColor');
      var inactiveBorderColor = legendModel.get('inactiveBorderColor');
      var symbolKeepAspect = legendModel.get('symbolKeepAspect');
      var legendModelItemStyle = legendModel.getModel('itemStyle');
      var isSelected = legendModel.isSelected(name);
      var itemGroup = new Group$2();
      var textStyleModel = itemModel.getModel('textStyle');
      var itemIcon = itemModel.get('icon');
      var tooltipModel = itemModel.getModel('tooltip');
      var legendGlobalTooltipModel = tooltipModel.parentModel;
      legendSymbolType = itemIcon || legendSymbolType;
      var legendSymbol = createSymbol(legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor, symbolKeepAspect == null ? true : symbolKeepAspect);
      itemGroup.add(setSymbolStyle(legendSymbol, legendSymbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected));

      if (!itemIcon && symbolType && (symbolType !== legendSymbolType || symbolType === 'none')) {
        var size = itemHeight * 0.8;

        if (symbolType === 'none') {
          symbolType = 'circle';
        }

        var legendSymbolCenter = createSymbol(symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size, isSelected ? color : inactiveColor, symbolKeepAspect == null ? true : symbolKeepAspect);
        itemGroup.add(setSymbolStyle(legendSymbolCenter, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected));
      }

      var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
      var textAlign = itemAlign;
      var formatter = legendModel.get('formatter');
      var content = name;

      if (typeof formatter === 'string' && formatter) {
        content = formatter.replace('{name}', name != null ? name : '');
      } else if (typeof formatter === 'function') {
        content = formatter(name);
      }

      itemGroup.add(new ZRText({
        style: createTextStyle(textStyleModel, {
          text: content,
          x: textX,
          y: itemHeight / 2,
          fill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
          align: textAlign,
          verticalAlign: 'middle'
        })
      }));
      var hitRect = new Rect({
        shape: itemGroup.getBoundingRect(),
        invisible: true
      });

      if (tooltipModel.get('show')) {
        var formatterParams = {
          componentType: 'legend',
          legendIndex: legendModel.componentIndex,
          name: name,
          $vars: ['name']
        };
        hitRect.tooltip = extend({
          content: name,
          formatter: legendGlobalTooltipModel.get('formatter', true) || function (params) {
            return params.name;
          },
          formatterParams: formatterParams
        }, tooltipModel.option);
      }

      itemGroup.add(hitRect);
      itemGroup.eachChild(function (child) {
        child.silent = true;
      });
      hitRect.silent = !selectMode;
      this.getContentGroup().add(itemGroup);
      enableHoverEmphasis(itemGroup);
      itemGroup.__legendDataIndex = dataIndex;
      return itemGroup;
    };

    LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
      var contentGroup = this.getContentGroup();
      var selectorGroup = this.getSelectorGroup();
      box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height);
      var contentRect = contentGroup.getBoundingRect();
      var contentPos = [-contentRect.x, -contentRect.y];
      selectorGroup.markRedraw();
      contentGroup.markRedraw();

      if (selector) {
        box('horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
        var selectorRect = selectorGroup.getBoundingRect();
        var selectorPos = [-selectorRect.x, -selectorRect.y];
        var selectorButtonGap = legendModel.get('selectorButtonGap', true);
        var orientIdx = legendModel.getOrient().index;
        var wh = orientIdx === 0 ? 'width' : 'height';
        var hw = orientIdx === 0 ? 'height' : 'width';
        var yx = orientIdx === 0 ? 'y' : 'x';

        if (selectorPosition === 'end') {
          selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap;
        } else {
          contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap;
        }

        selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2;
        selectorGroup.x = selectorPos[0];
        selectorGroup.y = selectorPos[1];
        contentGroup.x = contentPos[0];
        contentGroup.y = contentPos[1];
        var mainRect = {
          x: 0,
          y: 0
        };
        mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh];
        mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]);
        mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]);
        return mainRect;
      } else {
        contentGroup.x = contentPos[0];
        contentGroup.y = contentPos[1];
        return this.group.getBoundingRect();
      }
    };

    LegendView.prototype.remove = function () {
      this.getContentGroup().removeAll();
      this._isFirstRender = true;
    };

    LegendView.type = 'legend.plain';
    return LegendView;
  }(ComponentView);

  function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected) {
    var itemStyle;

    if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
      itemStyle = legendModelItemStyle.getItemStyle();
      symbol.style.stroke = borderColor;
      symbol.style.decal = decal;

      if (!isSelected) {
        itemStyle.stroke = inactiveBorderColor;
      }
    } else {
      itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']);
    }

    symbol.setStyle(itemStyle);
    return symbol;
  }

  function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
    dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
    api.dispatchAction({
      type: 'legendToggleSelect',
      name: seriesName != null ? seriesName : dataName
    });
    dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
  }

  function isUseHoverLayer(api) {
    var list = api.getZr().storage.getDisplayList();
    var emphasisState;
    var i = 0;
    var len = list.length;

    while (i < len && !(emphasisState = list[i].states.emphasis)) {
      i++;
    }

    return emphasisState && emphasisState.hoverLayer;
  }

  function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
    if (!isUseHoverLayer(api)) {
      api.dispatchAction({
        type: 'highlight',
        seriesName: seriesName,
        name: dataName,
        excludeSeriesId: excludeSeriesId
      });
    }
  }

  function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) {
    if (!isUseHoverLayer(api)) {
      api.dispatchAction({
        type: 'downplay',
        seriesName: seriesName,
        name: dataName,
        excludeSeriesId: excludeSeriesId
      });
    }
  }

  ComponentView.registerClass(LegendView);

  function legendFilter(ecModel) {
    var legendModels = ecModel.findComponents({
      mainType: 'legend'
    });

    if (legendModels && legendModels.length) {
      ecModel.filterSeries(function (series) {
        for (var i = 0; i < legendModels.length; i++) {
          if (!legendModels[i].isSelected(series.name)) {
            return false;
          }
        }

        return true;
      });
    }
  }

  registerProcessor(PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter);
  ComponentModel.registerSubTypeDefaulter('legend', function () {
    return 'plain';
  });

  var ScrollableLegendModel = function (_super) {
    __extends(ScrollableLegendModel, _super);

    function ScrollableLegendModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ScrollableLegendModel.type;
      return _this;
    }

    ScrollableLegendModel.prototype.setScrollDataIndex = function (scrollDataIndex) {
      this.option.scrollDataIndex = scrollDataIndex;
    };

    ScrollableLegendModel.prototype.init = function (option, parentModel, ecModel) {
      var inputPositionParams = getLayoutParams(option);

      _super.prototype.init.call(this, option, parentModel, ecModel);

      mergeAndNormalizeLayoutParams$1(this, option, inputPositionParams);
    };

    ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) {
      _super.prototype.mergeOption.call(this, option, ecModel);

      mergeAndNormalizeLayoutParams$1(this, this.option, option);
    };

    ScrollableLegendModel.type = 'legend.scroll';
    ScrollableLegendModel.defaultOption = inheritDefaultOption(LegendModel.defaultOption, {
      scrollDataIndex: 0,
      pageButtonItemGap: 5,
      pageButtonGap: null,
      pageButtonPosition: 'end',
      pageFormatter: '{current}/{total}',
      pageIcons: {
        horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'],
        vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z']
      },
      pageIconColor: '#2f4554',
      pageIconInactiveColor: '#aaa',
      pageIconSize: 15,
      pageTextStyle: {
        color: '#333'
      },
      animationDurationUpdate: 800
    });
    return ScrollableLegendModel;
  }(LegendModel);

  function mergeAndNormalizeLayoutParams$1(legendModel, target, raw) {
    var orient = legendModel.getOrient();
    var ignoreSize = [1, 1];
    ignoreSize[orient.index] = 0;
    mergeLayoutParam(target, raw, {
      type: 'box',
      ignoreSize: !!ignoreSize
    });
  }

  ComponentModel.registerClass(ScrollableLegendModel);
  var Group$3 = Group;
  var WH$1 = ['width', 'height'];
  var XY$1 = ['x', 'y'];

  var ScrollableLegendView = function (_super) {
    __extends(ScrollableLegendView, _super);

    function ScrollableLegendView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ScrollableLegendView.type;
      _this.newlineDisabled = true;
      _this._currentIndex = 0;
      return _this;
    }

    ScrollableLegendView.prototype.init = function () {
      _super.prototype.init.call(this);

      this.group.add(this._containerGroup = new Group$3());

      this._containerGroup.add(this.getContentGroup());

      this.group.add(this._controllerGroup = new Group$3());
    };

    ScrollableLegendView.prototype.resetInner = function () {
      _super.prototype.resetInner.call(this);

      this._controllerGroup.removeAll();

      this._containerGroup.removeClipPath();

      this._containerGroup.__rectSize = null;
    };

    ScrollableLegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
      var self = this;

      _super.prototype.renderInner.call(this, itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);

      var controllerGroup = this._controllerGroup;
      var pageIconSize = legendModel.get('pageIconSize', true);
      var pageIconSizeArr = isArray(pageIconSize) ? pageIconSize : [pageIconSize, pageIconSize];
      createPageButton('pagePrev', 0);
      var pageTextStyleModel = legendModel.getModel('pageTextStyle');
      controllerGroup.add(new ZRText({
        name: 'pageText',
        style: {
          text: 'xx/xx',
          fill: pageTextStyleModel.getTextColor(),
          font: pageTextStyleModel.getFont(),
          verticalAlign: 'middle',
          align: 'center'
        },
        silent: true
      }));
      createPageButton('pageNext', 1);

      function createPageButton(name, iconIdx) {
        var pageDataIndexName = name + 'DataIndex';
        var icon = createIcon(legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], {
          onclick: bind(self._pageGo, self, pageDataIndexName, legendModel, api)
        }, {
          x: -pageIconSizeArr[0] / 2,
          y: -pageIconSizeArr[1] / 2,
          width: pageIconSizeArr[0],
          height: pageIconSizeArr[1]
        });
        icon.name = name;
        controllerGroup.add(icon);
      }
    };

    ScrollableLegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
      var selectorGroup = this.getSelectorGroup();
      var orientIdx = legendModel.getOrient().index;
      var wh = WH$1[orientIdx];
      var xy = XY$1[orientIdx];
      var hw = WH$1[1 - orientIdx];
      var yx = XY$1[1 - orientIdx];
      selector && box('horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
      var selectorButtonGap = legendModel.get('selectorButtonGap', true);
      var selectorRect = selectorGroup.getBoundingRect();
      var selectorPos = [-selectorRect.x, -selectorRect.y];
      var processMaxSize = clone(maxSize);
      selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap);

      var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx, xy);

      if (selector) {
        if (selectorPosition === 'end') {
          selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap;
        } else {
          var offset = selectorRect[wh] + selectorButtonGap;
          selectorPos[orientIdx] -= offset;
          mainRect[xy] -= offset;
        }

        mainRect[wh] += selectorRect[wh] + selectorButtonGap;
        selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2;
        mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]);
        mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]);
        selectorGroup.x = selectorPos[0];
        selectorGroup.y = selectorPos[1];
        selectorGroup.markRedraw();
      }

      return mainRect;
    };

    ScrollableLegendView.prototype._layoutContentAndController = function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx, xy) {
      var contentGroup = this.getContentGroup();
      var containerGroup = this._containerGroup;
      var controllerGroup = this._controllerGroup;
      box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height);
      box('horizontal', controllerGroup, legendModel.get('pageButtonItemGap', true));
      var contentRect = contentGroup.getBoundingRect();
      var controllerRect = controllerGroup.getBoundingRect();
      var showController = this._showController = contentRect[wh] > maxSize[wh];
      var contentPos = [-contentRect.x, -contentRect.y];

      if (!isFirstRender) {
        contentPos[orientIdx] = contentGroup[xy];
      }

      var containerPos = [0, 0];
      var controllerPos = [-controllerRect.x, -controllerRect.y];
      var pageButtonGap = retrieve2(legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true));

      if (showController) {
        var pageButtonPosition = legendModel.get('pageButtonPosition', true);

        if (pageButtonPosition === 'end') {
          controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh];
        } else {
          containerPos[orientIdx] += controllerRect[wh] + pageButtonGap;
        }
      }

      controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2;
      contentGroup.setPosition(contentPos);
      containerGroup.setPosition(containerPos);
      controllerGroup.setPosition(controllerPos);
      var mainRect = {
        x: 0,
        y: 0
      };
      mainRect[wh] = showController ? maxSize[wh] : contentRect[wh];
      mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]);
      mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]);
      containerGroup.__rectSize = maxSize[wh];

      if (showController) {
        var clipShape = {
          x: 0,
          y: 0
        };
        clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0);
        clipShape[hw] = mainRect[hw];
        containerGroup.setClipPath(new Rect({
          shape: clipShape
        }));
        containerGroup.__rectSize = clipShape[wh];
      } else {
        controllerGroup.eachChild(function (child) {
          child.attr({
            invisible: true,
            silent: true
          });
        });
      }

      var pageInfo = this._getPageInfo(legendModel);

      pageInfo.pageIndex != null && updateProps(contentGroup, {
        x: pageInfo.contentPosition[0],
        y: pageInfo.contentPosition[1]
      }, showController ? legendModel : null);

      this._updatePageInfoView(legendModel, pageInfo);

      return mainRect;
    };

    ScrollableLegendView.prototype._pageGo = function (to, legendModel, api) {
      var scrollDataIndex = this._getPageInfo(legendModel)[to];

      scrollDataIndex != null && api.dispatchAction({
        type: 'legendScroll',
        scrollDataIndex: scrollDataIndex,
        legendId: legendModel.id
      });
    };

    ScrollableLegendView.prototype._updatePageInfoView = function (legendModel, pageInfo) {
      var controllerGroup = this._controllerGroup;
      each(['pagePrev', 'pageNext'], function (name) {
        var key = name + 'DataIndex';
        var canJump = pageInfo[key] != null;
        var icon = controllerGroup.childOfName(name);

        if (icon) {
          icon.setStyle('fill', canJump ? legendModel.get('pageIconColor', true) : legendModel.get('pageIconInactiveColor', true));
          icon.cursor = canJump ? 'pointer' : 'default';
        }
      });
      var pageText = controllerGroup.childOfName('pageText');
      var pageFormatter = legendModel.get('pageFormatter');
      var pageIndex = pageInfo.pageIndex;
      var current = pageIndex != null ? pageIndex + 1 : 0;
      var total = pageInfo.pageCount;
      pageText && pageFormatter && pageText.setStyle('text', isString(pageFormatter) ? pageFormatter.replace('{current}', current == null ? '' : current + '').replace('{total}', total == null ? '' : total + '') : pageFormatter({
        current: current,
        total: total
      }));
    };

    ScrollableLegendView.prototype._getPageInfo = function (legendModel) {
      var scrollDataIndex = legendModel.get('scrollDataIndex', true);
      var contentGroup = this.getContentGroup();
      var containerRectSize = this._containerGroup.__rectSize;
      var orientIdx = legendModel.getOrient().index;
      var wh = WH$1[orientIdx];
      var xy = XY$1[orientIdx];

      var targetItemIndex = this._findTargetItemIndex(scrollDataIndex);

      var children = contentGroup.children();
      var targetItem = children[targetItemIndex];
      var itemCount = children.length;
      var pCount = !itemCount ? 0 : 1;
      var result = {
        contentPosition: [contentGroup.x, contentGroup.y],
        pageCount: pCount,
        pageIndex: pCount - 1,
        pagePrevDataIndex: null,
        pageNextDataIndex: null
      };

      if (!targetItem) {
        return result;
      }

      var targetItemInfo = getItemInfo(targetItem);
      result.contentPosition[orientIdx] = -targetItemInfo.s;

      for (var i = targetItemIndex + 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i <= itemCount; ++i) {
        currItemInfo = getItemInfo(children[i]);

        if (!currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize || currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) {
          if (winEndItemInfo.i > winStartItemInfo.i) {
            winStartItemInfo = winEndItemInfo;
          } else {
            winStartItemInfo = currItemInfo;
          }

          if (winStartItemInfo) {
            if (result.pageNextDataIndex == null) {
              result.pageNextDataIndex = winStartItemInfo.i;
            }

            ++result.pageCount;
          }
        }

        winEndItemInfo = currItemInfo;
      }

      for (var i = targetItemIndex - 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i >= -1; --i) {
        currItemInfo = getItemInfo(children[i]);

        if ((!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s)) && winStartItemInfo.i < winEndItemInfo.i) {
          winEndItemInfo = winStartItemInfo;

          if (result.pagePrevDataIndex == null) {
            result.pagePrevDataIndex = winStartItemInfo.i;
          }

          ++result.pageCount;
          ++result.pageIndex;
        }

        winStartItemInfo = currItemInfo;
      }

      return result;

      function getItemInfo(el) {
        if (el) {
          var itemRect = el.getBoundingRect();
          var start = itemRect[xy] + el[xy];
          return {
            s: start,
            e: start + itemRect[wh],
            i: el.__legendDataIndex
          };
        }
      }

      function intersect(itemInfo, winStart) {
        return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize;
      }
    };

    ScrollableLegendView.prototype._findTargetItemIndex = function (targetDataIndex) {
      if (!this._showController) {
        return 0;
      }

      var index;
      var contentGroup = this.getContentGroup();
      var defaultIndex;
      contentGroup.eachChild(function (child, idx) {
        var legendDataIdx = child.__legendDataIndex;

        if (defaultIndex == null && legendDataIdx != null) {
          defaultIndex = idx;
        }

        if (legendDataIdx === targetDataIndex) {
          index = idx;
        }
      });
      return index != null ? index : defaultIndex;
    };

    ScrollableLegendView.type = 'legend.scroll';
    return ScrollableLegendView;
  }(LegendView);

  ComponentView.registerClass(ScrollableLegendView);
  registerAction('legendScroll', 'legendscroll', function (payload, ecModel) {
    var scrollDataIndex = payload.scrollDataIndex;
    scrollDataIndex != null && ecModel.eachComponent({
      mainType: 'legend',
      subType: 'scroll',
      query: payload
    }, function (legendModel) {
      legendModel.setScrollDataIndex(scrollDataIndex);
    });
  });

  var SliderZoomModel = function (_super) {
    __extends(SliderZoomModel, _super);

    function SliderZoomModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SliderZoomModel.type;
      return _this;
    }

    SliderZoomModel.type = 'dataZoom.slider';
    SliderZoomModel.layoutMode = 'box';
    SliderZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, {
      show: true,
      right: 'ph',
      top: 'ph',
      width: 'ph',
      height: 'ph',
      left: null,
      bottom: null,
      borderColor: '#d2dbee',
      borderRadius: 3,
      backgroundColor: 'rgba(47,69,84,0)',
      dataBackground: {
        lineStyle: {
          color: '#d2dbee',
          width: 0.5
        },
        areaStyle: {
          color: '#d2dbee',
          opacity: 0.2
        }
      },
      selectedDataBackground: {
        lineStyle: {
          color: '#8fb0f7',
          width: 0.5
        },
        areaStyle: {
          color: '#8fb0f7',
          opacity: 0.2
        }
      },
      fillerColor: 'rgba(135,175,274,0.2)',
      handleIcon: 'path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z',
      handleSize: '100%',
      handleStyle: {
        color: '#fff',
        borderColor: '#ACB8D1'
      },
      moveHandleSize: 7,
      moveHandleIcon: 'path://M-320.9-50L-320.9-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-348-41-339-50-320.9-50z M-212.3-50L-212.3-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-239.4-41-230.4-50-212.3-50z M-103.7-50L-103.7-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-130.9-41-121.8-50-103.7-50z',
      moveHandleStyle: {
        color: '#D2DBEE',
        opacity: 0.7
      },
      showDetail: true,
      showDataShadow: 'auto',
      realtime: true,
      zoomLock: false,
      textStyle: {
        color: '#6E7079'
      },
      brushSelect: true,
      brushStyle: {
        color: 'rgba(135,175,274,0.15)'
      },
      emphasis: {
        handleStyle: {
          borderColor: '#8FB0F7'
        },
        moveHandleStyle: {
          color: '#8FB0F7'
        }
      }
    });
    return SliderZoomModel;
  }(DataZoomModel);

  ComponentModel.registerClass(SliderZoomModel);
  var Rect$2 = Rect;
  var DEFAULT_LOCATION_EDGE_GAP = 7;
  var DEFAULT_FRAME_BORDER_WIDTH = 1;
  var DEFAULT_FILLER_SIZE = 30;
  var DEFAULT_MOVE_HANDLE_SIZE = 7;
  var HORIZONTAL = 'horizontal';
  var VERTICAL = 'vertical';
  var LABEL_GAP = 5;
  var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter'];
  var REALTIME_ANIMATION_CONFIG = {
    easing: 'cubicOut',
    duration: 100
  };

  var SliderZoomView = function (_super) {
    __extends(SliderZoomView, _super);

    function SliderZoomView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = SliderZoomView.type;
      _this._displayables = {};
      return _this;
    }

    SliderZoomView.prototype.init = function (ecModel, api) {
      this.api = api;
      this._onBrush = bind(this._onBrush, this);
      this._onBrushEnd = bind(this._onBrushEnd, this);
    };

    SliderZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) {
      _super.prototype.render.apply(this, arguments);

      createOrUpdate(this, '_dispatchZoomAction', dataZoomModel.get('throttle'), 'fixRate');
      this._orient = dataZoomModel.getOrient();

      if (dataZoomModel.get('show') === false) {
        this.group.removeAll();
        return;
      }

      if (dataZoomModel.noTarget()) {
        this._clear();

        this.group.removeAll();
        return;
      }

      if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
        this._buildView();
      }

      this._updateView();
    };

    SliderZoomView.prototype.dispose = function () {
      this._clear();

      _super.prototype.dispose.apply(this, arguments);
    };

    SliderZoomView.prototype._clear = function () {
      clear(this, '_dispatchZoomAction');
      var zr = this.api.getZr();
      zr.off('mousemove', this._onBrush);
      zr.off('mouseup', this._onBrushEnd);
    };

    SliderZoomView.prototype._buildView = function () {
      var thisGroup = this.group;
      thisGroup.removeAll();
      this._brushing = false;
      this._displayables.brushRect = null;

      this._resetLocation();

      this._resetInterval();

      var barGroup = this._displayables.sliderGroup = new Group();

      this._renderBackground();

      this._renderHandle();

      this._renderDataShadow();

      thisGroup.add(barGroup);

      this._positionGroup();
    };

    SliderZoomView.prototype._resetLocation = function () {
      var dataZoomModel = this.dataZoomModel;
      var api = this.api;
      var showMoveHandle = dataZoomModel.get('brushSelect');
      var moveHandleSize = showMoveHandle ? DEFAULT_MOVE_HANDLE_SIZE : 0;

      var coordRect = this._findCoordRect();

      var ecSize = {
        width: api.getWidth(),
        height: api.getHeight()
      };
      var positionInfo = this._orient === HORIZONTAL ? {
        right: ecSize.width - coordRect.x - coordRect.width,
        top: ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP - moveHandleSize,
        width: coordRect.width,
        height: DEFAULT_FILLER_SIZE
      } : {
        right: DEFAULT_LOCATION_EDGE_GAP,
        top: coordRect.y,
        width: DEFAULT_FILLER_SIZE,
        height: coordRect.height
      };
      var layoutParams = getLayoutParams(dataZoomModel.option);
      each(['right', 'top', 'width', 'height'], function (name) {
        if (layoutParams[name] === 'ph') {
          layoutParams[name] = positionInfo[name];
        }
      });
      var layoutRect = getLayoutRect(layoutParams, ecSize);
      this._location = {
        x: layoutRect.x,
        y: layoutRect.y
      };
      this._size = [layoutRect.width, layoutRect.height];
      this._orient === VERTICAL && this._size.reverse();
    };

    SliderZoomView.prototype._positionGroup = function () {
      var thisGroup = this.group;
      var location = this._location;
      var orient = this._orient;
      var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel();
      var inverse = targetAxisModel && targetAxisModel.get('inverse');
      var sliderGroup = this._displayables.sliderGroup;
      var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse;
      sliderGroup.attr(orient === HORIZONTAL && !inverse ? {
        scaleY: otherAxisInverse ? 1 : -1,
        scaleX: 1
      } : orient === HORIZONTAL && inverse ? {
        scaleY: otherAxisInverse ? 1 : -1,
        scaleX: -1
      } : orient === VERTICAL && !inverse ? {
        scaleY: otherAxisInverse ? -1 : 1,
        scaleX: 1,
        rotation: Math.PI / 2
      } : {
        scaleY: otherAxisInverse ? -1 : 1,
        scaleX: -1,
        rotation: Math.PI / 2
      });
      var rect = thisGroup.getBoundingRect([sliderGroup]);
      thisGroup.x = location.x - rect.x;
      thisGroup.y = location.y - rect.y;
      thisGroup.markRedraw();
    };

    SliderZoomView.prototype._getViewExtent = function () {
      return [0, this._size[0]];
    };

    SliderZoomView.prototype._renderBackground = function () {
      var dataZoomModel = this.dataZoomModel;
      var size = this._size;
      var barGroup = this._displayables.sliderGroup;
      var brushSelect = dataZoomModel.get('brushSelect');
      barGroup.add(new Rect$2({
        silent: true,
        shape: {
          x: 0,
          y: 0,
          width: size[0],
          height: size[1]
        },
        style: {
          fill: dataZoomModel.get('backgroundColor')
        },
        z2: -40
      }));
      var clickPanel = new Rect$2({
        shape: {
          x: 0,
          y: 0,
          width: size[0],
          height: size[1]
        },
        style: {
          fill: 'transparent'
        },
        z2: 0,
        onclick: bind(this._onClickPanel, this)
      });
      var zr = this.api.getZr();

      if (brushSelect) {
        clickPanel.on('mousedown', this._onBrushStart, this);
        clickPanel.cursor = 'crosshair';
        zr.on('mousemove', this._onBrush);
        zr.on('mouseup', this._onBrushEnd);
      } else {
        zr.off('mousemove', this._onBrush);
        zr.off('mouseup', this._onBrushEnd);
      }

      barGroup.add(clickPanel);
    };

    SliderZoomView.prototype._renderDataShadow = function () {
      var info = this._dataShadowInfo = this._prepareDataShadowInfo();

      this._displayables.dataShadowSegs = [];

      if (!info) {
        return;
      }

      var size = this._size;
      var seriesModel = info.series;
      var data = seriesModel.getRawData();
      var otherDim = seriesModel.getShadowDim ? seriesModel.getShadowDim() : info.otherDim;

      if (otherDim == null) {
        return;
      }

      var otherDataExtent = data.getDataExtent(otherDim);
      var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
      otherDataExtent = [otherDataExtent[0] - otherOffset, otherDataExtent[1] + otherOffset];
      var otherShadowExtent = [0, size[1]];
      var thisShadowExtent = [0, size[0]];
      var areaPoints = [[size[0], 0], [0, 0]];
      var linePoints = [];
      var step = thisShadowExtent[1] / (data.count() - 1);
      var thisCoord = 0;
      var stride = Math.round(data.count() / size[0]);
      var lastIsEmpty;
      data.each([otherDim], function (value, index) {
        if (stride > 0 && index % stride) {
          thisCoord += step;
          return;
        }

        var isEmpty = value == null || isNaN(value) || value === '';
        var otherCoord = isEmpty ? 0 : linearMap(value, otherDataExtent, otherShadowExtent, true);

        if (isEmpty && !lastIsEmpty && index) {
          areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
          linePoints.push([linePoints[linePoints.length - 1][0], 0]);
        } else if (!isEmpty && lastIsEmpty) {
          areaPoints.push([thisCoord, 0]);
          linePoints.push([thisCoord, 0]);
        }

        areaPoints.push([thisCoord, otherCoord]);
        linePoints.push([thisCoord, otherCoord]);
        thisCoord += step;
        lastIsEmpty = isEmpty;
      });
      var dataZoomModel = this.dataZoomModel;

      function createDataShadowGroup(isSelectedArea) {
        var model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground');
        var group = new Group();
        var polygon = new Polygon({
          shape: {
            points: areaPoints
          },
          segmentIgnoreThreshold: 1,
          style: model.getModel('areaStyle').getAreaStyle(),
          silent: true,
          z2: -20
        });
        var polyline = new Polyline({
          shape: {
            points: linePoints
          },
          segmentIgnoreThreshold: 1,
          style: model.getModel('lineStyle').getLineStyle(),
          silent: true,
          z2: -19
        });
        group.add(polygon);
        group.add(polyline);
        return group;
      }

      for (var i = 0; i < 3; i++) {
        var group = createDataShadowGroup(i === 1);

        this._displayables.sliderGroup.add(group);

        this._displayables.dataShadowSegs.push(group);
      }
    };

    SliderZoomView.prototype._prepareDataShadowInfo = function () {
      var dataZoomModel = this.dataZoomModel;
      var showDataShadow = dataZoomModel.get('showDataShadow');

      if (showDataShadow === false) {
        return;
      }

      var result;
      var ecModel = this.ecModel;
      dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
        var seriesModels = dataZoomModel.getAxisProxy(axisDim, axisIndex).getTargetSeriesModels();
        each(seriesModels, function (seriesModel) {
          if (result) {
            return;
          }

          if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) {
            return;
          }

          var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis;
          var otherDim = getOtherDim(axisDim);
          var otherAxisInverse;
          var coordSys = seriesModel.coordinateSystem;

          if (otherDim != null && coordSys.getOtherAxis) {
            otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse;
          }

          otherDim = seriesModel.getData().mapDimension(otherDim);
          result = {
            thisAxis: thisAxis,
            series: seriesModel,
            thisDim: axisDim,
            otherDim: otherDim,
            otherAxisInverse: otherAxisInverse
          };
        }, this);
      }, this);
      return result;
    };

    SliderZoomView.prototype._renderHandle = function () {
      var thisGroup = this.group;
      var displayables = this._displayables;
      var handles = displayables.handles = [null, null];
      var handleLabels = displayables.handleLabels = [null, null];
      var sliderGroup = this._displayables.sliderGroup;
      var size = this._size;
      var dataZoomModel = this.dataZoomModel;
      var api = this.api;
      var borderRadius = dataZoomModel.get('borderRadius') || 0;
      var brushSelect = dataZoomModel.get('brushSelect');
      var filler = displayables.filler = new Rect$2({
        silent: brushSelect,
        style: {
          fill: dataZoomModel.get('fillerColor')
        },
        textConfig: {
          position: 'inside'
        }
      });
      sliderGroup.add(filler);
      sliderGroup.add(new Rect$2({
        silent: true,
        subPixelOptimize: true,
        shape: {
          x: 0,
          y: 0,
          width: size[0],
          height: size[1],
          r: borderRadius
        },
        style: {
          stroke: dataZoomModel.get('dataBackgroundColor') || dataZoomModel.get('borderColor'),
          lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
          fill: 'rgba(0,0,0,0)'
        }
      }));
      each([0, 1], function (handleIndex) {
        var iconStr = dataZoomModel.get('handleIcon');

        if (!symbolBuildProxies[iconStr] && iconStr.indexOf('path://') < 0) {
          iconStr = 'path://' + iconStr;

          if (true) {
            deprecateLog('handleIcon now needs \'path://\' prefix when using a path string');
          }
        }

        var path = createSymbol(iconStr, -1, 0, 2, 2, null, true);
        path.attr({
          cursor: getCursor(this._orient),
          draggable: true,
          drift: bind(this._onDragMove, this, handleIndex),
          ondragend: bind(this._onDragEnd, this),
          onmouseover: bind(this._showDataInfo, this, true),
          onmouseout: bind(this._showDataInfo, this, false),
          z2: 5
        });
        var bRect = path.getBoundingRect();
        var handleSize = dataZoomModel.get('handleSize');
        this._handleHeight = parsePercent$2(handleSize, this._size[1]);
        this._handleWidth = bRect.width / bRect.height * this._handleHeight;
        path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle());
        path.style.strokeNoScale = true;
        path.rectHover = true;
        path.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'handleStyle']).getItemStyle();
        enableHoverEmphasis(path);
        var handleColor = dataZoomModel.get('handleColor');

        if (handleColor != null) {
          path.style.fill = handleColor;
        }

        sliderGroup.add(handles[handleIndex] = path);
        var textStyleModel = dataZoomModel.getModel('textStyle');
        thisGroup.add(handleLabels[handleIndex] = new ZRText({
          silent: true,
          invisible: true,
          style: {
            x: 0,
            y: 0,
            text: '',
            verticalAlign: 'middle',
            align: 'center',
            fill: textStyleModel.getTextColor(),
            font: textStyleModel.getFont()
          },
          z2: 10
        }));
      }, this);
      var actualMoveZone = filler;

      if (brushSelect) {
        var moveHandleHeight = parsePercent$2(dataZoomModel.get('moveHandleSize'), size[1]);
        var moveHandle_1 = displayables.moveHandle = new Rect({
          style: dataZoomModel.getModel('moveHandleStyle').getItemStyle(),
          silent: true,
          shape: {
            r: [0, 0, 2, 2],
            y: size[1] - 0.5,
            height: moveHandleHeight
          }
        });
        var iconSize = moveHandleHeight * 0.8;
        var moveHandleIcon = displayables.moveHandleIcon = createSymbol(dataZoomModel.get('moveHandleIcon'), -iconSize / 2, -iconSize / 2, iconSize, iconSize, '#fff', true);
        moveHandleIcon.silent = true;
        moveHandleIcon.y = size[1] + moveHandleHeight / 2 - 0.5;
        moveHandle_1.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'moveHandleStyle']).getItemStyle();
        var moveZoneExpandSize = Math.min(size[1] / 2, Math.max(moveHandleHeight, 10));
        actualMoveZone = displayables.moveZone = new Rect({
          invisible: true,
          shape: {
            y: size[1] - moveZoneExpandSize,
            height: moveHandleHeight + moveZoneExpandSize
          }
        });
        actualMoveZone.on('mouseover', function () {
          api.enterEmphasis(moveHandle_1);
        }).on('mouseout', function () {
          api.leaveEmphasis(moveHandle_1);
        });
        sliderGroup.add(moveHandle_1);
        sliderGroup.add(moveHandleIcon);
        sliderGroup.add(actualMoveZone);
      }

      actualMoveZone.attr({
        draggable: true,
        cursor: getCursor(this._orient),
        drift: bind(this._onDragMove, this, 'all'),
        ondragstart: bind(this._showDataInfo, this, true),
        ondragend: bind(this._onDragEnd, this),
        onmouseover: bind(this._showDataInfo, this, true),
        onmouseout: bind(this._showDataInfo, this, false)
      });
    };

    SliderZoomView.prototype._resetInterval = function () {
      var range = this._range = this.dataZoomModel.getPercentRange();

      var viewExtent = this._getViewExtent();

      this._handleEnds = [linearMap(range[0], [0, 100], viewExtent, true), linearMap(range[1], [0, 100], viewExtent, true)];
    };

    SliderZoomView.prototype._updateInterval = function (handleIndex, delta) {
      var dataZoomModel = this.dataZoomModel;
      var handleEnds = this._handleEnds;

      var viewExtend = this._getViewExtent();

      var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
      var percentExtent = [0, 100];
      sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null);
      var lastRange = this._range;
      var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]);
      return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1];
    };

    SliderZoomView.prototype._updateView = function (nonRealtime) {
      var displaybles = this._displayables;
      var handleEnds = this._handleEnds;
      var handleInterval = asc(handleEnds.slice());
      var size = this._size;
      each([0, 1], function (handleIndex) {
        var handle = displaybles.handles[handleIndex];
        var handleHeight = this._handleHeight;
        handle.attr({
          scaleX: handleHeight / 2,
          scaleY: handleHeight / 2,
          x: handleEnds[handleIndex] + (handleIndex ? -1 : 1),
          y: size[1] / 2 - handleHeight / 2
        });
      }, this);
      displaybles.filler.setShape({
        x: handleInterval[0],
        y: 0,
        width: handleInterval[1] - handleInterval[0],
        height: size[1]
      });
      var viewExtent = {
        x: handleInterval[0],
        width: handleInterval[1] - handleInterval[0]
      };

      if (displaybles.moveHandle) {
        displaybles.moveHandle.setShape(viewExtent);
        displaybles.moveZone.setShape(viewExtent);
        displaybles.moveZone.getBoundingRect();
        displaybles.moveHandleIcon && displaybles.moveHandleIcon.attr('x', viewExtent.x + viewExtent.width / 2);
      }

      var dataShadowSegs = displaybles.dataShadowSegs;
      var segIntervals = [0, handleInterval[0], handleInterval[1], size[0]];

      for (var i = 0; i < dataShadowSegs.length; i++) {
        var segGroup = dataShadowSegs[i];
        var clipPath = segGroup.getClipPath();

        if (!clipPath) {
          clipPath = new Rect();
          segGroup.setClipPath(clipPath);
        }

        clipPath.setShape({
          x: segIntervals[i],
          y: 0,
          width: segIntervals[i + 1] - segIntervals[i],
          height: size[1]
        });
      }

      this._updateDataInfo(nonRealtime);
    };

    SliderZoomView.prototype._updateDataInfo = function (nonRealtime) {
      var dataZoomModel = this.dataZoomModel;
      var displaybles = this._displayables;
      var handleLabels = displaybles.handleLabels;
      var orient = this._orient;
      var labelTexts = ['', ''];

      if (dataZoomModel.get('showDetail')) {
        var axisProxy = dataZoomModel.findRepresentativeAxisProxy();

        if (axisProxy) {
          var axis = axisProxy.getAxisModel().axis;
          var range = this._range;
          var dataInterval = nonRealtime ? axisProxy.calculateDataWindow({
            start: range[0],
            end: range[1]
          }).valueWindow : axisProxy.getDataValueWindow();
          labelTexts = [this._formatLabel(dataInterval[0], axis), this._formatLabel(dataInterval[1], axis)];
        }
      }

      var orderedHandleEnds = asc(this._handleEnds.slice());
      setLabel.call(this, 0);
      setLabel.call(this, 1);

      function setLabel(handleIndex) {
        var barTransform = getTransform(displaybles.handles[handleIndex].parent, this.group);
        var direction = transformDirection(handleIndex === 0 ? 'right' : 'left', barTransform);
        var offset = this._handleWidth / 2 + LABEL_GAP;
        var textPoint = applyTransform$1([orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), this._size[1] / 2], barTransform);
        handleLabels[handleIndex].setStyle({
          x: textPoint[0],
          y: textPoint[1],
          verticalAlign: orient === HORIZONTAL ? 'middle' : direction,
          align: orient === HORIZONTAL ? direction : 'center',
          text: labelTexts[handleIndex]
        });
      }
    };

    SliderZoomView.prototype._formatLabel = function (value, axis) {
      var dataZoomModel = this.dataZoomModel;
      var labelFormatter = dataZoomModel.get('labelFormatter');
      var labelPrecision = dataZoomModel.get('labelPrecision');

      if (labelPrecision == null || labelPrecision === 'auto') {
        labelPrecision = axis.getPixelPrecision();
      }

      var valueStr = value == null || isNaN(value) ? '' : axis.type === 'category' || axis.type === 'time' ? axis.scale.getLabel({
        value: Math.round(value)
      }) : value.toFixed(Math.min(labelPrecision, 20));
      return isFunction(labelFormatter) ? labelFormatter(value, valueStr) : isString(labelFormatter) ? labelFormatter.replace('{value}', valueStr) : valueStr;
    };

    SliderZoomView.prototype._showDataInfo = function (showOrHide) {
      showOrHide = this._dragging || showOrHide;
      var displayables = this._displayables;
      var handleLabels = displayables.handleLabels;
      handleLabels[0].attr('invisible', !showOrHide);
      handleLabels[1].attr('invisible', !showOrHide);
      displayables.moveHandle && this.api[showOrHide ? 'enterEmphasis' : 'leaveEmphasis'](displayables.moveHandle, 1);
    };

    SliderZoomView.prototype._onDragMove = function (handleIndex, dx, dy, event) {
      this._dragging = true;
      stop(event.event);

      var barTransform = this._displayables.sliderGroup.getLocalTransform();

      var vertex = applyTransform$1([dx, dy], barTransform, true);

      var changed = this._updateInterval(handleIndex, vertex[0]);

      var realtime = this.dataZoomModel.get('realtime');

      this._updateView(!realtime);

      changed && realtime && this._dispatchZoomAction(true);
    };

    SliderZoomView.prototype._onDragEnd = function () {
      this._dragging = false;

      this._showDataInfo(false);

      var realtime = this.dataZoomModel.get('realtime');
      !realtime && this._dispatchZoomAction(false);
    };

    SliderZoomView.prototype._onClickPanel = function (e) {
      var size = this._size;

      var localPoint = this._displayables.sliderGroup.transformCoordToLocal(e.offsetX, e.offsetY);

      if (localPoint[0] < 0 || localPoint[0] > size[0] || localPoint[1] < 0 || localPoint[1] > size[1]) {
        return;
      }

      var handleEnds = this._handleEnds;
      var center = (handleEnds[0] + handleEnds[1]) / 2;

      var changed = this._updateInterval('all', localPoint[0] - center);

      this._updateView();

      changed && this._dispatchZoomAction(false);
    };

    SliderZoomView.prototype._onBrushStart = function (e) {
      var x = e.offsetX;
      var y = e.offsetY;
      this._brushStart = new Point(x, y);
      this._brushing = true;
      this._brushStartTime = +new Date();
    };

    SliderZoomView.prototype._onBrushEnd = function (e) {
      if (!this._brushing) {
        return;
      }

      var brushRect = this._displayables.brushRect;
      this._brushing = false;

      if (!brushRect) {
        return;
      }

      brushRect.attr('ignore', true);
      var brushShape = brushRect.shape;
      var brushEndTime = +new Date();

      if (brushEndTime - this._brushStartTime < 200 && Math.abs(brushShape.width) < 5) {
        return;
      }

      var viewExtend = this._getViewExtent();

      var percentExtent = [0, 100];
      this._range = asc([linearMap(brushShape.x, viewExtend, percentExtent, true), linearMap(brushShape.x + brushShape.width, viewExtend, percentExtent, true)]);
      this._handleEnds = [brushShape.x, brushShape.x + brushShape.width];

      this._updateView();

      this._dispatchZoomAction(false);
    };

    SliderZoomView.prototype._onBrush = function (e) {
      if (this._brushing) {
        stop(e.event);

        this._updateBrushRect(e.offsetX, e.offsetY);
      }
    };

    SliderZoomView.prototype._updateBrushRect = function (mouseX, mouseY) {
      var displayables = this._displayables;
      var dataZoomModel = this.dataZoomModel;
      var brushRect = displayables.brushRect;

      if (!brushRect) {
        brushRect = displayables.brushRect = new Rect$2({
          silent: true,
          style: dataZoomModel.getModel('brushStyle').getItemStyle()
        });
        displayables.sliderGroup.add(brushRect);
      }

      brushRect.attr('ignore', false);
      var brushStart = this._brushStart;
      var sliderGroup = this._displayables.sliderGroup;
      var endPoint = sliderGroup.transformCoordToLocal(mouseX, mouseY);
      var startPoint = sliderGroup.transformCoordToLocal(brushStart.x, brushStart.y);
      var size = this._size;
      endPoint[0] = Math.max(Math.min(size[0], endPoint[0]), 0);
      brushRect.setShape({
        x: startPoint[0],
        y: 0,
        width: endPoint[0] - startPoint[0],
        height: size[1]
      });
    };

    SliderZoomView.prototype._dispatchZoomAction = function (realtime) {
      var range = this._range;
      this.api.dispatchAction({
        type: 'dataZoom',
        from: this.uid,
        dataZoomId: this.dataZoomModel.id,
        animation: realtime ? REALTIME_ANIMATION_CONFIG : null,
        start: range[0],
        end: range[1]
      });
    };

    SliderZoomView.prototype._findCoordRect = function () {
      var rect;
      var coordSysInfoList = collectReferCoordSysModelInfo(this.dataZoomModel).infoList;

      if (!rect && coordSysInfoList.length) {
        var coordSys = coordSysInfoList[0].model.coordinateSystem;
        rect = coordSys.getRect && coordSys.getRect();
      }

      if (!rect) {
        var width = this.api.getWidth();
        var height = this.api.getHeight();
        rect = {
          x: width * 0.2,
          y: height * 0.2,
          width: width * 0.6,
          height: height * 0.6
        };
      }

      return rect;
    };

    SliderZoomView.type = 'dataZoom.slider';
    return SliderZoomView;
  }(DataZoomView);

  function getOtherDim(thisDim) {
    var map = {
      x: 'y',
      y: 'x',
      radius: 'angle',
      angle: 'radius'
    };
    return map[thisDim];
  }

  function getCursor(orient) {
    return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
  }

  ComponentView.registerClass(SliderZoomView);

  var InsideZoomModel = function (_super) {
    __extends(InsideZoomModel, _super);

    function InsideZoomModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = InsideZoomModel.type;
      return _this;
    }

    InsideZoomModel.type = 'dataZoom.inside';
    InsideZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, {
      disabled: false,
      zoomLock: false,
      zoomOnMouseWheel: true,
      moveOnMouseMove: true,
      moveOnMouseWheel: false,
      preventDefaultMouseMove: true
    });
    return InsideZoomModel;
  }(DataZoomModel);

  ComponentModel.registerClass(InsideZoomModel);
  var inner$m = makeInner();
  registerProcessor(PRIORITY.PROCESSOR.FILTER, function (ecModel, api) {
    var apiInner = inner$m(api);
    var coordSysRecordMap = apiInner.coordSysRecordMap || (apiInner.coordSysRecordMap = createHashMap());
    coordSysRecordMap.each(function (coordSysRecord) {
      coordSysRecord.dataZoomInfoMap = null;
    });
    ecModel.eachComponent({
      mainType: 'dataZoom',
      subType: 'inside'
    }, function (dataZoomModel) {
      var dzReferCoordSysWrap = collectReferCoordSysModelInfo(dataZoomModel);
      each(dzReferCoordSysWrap.infoList, function (dzCoordSysInfo) {
        var coordSysUid = dzCoordSysInfo.model.uid;
        var coordSysRecord = coordSysRecordMap.get(coordSysUid) || coordSysRecordMap.set(coordSysUid, createCoordSysRecord(api, dzCoordSysInfo.model));
        var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap || (coordSysRecord.dataZoomInfoMap = createHashMap());
        dataZoomInfoMap.set(dataZoomModel.uid, {
          dzReferCoordSysInfo: dzCoordSysInfo,
          model: dataZoomModel,
          getRange: null
        });
      });
    });
    coordSysRecordMap.each(function (coordSysRecord) {
      var controller = coordSysRecord.controller;
      var firstDzInfo;
      var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap;

      if (dataZoomInfoMap) {
        var firstDzKey = dataZoomInfoMap.keys()[0];

        if (firstDzKey != null) {
          firstDzInfo = dataZoomInfoMap.get(firstDzKey);
        }
      }

      if (!firstDzInfo) {
        disposeCoordSysRecord(coordSysRecordMap, coordSysRecord);
        return;
      }

      var controllerParams = mergeControllerParams(dataZoomInfoMap);
      controller.enable(controllerParams.controlType, controllerParams.opt);
      controller.setPointerChecker(coordSysRecord.containsPoint);
      createOrUpdate(coordSysRecord, 'dispatchAction', firstDzInfo.model.get('throttle', true), 'fixRate');
    });
  });

  function setViewInfoToCoordSysRecord(api, dataZoomModel, getRange) {
    inner$m(api).coordSysRecordMap.each(function (coordSysRecord) {
      var dzInfo = coordSysRecord.dataZoomInfoMap.get(dataZoomModel.uid);

      if (dzInfo) {
        dzInfo.getRange = getRange;
      }
    });
  }

  function disposeCoordSysRecordIfNeeded(api, dataZoomModel) {
    var coordSysRecordMap = inner$m(api).coordSysRecordMap;
    var coordSysKeyArr = coordSysRecordMap.keys();

    for (var i = 0; i < coordSysKeyArr.length; i++) {
      var coordSysKey = coordSysKeyArr[i];
      var coordSysRecord = coordSysRecordMap.get(coordSysKey);
      var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap;

      if (dataZoomInfoMap) {
        var dzUid = dataZoomModel.uid;
        var dzInfo = dataZoomInfoMap.get(dzUid);

        if (dzInfo) {
          dataZoomInfoMap.removeKey(dzUid);

          if (!dataZoomInfoMap.keys().length) {
            disposeCoordSysRecord(coordSysRecordMap, coordSysRecord);
          }
        }
      }
    }
  }

  function disposeCoordSysRecord(coordSysRecordMap, coordSysRecord) {
    if (coordSysRecord) {
      coordSysRecordMap.removeKey(coordSysRecord.model.uid);
      var controller = coordSysRecord.controller;
      controller && controller.dispose();
    }
  }

  function createCoordSysRecord(api, coordSysModel) {
    var coordSysRecord = {
      model: coordSysModel,
      containsPoint: curry(containsPoint, coordSysModel),
      dispatchAction: curry(dispatchAction$1, api),
      dataZoomInfoMap: null,
      controller: null
    };
    var controller = coordSysRecord.controller = new RoamController(api.getZr());
    each(['pan', 'zoom', 'scrollMove'], function (eventName) {
      controller.on(eventName, function (event) {
        var batch = [];
        coordSysRecord.dataZoomInfoMap.each(function (dzInfo) {
          if (!event.isAvailableBehavior(dzInfo.model.option)) {
            return;
          }

          var method = (dzInfo.getRange || {})[eventName];
          var range = method && method(dzInfo.dzReferCoordSysInfo, coordSysRecord.model.mainType, coordSysRecord.controller, event);
          !dzInfo.model.get('disabled', true) && range && batch.push({
            dataZoomId: dzInfo.model.id,
            start: range[0],
            end: range[1]
          });
        });
        batch.length && coordSysRecord.dispatchAction(batch);
      });
    });
    return coordSysRecord;
  }

  function dispatchAction$1(api, batch) {
    api.dispatchAction({
      type: 'dataZoom',
      animation: {
        easing: 'cubicOut',
        duration: 100
      },
      batch: batch
    });
  }

  function containsPoint(coordSysModel, e, x, y) {
    return coordSysModel.coordinateSystem.containPoint([x, y]);
  }

  function mergeControllerParams(dataZoomInfoMap) {
    var controlType;
    var prefix = 'type_';
    var typePriority = {
      'type_true': 2,
      'type_move': 1,
      'type_false': 0,
      'type_undefined': -1
    };
    var preventDefaultMouseMove = true;
    dataZoomInfoMap.each(function (dataZoomInfo) {
      var dataZoomModel = dataZoomInfo.model;
      var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true;

      if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) {
        controlType = oneType;
      }

      preventDefaultMouseMove = preventDefaultMouseMove && dataZoomModel.get('preventDefaultMouseMove', true);
    });
    return {
      controlType: controlType,
      opt: {
        zoomOnMouseWheel: true,
        moveOnMouseMove: true,
        moveOnMouseWheel: true,
        preventDefaultMouseMove: !!preventDefaultMouseMove
      }
    };
  }

  var InsideZoomView = function (_super) {
    __extends(InsideZoomView, _super);

    function InsideZoomView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = 'dataZoom.inside';
      return _this;
    }

    InsideZoomView.prototype.render = function (dataZoomModel, ecModel, api) {
      _super.prototype.render.apply(this, arguments);

      if (dataZoomModel.noTarget()) {
        this._clear();

        return;
      }

      this.range = dataZoomModel.getPercentRange();
      setViewInfoToCoordSysRecord(api, dataZoomModel, {
        pan: bind(getRangeHandlers.pan, this),
        zoom: bind(getRangeHandlers.zoom, this),
        scrollMove: bind(getRangeHandlers.scrollMove, this)
      });
    };

    InsideZoomView.prototype.dispose = function () {
      this._clear();

      _super.prototype.dispose.apply(this, arguments);
    };

    InsideZoomView.prototype._clear = function () {
      disposeCoordSysRecordIfNeeded(this.api, this.dataZoomModel);
      this.range = null;
    };

    InsideZoomView.type = 'dataZoom.inside';
    return InsideZoomView;
  }(DataZoomView);

  var getRangeHandlers = {
    zoom: function (coordSysInfo, coordSysMainType, controller, e) {
      var lastRange = this.range;
      var range = lastRange.slice();
      var axisModel = coordSysInfo.axisModels[0];

      if (!axisModel) {
        return;
      }

      var directionInfo = getDirectionInfo[coordSysMainType](null, [e.originX, e.originY], axisModel, controller, coordSysInfo);
      var percentPoint = (directionInfo.signal > 0 ? directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel : directionInfo.pixel - directionInfo.pixelStart) / directionInfo.pixelLength * (range[1] - range[0]) + range[0];
      var scale = Math.max(1 / e.scale, 0);
      range[0] = (range[0] - percentPoint) * scale + percentPoint;
      range[1] = (range[1] - percentPoint) * scale + percentPoint;
      var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
      sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan);
      this.range = range;

      if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
        return range;
      }
    },
    pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) {
      var directionInfo = getDirectionInfo[coordSysMainType]([e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordSysInfo);
      return directionInfo.signal * (range[1] - range[0]) * directionInfo.pixel / directionInfo.pixelLength;
    }),
    scrollMove: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) {
      var directionInfo = getDirectionInfo[coordSysMainType]([0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordSysInfo);
      return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta;
    })
  };

  function makeMover(getPercentDelta) {
    return function (coordSysInfo, coordSysMainType, controller, e) {
      var lastRange = this.range;
      var range = lastRange.slice();
      var axisModel = coordSysInfo.axisModels[0];

      if (!axisModel) {
        return;
      }

      var percentDelta = getPercentDelta(range, axisModel, coordSysInfo, coordSysMainType, controller, e);
      sliderMove(percentDelta, range, [0, 100], 'all');
      this.range = range;

      if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
        return range;
      }
    };
  }

  var getDirectionInfo = {
    grid: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) {
      var axis = axisModel.axis;
      var ret = {};
      var rect = coordSysInfo.model.coordinateSystem.getRect();
      oldPoint = oldPoint || [0, 0];

      if (axis.dim === 'x') {
        ret.pixel = newPoint[0] - oldPoint[0];
        ret.pixelLength = rect.width;
        ret.pixelStart = rect.x;
        ret.signal = axis.inverse ? 1 : -1;
      } else {
        ret.pixel = newPoint[1] - oldPoint[1];
        ret.pixelLength = rect.height;
        ret.pixelStart = rect.y;
        ret.signal = axis.inverse ? -1 : 1;
      }

      return ret;
    },
    polar: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) {
      var axis = axisModel.axis;
      var ret = {};
      var polar = coordSysInfo.model.coordinateSystem;
      var radiusExtent = polar.getRadiusAxis().getExtent();
      var angleExtent = polar.getAngleAxis().getExtent();
      oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0];
      newPoint = polar.pointToCoord(newPoint);

      if (axisModel.mainType === 'radiusAxis') {
        ret.pixel = newPoint[0] - oldPoint[0];
        ret.pixelLength = radiusExtent[1] - radiusExtent[0];
        ret.pixelStart = radiusExtent[0];
        ret.signal = axis.inverse ? 1 : -1;
      } else {
        ret.pixel = newPoint[1] - oldPoint[1];
        ret.pixelLength = angleExtent[1] - angleExtent[0];
        ret.pixelStart = angleExtent[0];
        ret.signal = axis.inverse ? -1 : 1;
      }

      return ret;
    },
    singleAxis: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) {
      var axis = axisModel.axis;
      var rect = coordSysInfo.model.coordinateSystem.getRect();
      var ret = {};
      oldPoint = oldPoint || [0, 0];

      if (axis.orient === 'horizontal') {
        ret.pixel = newPoint[0] - oldPoint[0];
        ret.pixelLength = rect.width;
        ret.pixelStart = rect.x;
        ret.signal = axis.inverse ? 1 : -1;
      } else {
        ret.pixel = newPoint[1] - oldPoint[1];
        ret.pixelLength = rect.height;
        ret.pixelStart = rect.y;
        ret.signal = axis.inverse ? -1 : 1;
      }

      return ret;
    }
  };
  ComponentView.registerClass(InsideZoomView);
  var each$f = each;

  function visualMapPreprocessor(option) {
    var visualMap = option && option.visualMap;

    if (!isArray(visualMap)) {
      visualMap = visualMap ? [visualMap] : [];
    }

    each$f(visualMap, function (opt) {
      if (!opt) {
        return;
      }

      if (has$1(opt, 'splitList') && !has$1(opt, 'pieces')) {
        opt.pieces = opt.splitList;
        delete opt.splitList;
      }

      var pieces = opt.pieces;

      if (pieces && isArray(pieces)) {
        each$f(pieces, function (piece) {
          if (isObject(piece)) {
            if (has$1(piece, 'start') && !has$1(piece, 'min')) {
              piece.min = piece.start;
            }

            if (has$1(piece, 'end') && !has$1(piece, 'max')) {
              piece.max = piece.end;
            }
          }
        });
      }
    });
  }

  function has$1(obj, name) {
    return obj && obj.hasOwnProperty && obj.hasOwnProperty(name);
  }

  ComponentModel.registerSubTypeDefaulter('visualMap', function (option) {
    return !option.categories && (!(option.pieces ? option.pieces.length > 0 : option.splitNumber > 0) || option.calculable) ? 'continuous' : 'piecewise';
  });
  var VISUAL_PRIORITY = PRIORITY.VISUAL.COMPONENT;
  registerVisual(VISUAL_PRIORITY, {
    createOnAllSeries: true,
    reset: function (seriesModel, ecModel) {
      var resetDefines = [];
      ecModel.eachComponent('visualMap', function (visualMapModel) {
        var pipelineContext = seriesModel.pipelineContext;

        if (!visualMapModel.isTargetSeries(seriesModel) || pipelineContext && pipelineContext.large) {
          return;
        }

        resetDefines.push(incrementalApplyVisual(visualMapModel.stateList, visualMapModel.targetVisuals, bind(visualMapModel.getValueState, visualMapModel), visualMapModel.getDataDimension(seriesModel.getData())));
      });
      return resetDefines;
    }
  });
  registerVisual(VISUAL_PRIORITY, {
    createOnAllSeries: true,
    reset: function (seriesModel, ecModel) {
      var data = seriesModel.getData();
      var visualMetaList = [];
      ecModel.eachComponent('visualMap', function (visualMapModel) {
        if (visualMapModel.isTargetSeries(seriesModel)) {
          var visualMeta = visualMapModel.getVisualMeta(bind(getColorVisual, null, seriesModel, visualMapModel)) || {
            stops: [],
            outerColors: []
          };
          var concreteDim = visualMapModel.getDataDimension(data);
          var dimInfo = data.getDimensionInfo(concreteDim);

          if (dimInfo != null) {
            visualMeta.dimension = dimInfo.index;
            visualMetaList.push(visualMeta);
          }
        }
      });
      seriesModel.getData().setVisual('visualMeta', visualMetaList);
    }
  });

  function getColorVisual(seriesModel, visualMapModel, value, valueState) {
    var mappings = visualMapModel.targetVisuals[valueState];
    var visualTypes = VisualMapping.prepareVisualTypes(mappings);
    var resultVisual = {
      color: getVisualFromData(seriesModel.getData(), 'color')
    };

    for (var i = 0, len = visualTypes.length; i < len; i++) {
      var type = visualTypes[i];
      var mapping = mappings[type === 'opacity' ? '__alphaForOpacity' : type];
      mapping && mapping.applyVisual(value, getVisual, setVisual);
    }

    return resultVisual.color;

    function getVisual(key) {
      return resultVisual[key];
    }

    function setVisual(key, value) {
      resultVisual[key] = value;
    }
  }

  var visualDefault = {
    get: function (visualType, key, isCategory) {
      var value = clone((defaultOption$2[visualType] || {})[key]);
      return isCategory ? isArray(value) ? value[value.length - 1] : value : value;
    }
  };
  var defaultOption$2 = {
    color: {
      active: ['#006edd', '#e0ffff'],
      inactive: ['rgba(0,0,0,0)']
    },
    colorHue: {
      active: [0, 360],
      inactive: [0, 0]
    },
    colorSaturation: {
      active: [0.3, 1],
      inactive: [0, 0]
    },
    colorLightness: {
      active: [0.9, 0.5],
      inactive: [0, 0]
    },
    colorAlpha: {
      active: [0.3, 1],
      inactive: [0, 0]
    },
    opacity: {
      active: [0.3, 1],
      inactive: [0, 0]
    },
    symbol: {
      active: ['circle', 'roundRect', 'diamond'],
      inactive: ['none']
    },
    symbolSize: {
      active: [10, 50],
      inactive: [0, 0]
    }
  };
  var mapVisual$1 = VisualMapping.mapVisual;
  var eachVisual = VisualMapping.eachVisual;
  var isArray$1 = isArray;
  var each$g = each;
  var asc$2 = asc;
  var linearMap$1 = linearMap;

  var VisualMapModel = function (_super) {
    __extends(VisualMapModel, _super);

    function VisualMapModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = VisualMapModel.type;
      _this.stateList = ['inRange', 'outOfRange'];
      _this.replacableOptionKeys = ['inRange', 'outOfRange', 'target', 'controller', 'color'];
      _this.layoutMode = {
        type: 'box',
        ignoreSize: true
      };
      _this.dataBound = [-Infinity, Infinity];
      _this.targetVisuals = {};
      _this.controllerVisuals = {};
      return _this;
    }

    VisualMapModel.prototype.init = function (option, parentModel, ecModel) {
      this.mergeDefaultAndTheme(option, ecModel);
    };

    VisualMapModel.prototype.optionUpdated = function (newOption, isInit) {
      var thisOption = this.option;

      if (!env.canvasSupported) {
        thisOption.realtime = false;
      }

      !isInit && replaceVisualOption(thisOption, newOption, this.replacableOptionKeys);
      this.textStyleModel = this.getModel('textStyle');
      this.resetItemSize();
      this.completeVisualOption();
    };

    VisualMapModel.prototype.resetVisual = function (supplementVisualOption) {
      var stateList = this.stateList;
      supplementVisualOption = bind(supplementVisualOption, this);
      this.controllerVisuals = createVisualMappings(this.option.controller, stateList, supplementVisualOption);
      this.targetVisuals = createVisualMappings(this.option.target, stateList, supplementVisualOption);
    };

    VisualMapModel.prototype.getTargetSeriesIndices = function () {
      var optionSeriesIndex = this.option.seriesIndex;
      var seriesIndices = [];

      if (optionSeriesIndex == null || optionSeriesIndex === 'all') {
        this.ecModel.eachSeries(function (seriesModel, index) {
          seriesIndices.push(index);
        });
      } else {
        seriesIndices = normalizeToArray(optionSeriesIndex);
      }

      return seriesIndices;
    };

    VisualMapModel.prototype.eachTargetSeries = function (callback, context) {
      each(this.getTargetSeriesIndices(), function (seriesIndex) {
        var seriesModel = this.ecModel.getSeriesByIndex(seriesIndex);

        if (seriesModel) {
          callback.call(context, seriesModel);
        }
      }, this);
    };

    VisualMapModel.prototype.isTargetSeries = function (seriesModel) {
      var is = false;
      this.eachTargetSeries(function (model) {
        model === seriesModel && (is = true);
      });
      return is;
    };

    VisualMapModel.prototype.formatValueText = function (value, isCategory, edgeSymbols) {
      var option = this.option;
      var precision = option.precision;
      var dataBound = this.dataBound;
      var formatter = option.formatter;
      var isMinMax;
      edgeSymbols = edgeSymbols || ['<', '>'];

      if (isArray(value)) {
        value = value.slice();
        isMinMax = true;
      }

      var textValue = isCategory ? value : isMinMax ? [toFixed(value[0]), toFixed(value[1])] : toFixed(value);

      if (isString(formatter)) {
        return formatter.replace('{value}', isMinMax ? textValue[0] : textValue).replace('{value2}', isMinMax ? textValue[1] : textValue);
      } else if (isFunction(formatter)) {
        return isMinMax ? formatter(value[0], value[1]) : formatter(value);
      }

      if (isMinMax) {
        if (value[0] === dataBound[0]) {
          return edgeSymbols[0] + ' ' + textValue[1];
        } else if (value[1] === dataBound[1]) {
          return edgeSymbols[1] + ' ' + textValue[0];
        } else {
          return textValue[0] + ' - ' + textValue[1];
        }
      } else {
        return textValue;
      }

      function toFixed(val) {
        return val === dataBound[0] ? 'min' : val === dataBound[1] ? 'max' : (+val).toFixed(Math.min(precision, 20));
      }
    };

    VisualMapModel.prototype.resetExtent = function () {
      var thisOption = this.option;
      var extent = asc$2([thisOption.min, thisOption.max]);
      this._dataExtent = extent;
    };

    VisualMapModel.prototype.getDataDimension = function (list) {
      var optDim = this.option.dimension;
      var listDimensions = list.dimensions;

      if (optDim == null && !listDimensions.length) {
        return;
      }

      if (optDim != null) {
        return list.getDimension(optDim);
      }

      var dimNames = list.dimensions;

      for (var i = dimNames.length - 1; i >= 0; i--) {
        var dimName = dimNames[i];
        var dimInfo = list.getDimensionInfo(dimName);

        if (!dimInfo.isCalculationCoord) {
          return dimName;
        }
      }
    };

    VisualMapModel.prototype.getExtent = function () {
      return this._dataExtent.slice();
    };

    VisualMapModel.prototype.completeVisualOption = function () {
      var ecModel = this.ecModel;
      var thisOption = this.option;
      var base = {
        inRange: thisOption.inRange,
        outOfRange: thisOption.outOfRange
      };
      var target = thisOption.target || (thisOption.target = {});
      var controller = thisOption.controller || (thisOption.controller = {});
      merge(target, base);
      merge(controller, base);
      var isCategory = this.isCategory();
      completeSingle.call(this, target);
      completeSingle.call(this, controller);
      completeInactive.call(this, target, 'inRange', 'outOfRange');
      completeController.call(this, controller);

      function completeSingle(base) {
        if (isArray$1(thisOption.color) && !base.inRange) {
          base.inRange = {
            color: thisOption.color.slice().reverse()
          };
        }

        base.inRange = base.inRange || {
          color: ecModel.get('gradientColor')
        };
      }

      function completeInactive(base, stateExist, stateAbsent) {
        var optExist = base[stateExist];
        var optAbsent = base[stateAbsent];

        if (optExist && !optAbsent) {
          optAbsent = base[stateAbsent] = {};
          each$g(optExist, function (visualData, visualType) {
            if (!VisualMapping.isValidType(visualType)) {
              return;
            }

            var defa = visualDefault.get(visualType, 'inactive', isCategory);

            if (defa != null) {
              optAbsent[visualType] = defa;

              if (visualType === 'color' && !optAbsent.hasOwnProperty('opacity') && !optAbsent.hasOwnProperty('colorAlpha')) {
                optAbsent.opacity = [0, 0];
              }
            }
          });
        }
      }

      function completeController(controller) {
        var symbolExists = (controller.inRange || {}).symbol || (controller.outOfRange || {}).symbol;
        var symbolSizeExists = (controller.inRange || {}).symbolSize || (controller.outOfRange || {}).symbolSize;
        var inactiveColor = this.get('inactiveColor');
        each$g(this.stateList, function (state) {
          var itemSize = this.itemSize;
          var visuals = controller[state];

          if (!visuals) {
            visuals = controller[state] = {
              color: isCategory ? inactiveColor : [inactiveColor]
            };
          }

          if (visuals.symbol == null) {
            visuals.symbol = symbolExists && clone(symbolExists) || (isCategory ? 'roundRect' : ['roundRect']);
          }

          if (visuals.symbolSize == null) {
            visuals.symbolSize = symbolSizeExists && clone(symbolSizeExists) || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
          }

          visuals.symbol = mapVisual$1(visuals.symbol, function (symbol) {
            return symbol === 'none' || symbol === 'square' ? 'roundRect' : symbol;
          });
          var symbolSize = visuals.symbolSize;

          if (symbolSize != null) {
            var max_1 = -Infinity;
            eachVisual(symbolSize, function (value) {
              value > max_1 && (max_1 = value);
            });
            visuals.symbolSize = mapVisual$1(symbolSize, function (value) {
              return linearMap$1(value, [0, max_1], [0, itemSize[0]], true);
            });
          }
        }, this);
      }
    };

    VisualMapModel.prototype.resetItemSize = function () {
      this.itemSize = [parseFloat(this.get('itemWidth')), parseFloat(this.get('itemHeight'))];
    };

    VisualMapModel.prototype.isCategory = function () {
      return !!this.option.categories;
    };

    VisualMapModel.prototype.setSelected = function (selected) {};

    VisualMapModel.prototype.getSelected = function () {
      return null;
    };

    VisualMapModel.prototype.getValueState = function (value) {
      return null;
    };

    VisualMapModel.prototype.getVisualMeta = function (getColorVisual) {
      return null;
    };

    VisualMapModel.type = 'visualMap';
    VisualMapModel.dependencies = ['series'];
    VisualMapModel.defaultOption = {
      show: true,
      zlevel: 0,
      z: 4,
      seriesIndex: 'all',
      min: 0,
      max: 200,
      left: 0,
      right: null,
      top: null,
      bottom: 0,
      itemWidth: null,
      itemHeight: null,
      inverse: false,
      orient: 'vertical',
      backgroundColor: 'rgba(0,0,0,0)',
      borderColor: '#ccc',
      contentColor: '#5793f3',
      inactiveColor: '#aaa',
      borderWidth: 0,
      padding: 5,
      textGap: 10,
      precision: 0,
      textStyle: {
        color: '#333'
      }
    };
    return VisualMapModel;
  }(ComponentModel);

  var DEFAULT_BAR_BOUND = [20, 140];

  var ContinuousModel = function (_super) {
    __extends(ContinuousModel, _super);

    function ContinuousModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ContinuousModel.type;
      return _this;
    }

    ContinuousModel.prototype.optionUpdated = function (newOption, isInit) {
      _super.prototype.optionUpdated.apply(this, arguments);

      this.resetExtent();
      this.resetVisual(function (mappingOption) {
        mappingOption.mappingMethod = 'linear';
        mappingOption.dataExtent = this.getExtent();
      });

      this._resetRange();
    };

    ContinuousModel.prototype.resetItemSize = function () {
      _super.prototype.resetItemSize.apply(this, arguments);

      var itemSize = this.itemSize;
      (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]);
      (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]);
    };

    ContinuousModel.prototype._resetRange = function () {
      var dataExtent = this.getExtent();
      var range = this.option.range;

      if (!range || range.auto) {
        dataExtent.auto = 1;
        this.option.range = dataExtent;
      } else if (isArray(range)) {
        if (range[0] > range[1]) {
          range.reverse();
        }

        range[0] = Math.max(range[0], dataExtent[0]);
        range[1] = Math.min(range[1], dataExtent[1]);
      }
    };

    ContinuousModel.prototype.completeVisualOption = function () {
      _super.prototype.completeVisualOption.apply(this, arguments);

      each(this.stateList, function (state) {
        var symbolSize = this.option.controller[state].symbolSize;

        if (symbolSize && symbolSize[0] !== symbolSize[1]) {
          symbolSize[0] = symbolSize[1] / 3;
        }
      }, this);
    };

    ContinuousModel.prototype.setSelected = function (selected) {
      this.option.range = selected.slice();

      this._resetRange();
    };

    ContinuousModel.prototype.getSelected = function () {
      var dataExtent = this.getExtent();
      var dataInterval = asc((this.get('range') || []).slice());
      dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]);
      dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]);
      dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]);
      dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]);
      return dataInterval;
    };

    ContinuousModel.prototype.getValueState = function (value) {
      var range = this.option.range;
      var dataExtent = this.getExtent();
      return (range[0] <= dataExtent[0] || range[0] <= value) && (range[1] >= dataExtent[1] || value <= range[1]) ? 'inRange' : 'outOfRange';
    };

    ContinuousModel.prototype.findTargetDataIndices = function (range) {
      var result = [];
      this.eachTargetSeries(function (seriesModel) {
        var dataIndices = [];
        var data = seriesModel.getData();
        data.each(this.getDataDimension(data), function (value, dataIndex) {
          range[0] <= value && value <= range[1] && dataIndices.push(dataIndex);
        }, this);
        result.push({
          seriesId: seriesModel.id,
          dataIndex: dataIndices
        });
      }, this);
      return result;
    };

    ContinuousModel.prototype.getVisualMeta = function (getColorVisual) {
      var oVals = getColorStopValues(this, 'outOfRange', this.getExtent());
      var iVals = getColorStopValues(this, 'inRange', this.option.range.slice());
      var stops = [];

      function setStop(value, valueState) {
        stops.push({
          value: value,
          color: getColorVisual(value, valueState)
        });
      }

      var iIdx = 0;
      var oIdx = 0;
      var iLen = iVals.length;
      var oLen = oVals.length;

      for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) {
        if (oVals[oIdx] < iVals[iIdx]) {
          setStop(oVals[oIdx], 'outOfRange');
        }
      }

      for (var first = 1; iIdx < iLen; iIdx++, first = 0) {
        first && stops.length && setStop(iVals[iIdx], 'outOfRange');
        setStop(iVals[iIdx], 'inRange');
      }

      for (var first = 1; oIdx < oLen; oIdx++) {
        if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) {
          if (first) {
            stops.length && setStop(stops[stops.length - 1].value, 'outOfRange');
            first = 0;
          }

          setStop(oVals[oIdx], 'outOfRange');
        }
      }

      var stopsLen = stops.length;
      return {
        stops: stops,
        outerColors: [stopsLen ? stops[0].color : 'transparent', stopsLen ? stops[stopsLen - 1].color : 'transparent']
      };
    };

    ContinuousModel.type = 'visualMap.continuous';
    ContinuousModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, {
      align: 'auto',
      calculable: false,
      hoverLink: true,
      realtime: true,
      handleIcon: 'path://M-11.39,9.77h0a3.5,3.5,0,0,1-3.5,3.5h-22a3.5,3.5,0,0,1-3.5-3.5h0a3.5,3.5,0,0,1,3.5-3.5h22A3.5,3.5,0,0,1-11.39,9.77Z',
      handleSize: '120%',
      handleStyle: {
        borderColor: '#fff',
        borderWidth: 1
      },
      indicatorIcon: 'circle',
      indicatorSize: '50%',
      indicatorStyle: {
        borderColor: '#fff',
        borderWidth: 2,
        shadowBlur: 2,
        shadowOffsetX: 1,
        shadowOffsetY: 1,
        shadowColor: 'rgba(0,0,0,0.2)'
      }
    });
    return ContinuousModel;
  }(VisualMapModel);

  function getColorStopValues(visualMapModel, valueState, dataExtent) {
    if (dataExtent[0] === dataExtent[1]) {
      return dataExtent.slice();
    }

    var count = 200;
    var step = (dataExtent[1] - dataExtent[0]) / count;
    var value = dataExtent[0];
    var stopValues = [];

    for (var i = 0; i <= count && value < dataExtent[1]; i++) {
      stopValues.push(value);
      value += step;
    }

    stopValues.push(dataExtent[1]);
    return stopValues;
  }

  ComponentModel.registerClass(ContinuousModel);

  var VisualMapView = function (_super) {
    __extends(VisualMapView, _super);

    function VisualMapView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = VisualMapView.type;
      _this.autoPositionValues = {
        left: 1,
        right: 1,
        top: 1,
        bottom: 1
      };
      return _this;
    }

    VisualMapView.prototype.init = function (ecModel, api) {
      this.ecModel = ecModel;
      this.api = api;
    };

    VisualMapView.prototype.render = function (visualMapModel, ecModel, api, payload) {
      this.visualMapModel = visualMapModel;

      if (visualMapModel.get('show') === false) {
        this.group.removeAll();
        return;
      }

      this.doRender(visualMapModel, ecModel, api, payload);
    };

    VisualMapView.prototype.renderBackground = function (group) {
      var visualMapModel = this.visualMapModel;
      var padding = normalizeCssArray$1(visualMapModel.get('padding') || 0);
      var rect = group.getBoundingRect();
      group.add(new Rect({
        z2: -1,
        silent: true,
        shape: {
          x: rect.x - padding[3],
          y: rect.y - padding[0],
          width: rect.width + padding[3] + padding[1],
          height: rect.height + padding[0] + padding[2]
        },
        style: {
          fill: visualMapModel.get('backgroundColor'),
          stroke: visualMapModel.get('borderColor'),
          lineWidth: visualMapModel.get('borderWidth')
        }
      }));
    };

    VisualMapView.prototype.getControllerVisual = function (targetValue, visualCluster, opts) {
      opts = opts || {};
      var forceState = opts.forceState;
      var visualMapModel = this.visualMapModel;
      var visualObj = {};

      if (visualCluster === 'symbol') {
        visualObj.symbol = visualMapModel.get('itemSymbol');
      }

      if (visualCluster === 'color') {
        var defaultColor = visualMapModel.get('contentColor');
        visualObj.color = defaultColor;
      }

      function getter(key) {
        return visualObj[key];
      }

      function setter(key, value) {
        visualObj[key] = value;
      }

      var mappings = visualMapModel.controllerVisuals[forceState || visualMapModel.getValueState(targetValue)];
      var visualTypes = VisualMapping.prepareVisualTypes(mappings);
      each(visualTypes, function (type) {
        var visualMapping = mappings[type];

        if (opts.convertOpacityToAlpha && type === 'opacity') {
          type = 'colorAlpha';
          visualMapping = mappings.__alphaForOpacity;
        }

        if (VisualMapping.dependsOn(type, visualCluster)) {
          visualMapping && visualMapping.applyVisual(targetValue, getter, setter);
        }
      });
      return visualObj[visualCluster];
    };

    VisualMapView.prototype.positionGroup = function (group) {
      var model = this.visualMapModel;
      var api = this.api;
      positionElement(group, model.getBoxLayoutParams(), {
        width: api.getWidth(),
        height: api.getHeight()
      });
    };

    VisualMapView.prototype.doRender = function (visualMapModel, ecModel, api, payload) {};

    VisualMapView.type = 'visualMap';
    return VisualMapView;
  }(ComponentView);

  ComponentView.registerClass(VisualMapView);
  var paramsSet = [['left', 'right', 'width'], ['top', 'bottom', 'height']];

  function getItemAlign(visualMapModel, api, itemSize) {
    var modelOption = visualMapModel.option;
    var itemAlign = modelOption.align;

    if (itemAlign != null && itemAlign !== 'auto') {
      return itemAlign;
    }

    var ecSize = {
      width: api.getWidth(),
      height: api.getHeight()
    };
    var realIndex = modelOption.orient === 'horizontal' ? 1 : 0;
    var reals = paramsSet[realIndex];
    var fakeValue = [0, null, 10];
    var layoutInput = {};

    for (var i = 0; i < 3; i++) {
      layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i];
      layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]];
    }

    var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex];
    var rect = getLayoutRect(layoutInput, ecSize, modelOption.padding);
    return reals[(rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5 < ecSize[rParam[1]] * 0.5 ? 0 : 1];
  }

  function makeHighDownBatch(batch, visualMapModel) {
    each(batch || [], function (batchItem) {
      if (batchItem.dataIndex != null) {
        batchItem.dataIndexInside = batchItem.dataIndex;
        batchItem.dataIndex = null;
      }

      batchItem.highlightKey = 'visualMap' + (visualMapModel ? visualMapModel.componentIndex : '');
    });
    return batch;
  }

  var linearMap$2 = linearMap;
  var each$h = each;
  var mathMin$a = Math.min;
  var mathMax$a = Math.max;
  var HOVER_LINK_SIZE = 12;
  var HOVER_LINK_OUT = 6;

  var ContinuousView = function (_super) {
    __extends(ContinuousView, _super);

    function ContinuousView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = ContinuousView.type;
      _this._shapes = {};
      _this._dataInterval = [];
      _this._handleEnds = [];
      _this._hoverLinkDataIndices = [];
      return _this;
    }

    ContinuousView.prototype.doRender = function (visualMapModel, ecModel, api, payload) {
      this._api = api;

      if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
        this._buildView();
      }
    };

    ContinuousView.prototype._buildView = function () {
      this.group.removeAll();
      var visualMapModel = this.visualMapModel;
      var thisGroup = this.group;
      this._orient = visualMapModel.get('orient');
      this._useHandle = visualMapModel.get('calculable');

      this._resetInterval();

      this._renderBar(thisGroup);

      var dataRangeText = visualMapModel.get('text');

      this._renderEndsText(thisGroup, dataRangeText, 0);

      this._renderEndsText(thisGroup, dataRangeText, 1);

      this._updateView(true);

      this.renderBackground(thisGroup);

      this._updateView();

      this._enableHoverLinkToSeries();

      this._enableHoverLinkFromSeries();

      this.positionGroup(thisGroup);
    };

    ContinuousView.prototype._renderEndsText = function (group, dataRangeText, endsIndex) {
      if (!dataRangeText) {
        return;
      }

      var text = dataRangeText[1 - endsIndex];
      text = text != null ? text + '' : '';
      var visualMapModel = this.visualMapModel;
      var textGap = visualMapModel.get('textGap');
      var itemSize = visualMapModel.itemSize;
      var barGroup = this._shapes.mainGroup;

      var position = this._applyTransform([itemSize[0] / 2, endsIndex === 0 ? -textGap : itemSize[1] + textGap], barGroup);

      var align = this._applyTransform(endsIndex === 0 ? 'bottom' : 'top', barGroup);

      var orient = this._orient;
      var textStyleModel = this.visualMapModel.textStyleModel;
      this.group.add(new ZRText({
        style: {
          x: position[0],
          y: position[1],
          verticalAlign: orient === 'horizontal' ? 'middle' : align,
          align: orient === 'horizontal' ? align : 'center',
          text: text,
          font: textStyleModel.getFont(),
          fill: textStyleModel.getTextColor()
        }
      }));
    };

    ContinuousView.prototype._renderBar = function (targetGroup) {
      var visualMapModel = this.visualMapModel;
      var shapes = this._shapes;
      var itemSize = visualMapModel.itemSize;
      var orient = this._orient;
      var useHandle = this._useHandle;
      var itemAlign = getItemAlign(visualMapModel, this.api, itemSize);

      var mainGroup = shapes.mainGroup = this._createBarGroup(itemAlign);

      var gradientBarGroup = new Group();
      mainGroup.add(gradientBarGroup);
      gradientBarGroup.add(shapes.outOfRange = createPolygon());
      gradientBarGroup.add(shapes.inRange = createPolygon(null, useHandle ? getCursor$1(this._orient) : null, bind(this._dragHandle, this, 'all', false), bind(this._dragHandle, this, 'all', true)));
      gradientBarGroup.setClipPath(new Rect({
        shape: {
          x: 0,
          y: 0,
          width: itemSize[0],
          height: itemSize[1],
          r: 3
        }
      }));
      var textRect = visualMapModel.textStyleModel.getTextRect('国');
      var textSize = mathMax$a(textRect.width, textRect.height);

      if (useHandle) {
        shapes.handleThumbs = [];
        shapes.handleLabels = [];
        shapes.handleLabelPoints = [];

        this._createHandle(visualMapModel, mainGroup, 0, itemSize, textSize, orient);

        this._createHandle(visualMapModel, mainGroup, 1, itemSize, textSize, orient);
      }

      this._createIndicator(visualMapModel, mainGroup, itemSize, textSize, orient);

      targetGroup.add(mainGroup);
    };

    ContinuousView.prototype._createHandle = function (visualMapModel, mainGroup, handleIndex, itemSize, textSize, orient) {
      var onDrift = bind(this._dragHandle, this, handleIndex, false);
      var onDragEnd = bind(this._dragHandle, this, handleIndex, true);
      var handleSize = parsePercent(visualMapModel.get('handleSize'), itemSize[0]);
      var handleThumb = createSymbol(visualMapModel.get('handleIcon'), -handleSize / 2, -handleSize / 2, handleSize, handleSize, null, true);
      var cursor = getCursor$1(this._orient);
      handleThumb.attr({
        cursor: cursor,
        draggable: true,
        drift: onDrift,
        ondragend: onDragEnd,
        onmousemove: function (e) {
          stop(e.event);
        }
      });
      handleThumb.x = itemSize[0] / 2;
      handleThumb.useStyle(visualMapModel.getModel('handleStyle').getItemStyle());
      handleThumb.setStyle({
        strokeNoScale: true,
        strokeFirst: true
      });
      handleThumb.style.lineWidth *= 2;
      handleThumb.ensureState('emphasis').style = visualMapModel.getModel(['emphasis', 'handleStyle']).getItemStyle();
      setAsHighDownDispatcher(handleThumb, true);
      mainGroup.add(handleThumb);
      var textStyleModel = this.visualMapModel.textStyleModel;
      var handleLabel = new ZRText({
        cursor: cursor,
        draggable: true,
        drift: onDrift,
        onmousemove: function (e) {
          stop(e.event);
        },
        ondragend: onDragEnd,
        style: {
          x: 0,
          y: 0,
          text: '',
          font: textStyleModel.getFont(),
          fill: textStyleModel.getTextColor()
        }
      });
      handleLabel.ensureState('blur').style = {
        opacity: 0.1
      };
      handleLabel.stateTransition = {
        duration: 200
      };
      this.group.add(handleLabel);
      var handleLabelPoint = [handleSize, 0];
      var shapes = this._shapes;
      shapes.handleThumbs[handleIndex] = handleThumb;
      shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
      shapes.handleLabels[handleIndex] = handleLabel;
    };

    ContinuousView.prototype._createIndicator = function (visualMapModel, mainGroup, itemSize, textSize, orient) {
      var scale = parsePercent(visualMapModel.get('indicatorSize'), itemSize[0]);
      var indicator = createSymbol(visualMapModel.get('indicatorIcon'), -scale / 2, -scale / 2, scale, scale, null, true);
      indicator.attr({
        cursor: 'move',
        invisible: true,
        silent: true,
        x: itemSize[0] / 2
      });
      var indicatorStyle = visualMapModel.getModel('indicatorStyle').getItemStyle();

      if (indicator instanceof ZRImage) {
        var pathStyle = indicator.style;
        indicator.useStyle(extend({
          image: pathStyle.image,
          x: pathStyle.x,
          y: pathStyle.y,
          width: pathStyle.width,
          height: pathStyle.height
        }, indicatorStyle));
      } else {
        indicator.useStyle(indicatorStyle);
      }

      mainGroup.add(indicator);
      var textStyleModel = this.visualMapModel.textStyleModel;
      var indicatorLabel = new ZRText({
        silent: true,
        invisible: true,
        style: {
          x: 0,
          y: 0,
          text: '',
          font: textStyleModel.getFont(),
          fill: textStyleModel.getTextColor()
        }
      });
      this.group.add(indicatorLabel);
      var indicatorLabelPoint = [(orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT) + itemSize[0] / 2, 0];
      var shapes = this._shapes;
      shapes.indicator = indicator;
      shapes.indicatorLabel = indicatorLabel;
      shapes.indicatorLabelPoint = indicatorLabelPoint;
      this._firstShowIndicator = true;
    };

    ContinuousView.prototype._dragHandle = function (handleIndex, isEnd, dx, dy) {
      if (!this._useHandle) {
        return;
      }

      this._dragging = !isEnd;

      if (!isEnd) {
        var vertex = this._applyTransform([dx, dy], this._shapes.mainGroup, true);

        this._updateInterval(handleIndex, vertex[1]);

        this._hideIndicator();

        this._updateView();
      }

      if (isEnd === !this.visualMapModel.get('realtime')) {
        this.api.dispatchAction({
          type: 'selectDataRange',
          from: this.uid,
          visualMapId: this.visualMapModel.id,
          selected: this._dataInterval.slice()
        });
      }

      if (isEnd) {
        !this._hovering && this._clearHoverLinkToSeries();
      } else if (useHoverLinkOnHandle(this.visualMapModel)) {
        this._doHoverLinkToSeries(this._handleEnds[handleIndex], false);
      }
    };

    ContinuousView.prototype._resetInterval = function () {
      var visualMapModel = this.visualMapModel;
      var dataInterval = this._dataInterval = visualMapModel.getSelected();
      var dataExtent = visualMapModel.getExtent();
      var sizeExtent = [0, visualMapModel.itemSize[1]];
      this._handleEnds = [linearMap$2(dataInterval[0], dataExtent, sizeExtent, true), linearMap$2(dataInterval[1], dataExtent, sizeExtent, true)];
    };

    ContinuousView.prototype._updateInterval = function (handleIndex, delta) {
      delta = delta || 0;
      var visualMapModel = this.visualMapModel;
      var handleEnds = this._handleEnds;
      var sizeExtent = [0, visualMapModel.itemSize[1]];
      sliderMove(delta, handleEnds, sizeExtent, handleIndex, 0);
      var dataExtent = visualMapModel.getExtent();
      this._dataInterval = [linearMap$2(handleEnds[0], sizeExtent, dataExtent, true), linearMap$2(handleEnds[1], sizeExtent, dataExtent, true)];
    };

    ContinuousView.prototype._updateView = function (forSketch) {
      var visualMapModel = this.visualMapModel;
      var dataExtent = visualMapModel.getExtent();
      var shapes = this._shapes;
      var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
      var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;

      var visualInRange = this._createBarVisual(this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange');

      var visualOutOfRange = this._createBarVisual(dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange');

      shapes.inRange.setStyle({
        fill: visualInRange.barColor
      }).setShape('points', visualInRange.barPoints);
      shapes.outOfRange.setStyle({
        fill: visualOutOfRange.barColor
      }).setShape('points', visualOutOfRange.barPoints);

      this._updateHandle(inRangeHandleEnds, visualInRange);
    };

    ContinuousView.prototype._createBarVisual = function (dataInterval, dataExtent, handleEnds, forceState) {
      var opts = {
        forceState: forceState,
        convertOpacityToAlpha: true
      };

      var colorStops = this._makeColorGradient(dataInterval, opts);

      var symbolSizes = [this.getControllerVisual(dataInterval[0], 'symbolSize', opts), this.getControllerVisual(dataInterval[1], 'symbolSize', opts)];

      var barPoints = this._createBarPoints(handleEnds, symbolSizes);

      return {
        barColor: new LinearGradient(0, 0, 0, 1, colorStops),
        barPoints: barPoints,
        handlesColor: [colorStops[0].color, colorStops[colorStops.length - 1].color]
      };
    };

    ContinuousView.prototype._makeColorGradient = function (dataInterval, opts) {
      var sampleNumber = 100;
      var colorStops = [];
      var step = (dataInterval[1] - dataInterval[0]) / sampleNumber;
      colorStops.push({
        color: this.getControllerVisual(dataInterval[0], 'color', opts),
        offset: 0
      });

      for (var i = 1; i < sampleNumber; i++) {
        var currValue = dataInterval[0] + step * i;

        if (currValue > dataInterval[1]) {
          break;
        }

        colorStops.push({
          color: this.getControllerVisual(currValue, 'color', opts),
          offset: i / sampleNumber
        });
      }

      colorStops.push({
        color: this.getControllerVisual(dataInterval[1], 'color', opts),
        offset: 1
      });
      return colorStops;
    };

    ContinuousView.prototype._createBarPoints = function (handleEnds, symbolSizes) {
      var itemSize = this.visualMapModel.itemSize;
      return [[itemSize[0] - symbolSizes[0], handleEnds[0]], [itemSize[0], handleEnds[0]], [itemSize[0], handleEnds[1]], [itemSize[0] - symbolSizes[1], handleEnds[1]]];
    };

    ContinuousView.prototype._createBarGroup = function (itemAlign) {
      var orient = this._orient;
      var inverse = this.visualMapModel.get('inverse');
      return new Group(orient === 'horizontal' && !inverse ? {
        scaleX: itemAlign === 'bottom' ? 1 : -1,
        rotation: Math.PI / 2
      } : orient === 'horizontal' && inverse ? {
        scaleX: itemAlign === 'bottom' ? -1 : 1,
        rotation: -Math.PI / 2
      } : orient === 'vertical' && !inverse ? {
        scaleX: itemAlign === 'left' ? 1 : -1,
        scaleY: -1
      } : {
        scaleX: itemAlign === 'left' ? 1 : -1
      });
    };

    ContinuousView.prototype._updateHandle = function (handleEnds, visualInRange) {
      if (!this._useHandle) {
        return;
      }

      var shapes = this._shapes;
      var visualMapModel = this.visualMapModel;
      var handleThumbs = shapes.handleThumbs;
      var handleLabels = shapes.handleLabels;
      var itemSize = visualMapModel.itemSize;
      var dataExtent = visualMapModel.getExtent();
      each$h([0, 1], function (handleIndex) {
        var handleThumb = handleThumbs[handleIndex];
        handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]);
        handleThumb.y = handleEnds[handleIndex];
        var val = linearMap$2(handleEnds[handleIndex], [0, itemSize[1]], dataExtent, true);
        var symbolSize = this.getControllerVisual(val, 'symbolSize');
        handleThumb.scaleX = handleThumb.scaleY = symbolSize / itemSize[0];
        handleThumb.x = itemSize[0] - symbolSize / 2;
        var textPoint = applyTransform$1(shapes.handleLabelPoints[handleIndex], getTransform(handleThumb, this.group));
        handleLabels[handleIndex].setStyle({
          x: textPoint[0],
          y: textPoint[1],
          text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
          verticalAlign: 'middle',
          align: this._orient === 'vertical' ? this._applyTransform('left', shapes.mainGroup) : 'center'
        });
      }, this);
    };

    ContinuousView.prototype._showIndicator = function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) {
      var visualMapModel = this.visualMapModel;
      var dataExtent = visualMapModel.getExtent();
      var itemSize = visualMapModel.itemSize;
      var sizeExtent = [0, itemSize[1]];
      var shapes = this._shapes;
      var indicator = shapes.indicator;

      if (!indicator) {
        return;
      }

      indicator.attr('invisible', false);
      var opts = {
        convertOpacityToAlpha: true
      };
      var color = this.getControllerVisual(cursorValue, 'color', opts);
      var symbolSize = this.getControllerVisual(cursorValue, 'symbolSize');
      var y = linearMap$2(cursorValue, dataExtent, sizeExtent, true);
      var x = itemSize[0] - symbolSize / 2;
      var oldIndicatorPos = {
        x: indicator.x,
        y: indicator.y
      };
      indicator.y = y;
      indicator.x = x;
      var textPoint = applyTransform$1(shapes.indicatorLabelPoint, getTransform(indicator, this.group));
      var indicatorLabel = shapes.indicatorLabel;
      indicatorLabel.attr('invisible', false);

      var align = this._applyTransform('left', shapes.mainGroup);

      var orient = this._orient;
      var isHorizontal = orient === 'horizontal';
      indicatorLabel.setStyle({
        text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
        verticalAlign: isHorizontal ? align : 'middle',
        align: isHorizontal ? 'center' : align
      });
      var indicatorNewProps = {
        x: x,
        y: y,
        style: {
          fill: color
        }
      };
      var labelNewProps = {
        style: {
          x: textPoint[0],
          y: textPoint[1]
        }
      };

      if (visualMapModel.ecModel.isAnimationEnabled() && !this._firstShowIndicator) {
        var animationCfg = {
          duration: 100,
          easing: 'cubicInOut',
          additive: true
        };
        indicator.x = oldIndicatorPos.x;
        indicator.y = oldIndicatorPos.y;
        indicator.animateTo(indicatorNewProps, animationCfg);
        indicatorLabel.animateTo(labelNewProps, animationCfg);
      } else {
        indicator.attr(indicatorNewProps);
        indicatorLabel.attr(labelNewProps);
      }

      this._firstShowIndicator = false;
      var handleLabels = this._shapes.handleLabels;

      if (handleLabels) {
        for (var i = 0; i < handleLabels.length; i++) {
          this._api.enterBlur(handleLabels[i]);
        }
      }
    };

    ContinuousView.prototype._enableHoverLinkToSeries = function () {
      var self = this;

      this._shapes.mainGroup.on('mousemove', function (e) {
        self._hovering = true;

        if (!self._dragging) {
          var itemSize = self.visualMapModel.itemSize;

          var pos = self._applyTransform([e.offsetX, e.offsetY], self._shapes.mainGroup, true, true);

          pos[1] = mathMin$a(mathMax$a(0, pos[1]), itemSize[1]);

          self._doHoverLinkToSeries(pos[1], 0 <= pos[0] && pos[0] <= itemSize[0]);
        }
      }).on('mouseout', function () {
        self._hovering = false;
        !self._dragging && self._clearHoverLinkToSeries();
      });
    };

    ContinuousView.prototype._enableHoverLinkFromSeries = function () {
      var zr = this.api.getZr();

      if (this.visualMapModel.option.hoverLink) {
        zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this);
        zr.on('mouseout', this._hideIndicator, this);
      } else {
        this._clearHoverLinkFromSeries();
      }
    };

    ContinuousView.prototype._doHoverLinkToSeries = function (cursorPos, hoverOnBar) {
      var visualMapModel = this.visualMapModel;
      var itemSize = visualMapModel.itemSize;

      if (!visualMapModel.option.hoverLink) {
        return;
      }

      var sizeExtent = [0, itemSize[1]];
      var dataExtent = visualMapModel.getExtent();
      cursorPos = mathMin$a(mathMax$a(sizeExtent[0], cursorPos), sizeExtent[1]);
      var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent);
      var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize];
      var cursorValue = linearMap$2(cursorPos, sizeExtent, dataExtent, true);
      var valueRange = [linearMap$2(hoverRange[0], sizeExtent, dataExtent, true), linearMap$2(hoverRange[1], sizeExtent, dataExtent, true)];
      hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity);
      hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity);

      if (hoverOnBar) {
        if (valueRange[0] === -Infinity) {
          this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize);
        } else if (valueRange[1] === Infinity) {
          this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize);
        } else {
          this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize);
        }
      }

      var oldBatch = this._hoverLinkDataIndices;
      var newBatch = [];

      if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
        newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
      }

      var resultBatches = compressBatches(oldBatch, newBatch);

      this._dispatchHighDown('downplay', makeHighDownBatch(resultBatches[0], visualMapModel));

      this._dispatchHighDown('highlight', makeHighDownBatch(resultBatches[1], visualMapModel));
    };

    ContinuousView.prototype._hoverLinkFromSeriesMouseOver = function (e) {
      var el = e.target;
      var visualMapModel = this.visualMapModel;

      if (!el || getECData(el).dataIndex == null) {
        return;
      }

      var ecData = getECData(el);
      var dataModel = this.ecModel.getSeriesByIndex(ecData.seriesIndex);

      if (!visualMapModel.isTargetSeries(dataModel)) {
        return;
      }

      var data = dataModel.getData(ecData.dataType);
      var value = data.get(visualMapModel.getDataDimension(data), ecData.dataIndex);

      if (!isNaN(value)) {
        this._showIndicator(value, value);
      }
    };

    ContinuousView.prototype._hideIndicator = function () {
      var shapes = this._shapes;
      shapes.indicator && shapes.indicator.attr('invisible', true);
      shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);
      var handleLabels = this._shapes.handleLabels;

      if (handleLabels) {
        for (var i = 0; i < handleLabels.length; i++) {
          this._api.leaveBlur(handleLabels[i]);
        }
      }
    };

    ContinuousView.prototype._clearHoverLinkToSeries = function () {
      this._hideIndicator();

      var indices = this._hoverLinkDataIndices;

      this._dispatchHighDown('downplay', makeHighDownBatch(indices, this.visualMapModel));

      indices.length = 0;
    };

    ContinuousView.prototype._clearHoverLinkFromSeries = function () {
      this._hideIndicator();

      var zr = this.api.getZr();
      zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
      zr.off('mouseout', this._hideIndicator);
    };

    ContinuousView.prototype._applyTransform = function (vertex, element, inverse, global) {
      var transform = getTransform(element, global ? null : this.group);
      return isArray(vertex) ? applyTransform$1(vertex, transform, inverse) : transformDirection(vertex, transform, inverse);
    };

    ContinuousView.prototype._dispatchHighDown = function (type, batch) {
      batch && batch.length && this.api.dispatchAction({
        type: type,
        batch: batch
      });
    };

    ContinuousView.prototype.dispose = function () {
      this._clearHoverLinkFromSeries();

      this._clearHoverLinkToSeries();
    };

    ContinuousView.prototype.remove = function () {
      this._clearHoverLinkFromSeries();

      this._clearHoverLinkToSeries();
    };

    ContinuousView.type = 'visualMap.continuous';
    return ContinuousView;
  }(VisualMapView);

  function createPolygon(points, cursor, onDrift, onDragEnd) {
    return new Polygon({
      shape: {
        points: points
      },
      draggable: !!onDrift,
      cursor: cursor,
      drift: onDrift,
      onmousemove: function (e) {
        stop(e.event);
      },
      ondragend: onDragEnd
    });
  }

  function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
    var halfHoverLinkSize = HOVER_LINK_SIZE / 2;
    var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');

    if (hoverLinkDataSize) {
      halfHoverLinkSize = linearMap$2(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2;
    }

    return halfHoverLinkSize;
  }

  function useHoverLinkOnHandle(visualMapModel) {
    var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle');
    return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle);
  }

  function getCursor$1(orient) {
    return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
  }

  ComponentView.registerClass(ContinuousView);
  var actionInfo$2 = {
    type: 'selectDataRange',
    event: 'dataRangeSelected',
    update: 'update'
  };
  registerAction(actionInfo$2, function (payload, ecModel) {
    ecModel.eachComponent({
      mainType: 'visualMap',
      query: payload
    }, function (model) {
      model.setSelected(payload.selected);
    });
  });
  registerPreprocessor(visualMapPreprocessor);

  var PiecewiseModel = function (_super) {
    __extends(PiecewiseModel, _super);

    function PiecewiseModel() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = PiecewiseModel.type;
      _this._pieceList = [];
      return _this;
    }

    PiecewiseModel.prototype.optionUpdated = function (newOption, isInit) {
      _super.prototype.optionUpdated.apply(this, arguments);

      this.resetExtent();

      var mode = this._mode = this._determineMode();

      this._pieceList = [];

      resetMethods[this._mode].call(this, this._pieceList);

      this._resetSelected(newOption, isInit);

      var categories = this.option.categories;
      this.resetVisual(function (mappingOption, state) {
        if (mode === 'categories') {
          mappingOption.mappingMethod = 'category';
          mappingOption.categories = clone(categories);
        } else {
          mappingOption.dataExtent = this.getExtent();
          mappingOption.mappingMethod = 'piecewise';
          mappingOption.pieceList = map(this._pieceList, function (piece) {
            piece = clone(piece);

            if (state !== 'inRange') {
              piece.visual = null;
            }

            return piece;
          });
        }
      });
    };

    PiecewiseModel.prototype.completeVisualOption = function () {
      var option = this.option;
      var visualTypesInPieces = {};
      var visualTypes = VisualMapping.listVisualTypes();
      var isCategory = this.isCategory();
      each(option.pieces, function (piece) {
        each(visualTypes, function (visualType) {
          if (piece.hasOwnProperty(visualType)) {
            visualTypesInPieces[visualType] = 1;
          }
        });
      });
      each(visualTypesInPieces, function (v, visualType) {
        var exists = false;
        each(this.stateList, function (state) {
          exists = exists || has(option, state, visualType) || has(option.target, state, visualType);
        }, this);
        !exists && each(this.stateList, function (state) {
          (option[state] || (option[state] = {}))[visualType] = visualDefault.get(visualType, state === 'inRange' ? 'active' : 'inactive', isCategory);
        });
      }, this);

      function has(obj, state, visualType) {
        return obj && obj[state] && obj[state].hasOwnProperty(visualType);
      }

      _super.prototype.completeVisualOption.apply(this, arguments);
    };

    PiecewiseModel.prototype._resetSelected = function (newOption, isInit) {
      var thisOption = this.option;
      var pieceList = this._pieceList;
      var selected = (isInit ? thisOption : newOption).selected || {};
      thisOption.selected = selected;
      each(pieceList, function (piece, index) {
        var key = this.getSelectedMapKey(piece);

        if (!selected.hasOwnProperty(key)) {
          selected[key] = true;
        }
      }, this);

      if (thisOption.selectedMode === 'single') {
        var hasSel_1 = false;
        each(pieceList, function (piece, index) {
          var key = this.getSelectedMapKey(piece);

          if (selected[key]) {
            hasSel_1 ? selected[key] = false : hasSel_1 = true;
          }
        }, this);
      }
    };

    PiecewiseModel.prototype.getSelectedMapKey = function (piece) {
      return this._mode === 'categories' ? piece.value + '' : piece.index + '';
    };

    PiecewiseModel.prototype.getPieceList = function () {
      return this._pieceList;
    };

    PiecewiseModel.prototype._determineMode = function () {
      var option = this.option;
      return option.pieces && option.pieces.length > 0 ? 'pieces' : this.option.categories ? 'categories' : 'splitNumber';
    };

    PiecewiseModel.prototype.setSelected = function (selected) {
      this.option.selected = clone(selected);
    };

    PiecewiseModel.prototype.getValueState = function (value) {
      var index = VisualMapping.findPieceIndex(value, this._pieceList);
      return index != null ? this.option.selected[this.getSelectedMapKey(this._pieceList[index])] ? 'inRange' : 'outOfRange' : 'outOfRange';
    };

    PiecewiseModel.prototype.findTargetDataIndices = function (pieceIndex) {
      var result = [];
      var pieceList = this._pieceList;
      this.eachTargetSeries(function (seriesModel) {
        var dataIndices = [];
        var data = seriesModel.getData();
        data.each(this.getDataDimension(data), function (value, dataIndex) {
          var pIdx = VisualMapping.findPieceIndex(value, pieceList);
          pIdx === pieceIndex && dataIndices.push(dataIndex);
        }, this);
        result.push({
          seriesId: seriesModel.id,
          dataIndex: dataIndices
        });
      }, this);
      return result;
    };

    PiecewiseModel.prototype.getRepresentValue = function (piece) {
      var representValue;

      if (this.isCategory()) {
        representValue = piece.value;
      } else {
        if (piece.value != null) {
          representValue = piece.value;
        } else {
          var pieceInterval = piece.interval || [];
          representValue = pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity ? 0 : (pieceInterval[0] + pieceInterval[1]) / 2;
        }
      }

      return representValue;
    };

    PiecewiseModel.prototype.getVisualMeta = function (getColorVisual) {
      if (this.isCategory()) {
        return;
      }

      var stops = [];
      var outerColors = ['', ''];
      var visualMapModel = this;

      function setStop(interval, valueState) {
        var representValue = visualMapModel.getRepresentValue({
          interval: interval
        });

        if (!valueState) {
          valueState = visualMapModel.getValueState(representValue);
        }

        var color = getColorVisual(representValue, valueState);

        if (interval[0] === -Infinity) {
          outerColors[0] = color;
        } else if (interval[1] === Infinity) {
          outerColors[1] = color;
        } else {
          stops.push({
            value: interval[0],
            color: color
          }, {
            value: interval[1],
            color: color
          });
        }
      }

      var pieceList = this._pieceList.slice();

      if (!pieceList.length) {
        pieceList.push({
          interval: [-Infinity, Infinity]
        });
      } else {
        var edge = pieceList[0].interval[0];
        edge !== -Infinity && pieceList.unshift({
          interval: [-Infinity, edge]
        });
        edge = pieceList[pieceList.length - 1].interval[1];
        edge !== Infinity && pieceList.push({
          interval: [edge, Infinity]
        });
      }

      var curr = -Infinity;
      each(pieceList, function (piece) {
        var interval = piece.interval;

        if (interval) {
          interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
          setStop(interval.slice());
          curr = interval[1];
        }
      }, this);
      return {
        stops: stops,
        outerColors: outerColors
      };
    };

    PiecewiseModel.type = 'visualMap.piecewise';
    PiecewiseModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, {
      selected: null,
      minOpen: false,
      maxOpen: false,
      align: 'auto',
      itemWidth: 20,
      itemHeight: 14,
      itemSymbol: 'roundRect',
      pieces: null,
      categories: null,
      splitNumber: 5,
      selectedMode: 'multiple',
      itemGap: 10,
      hoverLink: true
    });
    return PiecewiseModel;
  }(VisualMapModel);

  var resetMethods = {
    splitNumber: function (outPieceList) {
      var thisOption = this.option;
      var precision = Math.min(thisOption.precision, 20);
      var dataExtent = this.getExtent();
      var splitNumber = thisOption.splitNumber;
      splitNumber = Math.max(parseInt(splitNumber, 10), 1);
      thisOption.splitNumber = splitNumber;
      var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber;

      while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
        precision++;
      }

      thisOption.precision = precision;
      splitStep = +splitStep.toFixed(precision);

      if (thisOption.minOpen) {
        outPieceList.push({
          interval: [-Infinity, dataExtent[0]],
          close: [0, 0]
        });
      }

      for (var index = 0, curr = dataExtent[0]; index < splitNumber; curr += splitStep, index++) {
        var max = index === splitNumber - 1 ? dataExtent[1] : curr + splitStep;
        outPieceList.push({
          interval: [curr, max],
          close: [1, 1]
        });
      }

      if (thisOption.maxOpen) {
        outPieceList.push({
          interval: [dataExtent[1], Infinity],
          close: [0, 0]
        });
      }

      reformIntervals(outPieceList);
      each(outPieceList, function (piece, index) {
        piece.index = index;
        piece.text = this.formatValueText(piece.interval);
      }, this);
    },
    categories: function (outPieceList) {
      var thisOption = this.option;
      each(thisOption.categories, function (cate) {
        outPieceList.push({
          text: this.formatValueText(cate, true),
          value: cate
        });
      }, this);
      normalizeReverse(thisOption, outPieceList);
    },
    pieces: function (outPieceList) {
      var thisOption = this.option;
      each(thisOption.pieces, function (pieceListItem, index) {
        if (!isObject(pieceListItem)) {
          pieceListItem = {
            value: pieceListItem
          };
        }

        var item = {
          text: '',
          index: index
        };

        if (pieceListItem.label != null) {
          item.text = pieceListItem.label;
        }

        if (pieceListItem.hasOwnProperty('value')) {
          var value = item.value = pieceListItem.value;
          item.interval = [value, value];
          item.close = [1, 1];
        } else {
          var interval = item.interval = [];
          var close_1 = item.close = [0, 0];
          var closeList = [1, 0, 1];
          var infinityList = [-Infinity, Infinity];
          var useMinMax = [];

          for (var lg = 0; lg < 2; lg++) {
            var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg];

            for (var i = 0; i < 3 && interval[lg] == null; i++) {
              interval[lg] = pieceListItem[names[i]];
              close_1[lg] = closeList[i];
              useMinMax[lg] = i === 2;
            }

            interval[lg] == null && (interval[lg] = infinityList[lg]);
          }

          useMinMax[0] && interval[1] === Infinity && (close_1[0] = 0);
          useMinMax[1] && interval[0] === -Infinity && (close_1[1] = 0);

          if (true) {
            if (interval[0] > interval[1]) {
              console.warn('Piece ' + index + 'is illegal: ' + interval + ' lower bound should not greater then uppper bound.');
            }
          }

          if (interval[0] === interval[1] && close_1[0] && close_1[1]) {
            item.value = interval[0];
          }
        }

        item.visual = VisualMapping.retrieveVisuals(pieceListItem);
        outPieceList.push(item);
      }, this);
      normalizeReverse(thisOption, outPieceList);
      reformIntervals(outPieceList);
      each(outPieceList, function (piece) {
        var close = piece.close;
        var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
        piece.text = piece.text || this.formatValueText(piece.value != null ? piece.value : piece.interval, false, edgeSymbols);
      }, this);
    }
  };

  function normalizeReverse(thisOption, pieceList) {
    var inverse = thisOption.inverse;

    if (thisOption.orient === 'vertical' ? !inverse : inverse) {
      pieceList.reverse();
    }
  }

  ComponentModel.registerClass(PiecewiseModel);

  var PiecewiseVisualMapView = function (_super) {
    __extends(PiecewiseVisualMapView, _super);

    function PiecewiseVisualMapView() {
      var _this = _super !== null && _super.apply(this, arguments) || this;

      _this.type = PiecewiseVisualMapView.type;
      return _this;
    }

    PiecewiseVisualMapView.prototype.doRender = function () {
      var thisGroup = this.group;
      thisGroup.removeAll();
      var visualMapModel = this.visualMapModel;
      var textGap = visualMapModel.get('textGap');
      var textStyleModel = visualMapModel.textStyleModel;
      var textFont = textStyleModel.getFont();
      var textFill = textStyleModel.getTextColor();

      var itemAlign = this._getItemAlign();

      var itemSize = visualMapModel.itemSize;

      var viewData = this._getViewData();

      var endsText = viewData.endsText;
      var showLabel = retrieve(visualMapModel.get('showLabel', true), !endsText);
      endsText && this._renderEndsText(thisGroup, endsText[0], itemSize, showLabel, itemAlign);
      each(viewData.viewPieceList, function (item) {
        var piece = item.piece;
        var itemGroup = new Group();
        itemGroup.onclick = bind(this._onItemClick, this, piece);

        this._enableHoverLink(itemGroup, item.indexInModelPieceList);

        var representValue = visualMapModel.getRepresentValue(piece);

        this._createItemSymbol(itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]);

        if (showLabel) {
          var visualState = this.visualMapModel.getValueState(representValue);
          itemGroup.add(new ZRText({
            style: {
              x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap,
              y: itemSize[1] / 2,
              text: piece.text,
              verticalAlign: 'middle',
              align: itemAlign,
              font: textFont,
              fill: textFill,
              opacity: visualState === 'outOfRange' ? 0.5 : 1
            }
          }));
        }

        thisGroup.add(itemGroup);
      }, this);
      endsText && this._renderEndsText(thisGroup, endsText[1], itemSize, showLabel, itemAlign);
      box(visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap'));
      this.renderBackground(thisGroup);
      this.positionGroup(thisGroup);
    };

    PiecewiseVisualMapView.prototype._enableHoverLink = function (itemGroup, pieceIndex) {
      var _this = this;

      itemGroup.on('mouseover', function () {
        return onHoverLink('highlight');
      }).on('mouseout', function () {
        return onHoverLink('downplay');
      });

      var onHoverLink = function (method) {
        var visualMapModel = _this.visualMapModel;
        visualMapModel.option.hoverLink && _this.api.dispatchAction({
          type: method,
          batch: makeHighDownBatch(visualMapModel.findTargetDataIndices(pieceIndex), visualMapModel)
        });
      };
    };

    PiecewiseVisualMapView.prototype._getItemAlign = function () {
      var visualMapModel = this.visualMapModel;
      var modelOption = visualMapModel.option;

      if (modelOption.orient === 'vertical') {
        return getItemAlign(visualMapModel, this.api, visualMapModel.itemSize);
      } else {
        var align = modelOption.align;

        if (!align || align === 'auto') {
          align = 'left';
        }

        return align;
      }
    };

    PiecewiseVisualMapView.prototype._renderEndsText = function (group, text, itemSize, showLabel, itemAlign) {
      if (!text) {
        return;
      }

      var itemGroup = new Group();
      var textStyleModel = this.visualMapModel.textStyleModel;
      itemGroup.add(new ZRText({
        style: {
          x: showLabel ? itemAlign === 'right' ? itemSize[0] : 0 : itemSize[0] / 2,
          y: itemSize[1] / 2,
          verticalAlign: 'middle',
          align: showLabel ? itemAlign : 'center',
          text: text,
          font: textStyleModel.getFont(),
          fill: textStyleModel.getTextColor()
        }
      }));
      group.add(itemGroup);
    };

    PiecewiseVisualMapView.prototype._getViewData = function () {
      var visualMapModel = this.visualMapModel;
      var viewPieceList = map(visualMapModel.getPieceList(), function (piece, index) {
        return {
          piece: piece,
          indexInModelPieceList: index
        };
      });
      var endsText = visualMapModel.get('text');
      var orient = visualMapModel.get('orient');
      var inverse = visualMapModel.get('inverse');

      if (orient === 'horizontal' ? inverse : !inverse) {
        viewPieceList.reverse();
      } else if (endsText) {
        endsText = endsText.slice().reverse();
      }

      return {
        viewPieceList: viewPieceList,
        endsText: endsText
      };
    };

    PiecewiseVisualMapView.prototype._createItemSymbol = function (group, representValue, shapeParam) {
      group.add(createSymbol(this.getControllerVisual(representValue, 'symbol'), shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3], this.getControllerVisual(representValue, 'color')));
    };

    PiecewiseVisualMapView.prototype._onItemClick = function (piece) {
      var visualMapModel = this.visualMapModel;
      var option = visualMapModel.option;
      var selected = clone(option.selected);
      var newKey = visualMapModel.getSelectedMapKey(piece);

      if (option.selectedMode === 'single') {
        selected[newKey] = true;
        each(selected, function (o, key) {
          selected[key] = key === newKey;
        });
      } else {
        selected[newKey] = !selected[newKey];
      }

      this.api.dispatchAction({
        type: 'selectDataRange',
        from: this.uid,
        visualMapId: this.visualMapModel.id,
        selected: selected
      });
    };

    PiecewiseVisualMapView.type = 'visualMap.piecewise';
    return PiecewiseVisualMapView;
  }(VisualMapView);

  ComponentView.registerClass(PiecewiseVisualMapView);
  registerPreprocessor(visualMapPreprocessor);
  var DEFAULT_OPTION = {
    label: {
      enabled: true
    },
    decal: {
      show: false
    }
  };
  var inner$n = makeInner();
  var decalPaletteScope = {};

  function ariaVisual(ecModel, api) {
    var ariaModel = ecModel.getModel('aria');

    if (!ariaModel.get('enabled')) {
      return;
    }

    var defaultOption = clone(DEFAULT_OPTION);
    merge(defaultOption.label, ecModel.getLocaleModel().get('aria'), false);
    merge(ariaModel.option, defaultOption, false);
    setDecal();
    setLabel();

    function setDecal() {
      var decalModel = ariaModel.getModel('decal');
      var useDecal = decalModel.get('show');

      if (useDecal) {
        var paletteScopeGroupByType_1 = createHashMap();
        ecModel.eachSeries(function (seriesModel) {
          if (!seriesModel.useColorPaletteOnData) {
            return;
          }

          var decalScope = paletteScopeGroupByType_1.get(seriesModel.type);

          if (!decalScope) {
            decalScope = {};
            paletteScopeGroupByType_1.set(seriesModel.type, decalScope);
          }

          inner$n(seriesModel).scope = decalScope;
        });
        ecModel.eachRawSeries(function (seriesModel) {
          if (ecModel.isSeriesFiltered(seriesModel)) {
            return;
          }

          if (typeof seriesModel.enableAriaDecal === 'function') {
            seriesModel.enableAriaDecal();
            return;
          }

          var data = seriesModel.getData();

          if (seriesModel.useColorPaletteOnData) {
            var dataAll_1 = seriesModel.getRawData();
            var idxMap_1 = {};
            var decalScope_1 = inner$n(seriesModel).scope;
            data.each(function (idx) {
              var rawIdx = data.getRawIndex(idx);
              idxMap_1[rawIdx] = idx;
            });
            var dataCount_1 = dataAll_1.count();
            dataAll_1.each(function (rawIdx) {
              var idx = idxMap_1[rawIdx];
              var name = dataAll_1.getName(rawIdx) || rawIdx + '';
              var paletteDecal = getDecalFromPalette(seriesModel.ecModel, name, decalScope_1, dataCount_1);
              var specifiedDecal = data.getItemVisual(idx, 'decal');
              data.setItemVisual(idx, 'decal', mergeDecal(specifiedDecal, paletteDecal));
            });
          } else {
            var paletteDecal = getDecalFromPalette(seriesModel.ecModel, seriesModel.name, decalPaletteScope, ecModel.getSeriesCount());
            var specifiedDecal = data.getVisual('decal');
            data.setVisual('decal', mergeDecal(specifiedDecal, paletteDecal));
          }

          function mergeDecal(specifiedDecal, paletteDecal) {
            var resultDecal = specifiedDecal ? extend(extend({}, paletteDecal), specifiedDecal) : paletteDecal;
            resultDecal.dirty = true;
            return resultDecal;
          }
        });
      }
    }

    function setLabel() {
      var labelLocale = ecModel.getLocaleModel().get('aria');
      var labelModel = ariaModel.getModel('label');
      labelModel.option = defaults(labelModel.option, labelLocale);

      if (!labelModel.get('enabled')) {
        return;
      }

      var dom = api.getZr().dom;

      if (labelModel.get('description')) {
        dom.setAttribute('aria-label', labelModel.get('description'));
        return;
      }

      var seriesCnt = ecModel.getSeriesCount();
      var maxDataCnt = labelModel.get(['data', 'maxCount']) || 10;
      var maxSeriesCnt = labelModel.get(['series', 'maxCount']) || 10;
      var displaySeriesCnt = Math.min(seriesCnt, maxSeriesCnt);
      var ariaLabel;

      if (seriesCnt < 1) {
        return;
      } else {
        var title = getTitle();

        if (title) {
          var withTitle = labelModel.get(['general', 'withTitle']);
          ariaLabel = replace(withTitle, {
            title: title
          });
        } else {
          ariaLabel = labelModel.get(['general', 'withoutTitle']);
        }

        var seriesLabels_1 = [];
        var prefix = seriesCnt > 1 ? labelModel.get(['series', 'multiple', 'prefix']) : labelModel.get(['series', 'single', 'prefix']);
        ariaLabel += replace(prefix, {
          seriesCount: seriesCnt
        });
        ecModel.eachSeries(function (seriesModel, idx) {
          if (idx < displaySeriesCnt) {
            var seriesLabel = void 0;
            var seriesName = seriesModel.get('name');
            var withName = seriesName ? 'withName' : 'withoutName';
            seriesLabel = seriesCnt > 1 ? labelModel.get(['series', 'multiple', withName]) : labelModel.get(['series', 'single', withName]);
            seriesLabel = replace(seriesLabel, {
              seriesId: seriesModel.seriesIndex,
              seriesName: seriesModel.get('name'),
              seriesType: getSeriesTypeName(seriesModel.subType)
            });
            var data = seriesModel.getData();

            if (data.count() > maxDataCnt) {
              var partialLabel = labelModel.get(['data', 'partialData']);
              seriesLabel += replace(partialLabel, {
                displayCnt: maxDataCnt
              });
            } else {
              seriesLabel += labelModel.get(['data', 'allData']);
            }

            var dataLabels = [];

            for (var i = 0; i < data.count(); i++) {
              if (i < maxDataCnt) {
                var name_1 = data.getName(i);
                var value = retrieveRawValue(data, i);
                var dataLabel = labelModel.get(['data', name_1 ? 'withName' : 'withoutName']);
                dataLabels.push(replace(dataLabel, {
                  name: name_1,
                  value: value
                }));
              }
            }

            var middleSeparator_1 = labelModel.get(['data', 'separator', 'middle']);
            var endSeparator_1 = labelModel.get(['data', 'separator', 'end']);
            seriesLabel += dataLabels.join(middleSeparator_1) + endSeparator_1;
            seriesLabels_1.push(seriesLabel);
          }
        });
        var separatorModel = labelModel.getModel(['series', 'multiple', 'separator']);
        var middleSeparator = separatorModel.get('middle');
        var endSeparator = separatorModel.get('end');
        ariaLabel += seriesLabels_1.join(middleSeparator) + endSeparator;
        dom.setAttribute('aria-label', ariaLabel);
      }
    }

    function replace(str, keyValues) {
      if (typeof str !== 'string') {
        return str;
      }

      var result = str;
      each(keyValues, function (value, key) {
        result = result.replace(new RegExp('\\{\\s*' + key + '\\s*\\}', 'g'), value);
      });
      return result;
    }

    function getTitle() {
      var title = ecModel.get('title');

      if (title && title.length) {
        title = title[0];
      }

      return title && title.text;
    }

    function getSeriesTypeName(type) {
      return ecModel.getLocaleModel().get(['series', 'typeNames'])[type] || '自定义图';
    }
  }

  function ariaPreprocessor(option) {
    if (!option || !option.aria) {
      return;
    }

    var aria = option.aria;

    if (aria.show != null) {
      aria.enabled = aria.show;
    }

    aria.label = aria.label || {};
    each(['description', 'general', 'series', 'data'], function (name) {
      if (aria[name] != null) {
        aria.label[name] = aria[name];
      }
    });
  }

  var PRIORITY_VISUAL_ARIA$1 = PRIORITY.VISUAL.ARIA;
  registerPreprocessor(ariaPreprocessor);
  registerVisual(PRIORITY_VISUAL_ARIA$1, ariaVisual);

  function createElement(name) {
    return document.createElementNS('http://www.w3.org/2000/svg', name);
  }

  var NONE = 'none';
  var mathRound = Math.round;
  var mathSin$4 = Math.sin;
  var mathCos$4 = Math.cos;
  var PI$a = Math.PI;
  var PI2$a = Math.PI * 2;
  var degree = 180 / PI$a;
  var EPSILON$4 = 1e-4;

  function round3(val) {
    return mathRound(val * 1e3) / 1e3;
  }

  function round4(val) {
    return mathRound(val * 1e4) / 1e4;
  }

  function isAroundZero$1(val) {
    return val < EPSILON$4 && val > -EPSILON$4;
  }

  function pathHasFill(style) {
    var fill = style.fill;
    return fill != null && fill !== NONE;
  }

  function pathHasStroke(style) {
    var stroke = style.stroke;
    return stroke != null && stroke !== NONE;
  }

  function setTransform(svgEl, m) {
    if (m) {
      attr(svgEl, 'transform', 'matrix(' + round3(m[0]) + ',' + round3(m[1]) + ',' + round3(m[2]) + ',' + round3(m[3]) + ',' + round4(m[4]) + ',' + round4(m[5]) + ')');
    }
  }

  function attr(el, key, val) {
    if (!val || val.type !== 'linear' && val.type !== 'radial') {
      el.setAttribute(key, val);
    }
  }

  function attrXLink(el, key, val) {
    el.setAttributeNS('http://www.w3.org/1999/xlink', key, val);
  }

  function attrXML(el, key, val) {
    el.setAttributeNS('http://www.w3.org/XML/1998/namespace', key, val);
  }

  function bindStyle(svgEl, style, el) {
    var opacity = style.opacity == null ? 1 : style.opacity;

    if (pathHasFill(style)) {
      var fill = style.fill;
      fill = fill === 'transparent' ? NONE : fill;
      attr(svgEl, 'fill', fill);
      attr(svgEl, 'fill-opacity', (style.fillOpacity != null ? style.fillOpacity * opacity : opacity) + '');
    } else {
      attr(svgEl, 'fill', NONE);
    }

    if (pathHasStroke(style)) {
      var stroke = style.stroke;
      stroke = stroke === 'transparent' ? NONE : stroke;
      attr(svgEl, 'stroke', stroke);
      var strokeWidth = style.lineWidth;
      var strokeScale_1 = style.strokeNoScale ? el.getLineScale() : 1;
      attr(svgEl, 'stroke-width', (strokeScale_1 ? strokeWidth / strokeScale_1 : 0) + '');
      attr(svgEl, 'paint-order', style.strokeFirst ? 'stroke' : 'fill');
      attr(svgEl, 'stroke-opacity', (style.strokeOpacity != null ? style.strokeOpacity * opacity : opacity) + '');
      var lineDash = style.lineDash && strokeWidth > 0 && normalizeLineDash(style.lineDash, strokeWidth);

      if (lineDash) {
        var lineDashOffset = style.lineDashOffset;

        if (strokeScale_1 && strokeScale_1 !== 1) {
          lineDash = map(lineDash, function (rawVal) {
            return rawVal / strokeScale_1;
          });

          if (lineDashOffset) {
            lineDashOffset /= strokeScale_1;
            lineDashOffset = mathRound(lineDashOffset);
          }
        }

        attr(svgEl, 'stroke-dasharray', lineDash.join(','));
        attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + '');
      } else {
        attr(svgEl, 'stroke-dasharray', '');
      }

      style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap);
      style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin);
      style.miterLimit && attr(svgEl, 'stroke-miterlimit', style.miterLimit + '');
    } else {
      attr(svgEl, 'stroke', NONE);
    }
  }

  var SVGPathRebuilder = function () {
    function SVGPathRebuilder() {}

    SVGPathRebuilder.prototype.reset = function () {
      this._d = [];
      this._str = '';
    };

    SVGPathRebuilder.prototype.moveTo = function (x, y) {
      this._add('M', x, y);
    };

    SVGPathRebuilder.prototype.lineTo = function (x, y) {
      this._add('L', x, y);
    };

    SVGPathRebuilder.prototype.bezierCurveTo = function (x, y, x2, y2, x3, y3) {
      this._add('C', x, y, x2, y2, x3, y3);
    };

    SVGPathRebuilder.prototype.quadraticCurveTo = function (x, y, x2, y2) {
      this._add('Q', x, y, x2, y2);
    };

    SVGPathRebuilder.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) {
      this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise);
    };

    SVGPathRebuilder.prototype.ellipse = function (cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise) {
      var firstCmd = this._d.length === 0;
      var dTheta = endAngle - startAngle;
      var clockwise = !anticlockwise;
      var dThetaPositive = Math.abs(dTheta);
      var isCircle = isAroundZero$1(dThetaPositive - PI2$a) || (clockwise ? dTheta >= PI2$a : -dTheta >= PI2$a);
      var unifiedTheta = dTheta > 0 ? dTheta % PI2$a : dTheta % PI2$a + PI2$a;
      var large = false;

      if (isCircle) {
        large = true;
      } else if (isAroundZero$1(dThetaPositive)) {
        large = false;
      } else {
        large = unifiedTheta >= PI$a === !!clockwise;
      }

      var x0 = round4(cx + rx * mathCos$4(startAngle));
      var y0 = round4(cy + ry * mathSin$4(startAngle));

      if (isCircle) {
        if (clockwise) {
          dTheta = PI2$a - 1e-4;
        } else {
          dTheta = -PI2$a + 1e-4;
        }

        large = true;

        if (firstCmd) {
          this._d.push('M', x0, y0);
        }
      }

      var x = round4(cx + rx * mathCos$4(startAngle + dTheta));
      var y = round4(cy + ry * mathSin$4(startAngle + dTheta));

      if (isNaN(x0) || isNaN(y0) || isNaN(rx) || isNaN(ry) || isNaN(psi) || isNaN(degree) || isNaN(x) || isNaN(y)) {
        return '';
      }

      this._d.push('A', round4(rx), round4(ry), mathRound(psi * degree), +large, +clockwise, x, y);
    };

    SVGPathRebuilder.prototype.rect = function (x, y, w, h) {
      this._add('M', x, y);

      this._add('L', x + w, y);

      this._add('L', x + w, y + h);

      this._add('L', x, y + h);

      this._add('L', x, y);
    };

    SVGPathRebuilder.prototype.closePath = function () {
      if (this._d.length > 0) {
        this._add('Z');
      }
    };

    SVGPathRebuilder.prototype._add = function (cmd, a, b, c, d, e, f, g, h) {
      this._d.push(cmd);

      for (var i = 1; i < arguments.length; i++) {
        var val = arguments[i];

        if (isNaN(val)) {
          this._invalid = true;
          return;
        }

        this._d.push(round4(val));
      }
    };

    SVGPathRebuilder.prototype.generateStr = function () {
      this._str = this._invalid ? '' : this._d.join(' ');
      this._d = [];
    };

    SVGPathRebuilder.prototype.getStr = function () {
      return this._str;
    };

    return SVGPathRebuilder;
  }();

  var svgPath = {
    brush: function (el) {
      var style = el.style;
      var svgEl = el.__svgEl;

      if (!svgEl) {
        svgEl = createElement('path');
        el.__svgEl = svgEl;
      }

      if (!el.path) {
        el.createPathProxy();
      }

      var path = el.path;

      if (el.shapeChanged()) {
        path.beginPath();
        el.buildPath(path, el.shape);
        el.pathUpdated();
      }

      var pathVersion = path.getVersion();
      var elExt = el;
      var svgPathBuilder = elExt.__svgPathBuilder;

      if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || el.style.strokePercent < 1) {
        if (!svgPathBuilder) {
          svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder();
        }

        svgPathBuilder.reset();
        path.rebuildPath(svgPathBuilder, el.style.strokePercent);
        svgPathBuilder.generateStr();
        elExt.__svgPathVersion = pathVersion;
      }

      attr(svgEl, 'd', svgPathBuilder.getStr());
      bindStyle(svgEl, style, el);
      setTransform(svgEl, el.transform);
    }
  };
  var svgImage = {
    brush: function (el) {
      var style = el.style;
      var image = style.image;

      if (image instanceof HTMLImageElement) {
        var src = image.src;
        image = src;
      }

      if (!image) {
        return;
      }

      var x = style.x || 0;
      var y = style.y || 0;
      var dw = style.width;
      var dh = style.height;
      var svgEl = el.__svgEl;

      if (!svgEl) {
        svgEl = createElement('image');
        el.__svgEl = svgEl;
      }

      if (image !== el.__imageSrc) {
        attrXLink(svgEl, 'href', image);
        el.__imageSrc = image;
      }

      attr(svgEl, 'width', dw + '');
      attr(svgEl, 'height', dh + '');
      attr(svgEl, 'x', x + '');
      attr(svgEl, 'y', y + '');
      setTransform(svgEl, el.transform);
    }
  };
  var TEXT_ALIGN_TO_ANCHOR = {
    left: 'start',
    right: 'end',
    center: 'middle',
    middle: 'middle'
  };

  function adjustTextY$1(y, lineHeight, textBaseline) {
    if (textBaseline === 'top') {
      y += lineHeight / 2;
    } else if (textBaseline === 'bottom') {
      y -= lineHeight / 2;
    }

    return y;
  }

  var svgText = {
    brush: function (el) {
      var style = el.style;
      var text = style.text;
      text != null && (text += '');

      if (!text || isNaN(style.x) || isNaN(style.y)) {
        return;
      }

      var textSvgEl = el.__svgEl;

      if (!textSvgEl) {
        textSvgEl = createElement('text');
        attrXML(textSvgEl, 'xml:space', 'preserve');
        el.__svgEl = textSvgEl;
      }

      var font = style.font || DEFAULT_FONT;
      var textSvgElStyle = textSvgEl.style;
      textSvgElStyle.font = font;
      textSvgEl.textContent = text;
      bindStyle(textSvgEl, style, el);
      setTransform(textSvgEl, el.transform);
      var x = style.x || 0;
      var y = adjustTextY$1(style.y || 0, getLineHeight(font), style.textBaseline);
      var textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign] || style.textAlign;
      attr(textSvgEl, 'dominant-baseline', 'central');
      attr(textSvgEl, 'text-anchor', textAlign);
      attr(textSvgEl, 'x', x + '');
      attr(textSvgEl, 'y', y + '');
    }
  };

  function diff(oldArr, newArr, equals) {
    if (!equals) {
      equals = function (a, b) {
        return a === b;
      };
    }

    oldArr = oldArr.slice();
    newArr = newArr.slice();
    var newLen = newArr.length;
    var oldLen = oldArr.length;
    var editLength = 1;
    var maxEditLength = newLen + oldLen;
    var bestPath = [{
      newPos: -1,
      components: []
    }];
    var oldPos = extractCommon(bestPath[0], newArr, oldArr, 0, equals);

    if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
      var indices = [];

      for (var i = 0; i < newArr.length; i++) {
        indices.push(i);
      }

      return [{
        indices: indices,
        count: newArr.length,
        added: false,
        removed: false
      }];
    }

    function execEditLength() {
      for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
        var basePath;
        var addPath = bestPath[diagonalPath - 1];
        var removePath = bestPath[diagonalPath + 1];
        var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;

        if (addPath) {
          bestPath[diagonalPath - 1] = undefined;
        }

        var canAdd = addPath && addPath.newPos + 1 < newLen;
        var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;

        if (!canAdd && !canRemove) {
          bestPath[diagonalPath] = undefined;
          continue;
        }

        if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
          basePath = clonePath(removePath);
          pushComponent(basePath.components, false, true);
        } else {
          basePath = addPath;
          basePath.newPos++;
          pushComponent(basePath.components, true, false);
        }

        oldPos = extractCommon(basePath, newArr, oldArr, diagonalPath, equals);

        if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
          return buildValues(basePath.components);
        } else {
          bestPath[diagonalPath] = basePath;
        }
      }

      editLength++;
    }

    while (editLength <= maxEditLength) {
      var ret = execEditLength();

      if (ret) {
        return ret;
      }
    }
  }

  function extractCommon(basePath, newArr, oldArr, diagonalPath, equals) {
    var newLen = newArr.length;
    var oldLen = oldArr.length;
    var newPos = basePath.newPos;
    var oldPos = newPos - diagonalPath;
    var commonCount = 0;

    while (newPos + 1 < newLen && oldPos + 1 < oldLen && equals(newArr[newPos + 1], oldArr[oldPos + 1])) {
      newPos++;
      oldPos++;
      commonCount++;
    }

    if (commonCount) {
      basePath.components.push({
        count: commonCount,
        added: false,
        removed: false,
        indices: []
      });
    }

    basePath.newPos = newPos;
    return oldPos;
  }

  function pushComponent(components, added, removed) {
    var last = components[components.length - 1];

    if (last && last.added === added && last.removed === removed) {
      components[components.length - 1] = {
        count: last.count + 1,
        added: added,
        removed: removed,
        indices: []
      };
    } else {
      components.push({
        count: 1,
        added: added,
        removed: removed,
        indices: []
      });
    }
  }

  function buildValues(components) {
    var componentPos = 0;
    var componentLen = components.length;
    var newPos = 0;
    var oldPos = 0;

    for (; componentPos < componentLen; componentPos++) {
      var component = components[componentPos];

      if (!component.removed) {
        var indices = [];

        for (var i = newPos; i < newPos + component.count; i++) {
          indices.push(i);
        }

        component.indices = indices;
        newPos += component.count;

        if (!component.added) {
          oldPos += component.count;
        }
      } else {
        for (var i = oldPos; i < oldPos + component.count; i++) {
          component.indices.push(i);
        }

        oldPos += component.count;
      }
    }

    return components;
  }

  function clonePath(path) {
    return {
      newPos: path.newPos,
      components: path.components.slice(0)
    };
  }

  function arrayDiff(oldArr, newArr, equal) {
    return diff(oldArr, newArr, equal);
  }

  var MARK_UNUSED = '0';
  var MARK_USED = '1';

  var Definable = function () {
    function Definable(zrId, svgRoot, tagNames, markLabel, domName) {
      this.nextId = 0;
      this._domName = '_dom';
      this.createElement = createElement;
      this._zrId = zrId;
      this._svgRoot = svgRoot;
      this._tagNames = typeof tagNames === 'string' ? [tagNames] : tagNames;
      this._markLabel = markLabel;

      if (domName) {
        this._domName = domName;
      }
    }

    Definable.prototype.getDefs = function (isForceCreating) {
      var svgRoot = this._svgRoot;

      var defs = this._svgRoot.getElementsByTagName('defs');

      if (defs.length === 0) {
        if (isForceCreating) {
          var defs_1 = svgRoot.insertBefore(this.createElement('defs'), svgRoot.firstChild);

          if (!defs_1.contains) {
            defs_1.contains = function (el) {
              var children = defs_1.children;

              if (!children) {
                return false;
              }

              for (var i = children.length - 1; i >= 0; --i) {
                if (children[i] === el) {
                  return true;
                }
              }

              return false;
            };
          }

          return defs_1;
        } else {
          return null;
        }
      } else {
        return defs[0];
      }
    };

    Definable.prototype.doUpdate = function (target, onUpdate) {
      if (!target) {
        return;
      }

      var defs = this.getDefs(false);

      if (target[this._domName] && defs.contains(target[this._domName])) {
        if (typeof onUpdate === 'function') {
          onUpdate(target);
        }
      } else {
        var dom = this.add(target);

        if (dom) {
          target[this._domName] = dom;
        }
      }
    };

    Definable.prototype.add = function (target) {
      return null;
    };

    Definable.prototype.addDom = function (dom) {
      var defs = this.getDefs(true);

      if (dom.parentNode !== defs) {
        defs.appendChild(dom);
      }
    };

    Definable.prototype.removeDom = function (target) {
      var defs = this.getDefs(false);

      if (defs && target[this._domName]) {
        defs.removeChild(target[this._domName]);
        target[this._domName] = null;
      }
    };

    Definable.prototype.getDoms = function () {
      var defs = this.getDefs(false);

      if (!defs) {
        return [];
      }

      var doms = [];
      each(this._tagNames, function (tagName) {
        var tags = defs.getElementsByTagName(tagName);

        for (var i = 0; i < tags.length; i++) {
          doms.push(tags[i]);
        }
      });
      return doms;
    };

    Definable.prototype.markAllUnused = function () {
      var doms = this.getDoms();
      var that = this;
      each(doms, function (dom) {
        dom[that._markLabel] = MARK_UNUSED;
      });
    };

    Definable.prototype.markDomUsed = function (dom) {
      dom && (dom[this._markLabel] = MARK_USED);
    };

    Definable.prototype.markDomUnused = function (dom) {
      dom && (dom[this._markLabel] = MARK_UNUSED);
    };

    Definable.prototype.isDomUnused = function (dom) {
      return dom && dom[this._markLabel] !== MARK_USED;
    };

    Definable.prototype.removeUnused = function () {
      var _this = this;

      var defs = this.getDefs(false);

      if (!defs) {
        return;
      }

      var doms = this.getDoms();
      each(doms, function (dom) {
        if (_this.isDomUnused(dom)) {
          defs.removeChild(dom);
        }
      });
    };

    Definable.prototype.getSvgProxy = function (displayable) {
      if (displayable instanceof Path) {
        return svgPath;
      } else if (displayable instanceof ZRImage) {
        return svgImage;
      } else if (displayable instanceof TSpan) {
        return svgText;
      } else {
        return svgPath;
      }
    };

    Definable.prototype.getSvgElement = function (displayable) {
      return displayable.__svgEl;
    };

    return Definable;
  }();

  function isLinearGradient(value) {
    return value.type === 'linear';
  }

  function isRadialGradient(value) {
    return value.type === 'radial';
  }

  function isGradient(value) {
    return value && (value.type === 'linear' || value.type === 'radial');
  }

  var GradientManager = function (_super) {
    __extends(GradientManager, _super);

    function GradientManager(zrId, svgRoot) {
      return _super.call(this, zrId, svgRoot, ['linearGradient', 'radialGradient'], '__gradient_in_use__') || this;
    }

    GradientManager.prototype.addWithoutUpdate = function (svgElement, displayable) {
      if (displayable && displayable.style) {
        var that_1 = this;
        each(['fill', 'stroke'], function (fillOrStroke) {
          var value = displayable.style[fillOrStroke];

          if (isGradient(value)) {
            var gradient = value;
            var defs = that_1.getDefs(true);
            var dom = void 0;

            if (gradient.__dom) {
              dom = gradient.__dom;

              if (!defs.contains(gradient.__dom)) {
                that_1.addDom(dom);
              }
            } else {
              dom = that_1.add(gradient);
            }

            that_1.markUsed(displayable);
            var id = dom.getAttribute('id');
            svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')');
          }
        });
      }
    };

    GradientManager.prototype.add = function (gradient) {
      var dom;

      if (isLinearGradient(gradient)) {
        dom = this.createElement('linearGradient');
      } else if (isRadialGradient(gradient)) {
        dom = this.createElement('radialGradient');
      } else {
        logError('Illegal gradient type.');
        return null;
      }

      gradient.id = gradient.id || this.nextId++;
      dom.setAttribute('id', 'zr' + this._zrId + '-gradient-' + gradient.id);
      this.updateDom(gradient, dom);
      this.addDom(dom);
      return dom;
    };

    GradientManager.prototype.update = function (gradient) {
      if (!isGradient(gradient)) {
        return;
      }

      var that = this;
      this.doUpdate(gradient, function () {
        var dom = gradient.__dom;

        if (!dom) {
          return;
        }

        var tagName = dom.tagName;
        var type = gradient.type;

        if (type === 'linear' && tagName === 'linearGradient' || type === 'radial' && tagName === 'radialGradient') {
          that.updateDom(gradient, gradient.__dom);
        } else {
          that.removeDom(gradient);
          that.add(gradient);
        }
      });
    };

    GradientManager.prototype.updateDom = function (gradient, dom) {
      if (isLinearGradient(gradient)) {
        dom.setAttribute('x1', gradient.x + '');
        dom.setAttribute('y1', gradient.y + '');
        dom.setAttribute('x2', gradient.x2 + '');
        dom.setAttribute('y2', gradient.y2 + '');
      } else if (isRadialGradient(gradient)) {
        dom.setAttribute('cx', gradient.x + '');
        dom.setAttribute('cy', gradient.y + '');
        dom.setAttribute('r', gradient.r + '');
      } else {
        logError('Illegal gradient type.');
        return;
      }

      if (gradient.global) {
        dom.setAttribute('gradientUnits', 'userSpaceOnUse');
      } else {
        dom.setAttribute('gradientUnits', 'objectBoundingBox');
      }

      dom.innerHTML = '';
      var colors = gradient.colorStops;

      for (var i = 0, len = colors.length; i < len; ++i) {
        var stop_1 = this.createElement('stop');
        stop_1.setAttribute('offset', colors[i].offset * 100 + '%');
        var color$1 = colors[i].color;

        if (color$1.indexOf('rgba') > -1) {
          var opacity = parse(color$1)[3];
          var hex = toHex(color$1);
          stop_1.setAttribute('stop-color', '#' + hex);
          stop_1.setAttribute('stop-opacity', opacity + '');
        } else {
          stop_1.setAttribute('stop-color', colors[i].color);
        }

        dom.appendChild(stop_1);
      }

      gradient.__dom = dom;
    };

    GradientManager.prototype.markUsed = function (displayable) {
      if (displayable.style) {
        var gradient = displayable.style.fill;

        if (gradient && gradient.__dom) {
          _super.prototype.markDomUsed.call(this, gradient.__dom);
        }

        gradient = displayable.style.stroke;

        if (gradient && gradient.__dom) {
          _super.prototype.markDomUsed.call(this, gradient.__dom);
        }
      }
    };

    return GradientManager;
  }(Definable);

  function isPattern(value) {
    return value && (!!value.image || !!value.svgElement);
  }

  var patternDomMap = new WeakMap();

  var PatternManager = function (_super) {
    __extends(PatternManager, _super);

    function PatternManager(zrId, svgRoot) {
      return _super.call(this, zrId, svgRoot, ['pattern'], '__pattern_in_use__') || this;
    }

    PatternManager.prototype.addWithoutUpdate = function (svgElement, displayable) {
      if (displayable && displayable.style) {
        var that_1 = this;
        each(['fill', 'stroke'], function (fillOrStroke) {
          var pattern = displayable.style[fillOrStroke];

          if (isPattern(pattern)) {
            var defs = that_1.getDefs(true);
            var dom = patternDomMap.get(pattern);

            if (dom) {
              if (!defs.contains(dom)) {
                that_1.addDom(dom);
              }
            } else {
              dom = that_1.add(pattern);
            }

            that_1.markUsed(displayable);
            var id = dom.getAttribute('id');
            svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')');
          }
        });
      }
    };

    PatternManager.prototype.add = function (pattern) {
      if (!isPattern(pattern)) {
        return;
      }

      var dom = this.createElement('pattern');
      pattern.id = pattern.id == null ? this.nextId++ : pattern.id;
      dom.setAttribute('id', 'zr' + this._zrId + '-pattern-' + pattern.id);
      dom.setAttribute('x', '0');
      dom.setAttribute('y', '0');
      dom.setAttribute('patternUnits', 'userSpaceOnUse');
      this.updateDom(pattern, dom);
      this.addDom(dom);
      return dom;
    };

    PatternManager.prototype.update = function (pattern) {
      if (!isPattern(pattern)) {
        return;
      }

      var that = this;
      this.doUpdate(pattern, function () {
        var dom = patternDomMap.get(pattern);
        that.updateDom(pattern, dom);
      });
    };

    PatternManager.prototype.updateDom = function (pattern, patternDom) {
      var svgElement = pattern.svgElement;

      if (svgElement instanceof SVGElement) {
        if (svgElement.parentNode !== patternDom) {
          patternDom.innerHTML = '';
          patternDom.appendChild(svgElement);
          patternDom.setAttribute('width', pattern.svgWidth + '');
          patternDom.setAttribute('height', pattern.svgHeight + '');
        }
      } else {
        var img = void 0;
        var prevImage = patternDom.getElementsByTagName('image');

        if (prevImage.length) {
          if (pattern.image) {
            img = prevImage[0];
          } else {
            patternDom.removeChild(prevImage[0]);
            return;
          }
        } else if (pattern.image) {
          img = this.createElement('image');
        }

        if (img) {
          var imageSrc = void 0;

          if (typeof pattern.image === 'string') {
            imageSrc = pattern.image;
          } else if (pattern.image instanceof HTMLImageElement) {
            imageSrc = pattern.image.src;
          } else if (pattern.image instanceof HTMLCanvasElement) {
            imageSrc = pattern.image.toDataURL();
          }

          if (imageSrc) {
            img.setAttribute('href', imageSrc);
            img.setAttribute('x', '0');
            img.setAttribute('y', '0');
            var hostEl = {
              dirty: function () {}
            };
            var createdImage = createOrUpdateImage(imageSrc, img, hostEl, function (img) {
              patternDom.setAttribute('width', img.width + '');
              patternDom.setAttribute('height', img.height + '');
            });

            if (createdImage && createdImage.width && createdImage.height) {
              patternDom.setAttribute('width', createdImage.width + '');
              patternDom.setAttribute('height', createdImage.height + '');
            }

            patternDom.appendChild(img);
          }
        }
      }

      var x = pattern.x || 0;
      var y = pattern.y || 0;
      var rotation = (pattern.rotation || 0) / Math.PI * 180;
      var scaleX = pattern.scaleX || 1;
      var scaleY = pattern.scaleY || 1;
      var transform = "translate(" + x + ", " + y + ") rotate(" + rotation + ") scale(" + scaleX + ", " + scaleY + ")";
      patternDom.setAttribute('patternTransform', transform);
      patternDomMap.set(pattern, patternDom);
    };

    PatternManager.prototype.markUsed = function (displayable) {
      if (displayable.style) {
        if (isPattern(displayable.style.fill)) {
          _super.prototype.markDomUsed.call(this, patternDomMap.get(displayable.style.fill));
        }

        if (isPattern(displayable.style.stroke)) {
          _super.prototype.markDomUsed.call(this, patternDomMap.get(displayable.style.stroke));
        }
      }
    };

    return PatternManager;
  }(Definable);

  function generateClipPathsKey(clipPaths) {
    var key = [];

    if (clipPaths) {
      for (var i = 0; i < clipPaths.length; i++) {
        var clipPath = clipPaths[i];
        key.push(clipPath.id);
      }
    }

    return key.join(',');
  }

  function hasClipPath(displayable) {
    var clipPaths = displayable.__clipPaths;
    return clipPaths && clipPaths.length > 0;
  }

  var ClippathManager = function (_super) {
    __extends(ClippathManager, _super);

    function ClippathManager(zrId, svgRoot) {
      var _this = _super.call(this, zrId, svgRoot, 'clipPath', '__clippath_in_use__') || this;

      _this._refGroups = {};
      _this._keyDuplicateCount = {};
      return _this;
    }

    ClippathManager.prototype.markAllUnused = function () {
      _super.prototype.markAllUnused.call(this);

      for (var key in this._refGroups) {
        this.markDomUnused(this._refGroups[key]);
      }

      this._keyDuplicateCount = {};
    };

    ClippathManager.prototype._getClipPathGroup = function (displayable, prevDisplayable) {
      if (!hasClipPath(displayable)) {
        return;
      }

      var clipPaths = displayable.__clipPaths;
      var keyDuplicateCount = this._keyDuplicateCount;
      var clipPathKey = generateClipPathsKey(clipPaths);

      if (isClipPathChanged(clipPaths, prevDisplayable && prevDisplayable.__clipPaths)) {
        keyDuplicateCount[clipPathKey] = keyDuplicateCount[clipPathKey] || 0;
        keyDuplicateCount[clipPathKey] && (clipPathKey += '-' + keyDuplicateCount[clipPathKey]);
        keyDuplicateCount[clipPathKey]++;
      }

      return this._refGroups[clipPathKey] || (this._refGroups[clipPathKey] = this.createElement('g'));
    };

    ClippathManager.prototype.update = function (displayable, prevDisplayable) {
      var clipGroup = this._getClipPathGroup(displayable, prevDisplayable);

      if (clipGroup) {
        this.markDomUsed(clipGroup);
        this.updateDom(clipGroup, displayable.__clipPaths);
      }

      return clipGroup;
    };

    ClippathManager.prototype.updateDom = function (parentEl, clipPaths) {
      if (clipPaths && clipPaths.length > 0) {
        var defs = this.getDefs(true);
        var clipPath = clipPaths[0];
        var clipPathEl = void 0;
        var id = void 0;

        if (clipPath._dom) {
          id = clipPath._dom.getAttribute('id');
          clipPathEl = clipPath._dom;

          if (!defs.contains(clipPathEl)) {
            defs.appendChild(clipPathEl);
          }
        } else {
          id = 'zr' + this._zrId + '-clip-' + this.nextId;
          ++this.nextId;
          clipPathEl = this.createElement('clipPath');
          clipPathEl.setAttribute('id', id);
          defs.appendChild(clipPathEl);
          clipPath._dom = clipPathEl;
        }

        var svgProxy = this.getSvgProxy(clipPath);
        svgProxy.brush(clipPath);
        var pathEl = this.getSvgElement(clipPath);
        clipPathEl.innerHTML = '';
        clipPathEl.appendChild(pathEl);
        parentEl.setAttribute('clip-path', 'url(#' + id + ')');

        if (clipPaths.length > 1) {
          this.updateDom(clipPathEl, clipPaths.slice(1));
        }
      } else {
        if (parentEl) {
          parentEl.setAttribute('clip-path', 'none');
        }
      }
    };

    ClippathManager.prototype.markUsed = function (displayable) {
      var _this = this;

      if (displayable.__clipPaths) {
        each(displayable.__clipPaths, function (clipPath) {
          if (clipPath._dom) {
            _super.prototype.markDomUsed.call(_this, clipPath._dom);
          }
        });
      }
    };

    ClippathManager.prototype.removeUnused = function () {
      _super.prototype.removeUnused.call(this);

      var newRefGroupsMap = {};

      for (var key in this._refGroups) {
        var group = this._refGroups[key];

        if (!this.isDomUnused(group)) {
          newRefGroupsMap[key] = group;
        } else if (group.parentNode) {
          group.parentNode.removeChild(group);
        }
      }

      this._refGroups = newRefGroupsMap;
    };

    return ClippathManager;
  }(Definable);

  var ShadowManager = function (_super) {
    __extends(ShadowManager, _super);

    function ShadowManager(zrId, svgRoot) {
      var _this = _super.call(this, zrId, svgRoot, ['filter'], '__filter_in_use__', '_shadowDom') || this;

      _this._shadowDomMap = {};
      _this._shadowDomPool = [];
      return _this;
    }

    ShadowManager.prototype._getFromPool = function () {
      var shadowDom = this._shadowDomPool.pop();

      if (!shadowDom) {
        shadowDom = this.createElement('filter');
        shadowDom.setAttribute('id', 'zr' + this._zrId + '-shadow-' + this.nextId++);
        var domChild = this.createElement('feDropShadow');
        shadowDom.appendChild(domChild);
        this.addDom(shadowDom);
      }

      return shadowDom;
    };

    ShadowManager.prototype.update = function (svgElement, displayable) {
      var style = displayable.style;

      if (hasShadow(style)) {
        var shadowKey = getShadowKey(displayable);
        var shadowDom = displayable._shadowDom = this._shadowDomMap[shadowKey];

        if (!shadowDom) {
          shadowDom = this._getFromPool();
          this._shadowDomMap[shadowKey] = shadowDom;
        }

        this.updateDom(svgElement, displayable, shadowDom);
      } else {
        this.remove(svgElement, displayable);
      }
    };

    ShadowManager.prototype.remove = function (svgElement, displayable) {
      if (displayable._shadowDom != null) {
        displayable._shadowDom = null;
        svgElement.style.filter = '';
      }
    };

    ShadowManager.prototype.updateDom = function (svgElement, displayable, shadowDom) {
      var domChild = shadowDom.children[0];
      var style = displayable.style;
      var globalScale = displayable.getGlobalScale();
      var scaleX = globalScale[0];
      var scaleY = globalScale[1];

      if (!scaleX || !scaleY) {
        return;
      }

      var offsetX = style.shadowOffsetX || 0;
      var offsetY = style.shadowOffsetY || 0;
      var blur = style.shadowBlur;
      var color = style.shadowColor;
      domChild.setAttribute('dx', offsetX / scaleX + '');
      domChild.setAttribute('dy', offsetY / scaleY + '');
      domChild.setAttribute('flood-color', color);
      var stdDx = blur / 2 / scaleX;
      var stdDy = blur / 2 / scaleY;
      var stdDeviation = stdDx + ' ' + stdDy;
      domChild.setAttribute('stdDeviation', stdDeviation);
      shadowDom.setAttribute('x', '-100%');
      shadowDom.setAttribute('y', '-100%');
      shadowDom.setAttribute('width', '300%');
      shadowDom.setAttribute('height', '300%');
      displayable._shadowDom = shadowDom;
      var id = shadowDom.getAttribute('id');
      svgElement.style.filter = 'url(#' + id + ')';
    };

    ShadowManager.prototype.removeUnused = function () {
      var defs = this.getDefs(false);

      if (!defs) {
        return;
      }

      var shadowDomsPool = this._shadowDomPool;

      for (var key in this._shadowDomMap) {
        var dom = this._shadowDomMap[key];
        shadowDomsPool.push(dom);
      }

      this._shadowDomMap = {};
    };

    return ShadowManager;
  }(Definable);

  function hasShadow(style) {
    return style && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY);
  }

  function getShadowKey(displayable) {
    var style = displayable.style;
    var globalScale = displayable.getGlobalScale();
    return [style.shadowColor, (style.shadowBlur || 0).toFixed(2), (style.shadowOffsetX || 0).toFixed(2), (style.shadowOffsetY || 0).toFixed(2), globalScale[0], globalScale[1]].join(',');
  }

  function parseInt10$1(val) {
    return parseInt(val, 10);
  }

  function getSvgProxy(el) {
    if (el instanceof Path) {
      return svgPath;
    } else if (el instanceof ZRImage) {
      return svgImage;
    } else if (el instanceof TSpan) {
      return svgText;
    } else {
      return svgPath;
    }
  }

  function checkParentAvailable(parent, child) {
    return child && parent && child.parentNode !== parent;
  }

  function insertAfter(parent, child, prevSibling) {
    if (checkParentAvailable(parent, child) && prevSibling) {
      var nextSibling = prevSibling.nextSibling;
      nextSibling ? parent.insertBefore(child, nextSibling) : parent.appendChild(child);
    }
  }

  function prepend(parent, child) {
    if (checkParentAvailable(parent, child)) {
      var firstChild = parent.firstChild;
      firstChild ? parent.insertBefore(child, firstChild) : parent.appendChild(child);
    }
  }

  function remove(parent, child) {
    if (child && parent && child.parentNode === parent) {
      parent.removeChild(child);
    }
  }

  function removeFromMyParent(child) {
    if (child && child.parentNode) {
      child.parentNode.removeChild(child);
    }
  }

  function getSvgElement(displayable) {
    return displayable.__svgEl;
  }

  var SVGPainter = function () {
    function SVGPainter(root, storage, opts, zrId) {
      this.type = 'svg';
      this.refreshHover = createMethodNotSupport('refreshHover');
      this.pathToImage = createMethodNotSupport('pathToImage');
      this.configLayer = createMethodNotSupport('configLayer');
      this.root = root;
      this.storage = storage;
      this._opts = opts = extend({}, opts || {});
      var svgDom = createElement('svg');
      svgDom.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
      svgDom.setAttribute('version', '1.1');
      svgDom.setAttribute('baseProfile', 'full');
      svgDom.style.cssText = 'user-select:none;position:absolute;left:0;top:0;';
      var bgRoot = createElement('g');
      svgDom.appendChild(bgRoot);
      var svgRoot = createElement('g');
      svgDom.appendChild(svgRoot);
      this._gradientManager = new GradientManager(zrId, svgRoot);
      this._patternManager = new PatternManager(zrId, svgRoot);
      this._clipPathManager = new ClippathManager(zrId, svgRoot);
      this._shadowManager = new ShadowManager(zrId, svgRoot);
      var viewport = document.createElement('div');
      viewport.style.cssText = 'overflow:hidden;position:relative';
      this._svgDom = svgDom;
      this._svgRoot = svgRoot;
      this._backgroundRoot = bgRoot;
      this._viewport = viewport;
      root.appendChild(viewport);
      viewport.appendChild(svgDom);
      this.resize(opts.width, opts.height);
      this._visibleList = [];
    }

    SVGPainter.prototype.getType = function () {
      return 'svg';
    };

    SVGPainter.prototype.getViewportRoot = function () {
      return this._viewport;
    };

    SVGPainter.prototype.getSvgDom = function () {
      return this._svgDom;
    };

    SVGPainter.prototype.getSvgRoot = function () {
      return this._svgRoot;
    };

    SVGPainter.prototype.getViewportRootOffset = function () {
      var viewportRoot = this.getViewportRoot();

      if (viewportRoot) {
        return {
          offsetLeft: viewportRoot.offsetLeft || 0,
          offsetTop: viewportRoot.offsetTop || 0
        };
      }
    };

    SVGPainter.prototype.refresh = function () {
      var list = this.storage.getDisplayList(true);

      this._paintList(list);
    };

    SVGPainter.prototype.setBackgroundColor = function (backgroundColor) {
      if (this._backgroundRoot && this._backgroundNode) {
        this._backgroundRoot.removeChild(this._backgroundNode);
      }

      var bgNode = createElement('rect');
      bgNode.setAttribute('width', this.getWidth());
      bgNode.setAttribute('height', this.getHeight());
      bgNode.setAttribute('x', 0);
      bgNode.setAttribute('y', 0);
      bgNode.setAttribute('id', 0);
      bgNode.style.fill = backgroundColor;

      this._backgroundRoot.appendChild(bgNode);

      this._backgroundNode = bgNode;
    };

    SVGPainter.prototype.createSVGElement = function (tag) {
      return createElement(tag);
    };

    SVGPainter.prototype.paintOne = function (el) {
      var svgProxy = getSvgProxy(el);
      svgProxy && svgProxy.brush(el);
      return getSvgElement(el);
    };

    SVGPainter.prototype._paintList = function (list) {
      var gradientManager = this._gradientManager;
      var patternManager = this._patternManager;
      var clipPathManager = this._clipPathManager;
      var shadowManager = this._shadowManager;
      gradientManager.markAllUnused();
      patternManager.markAllUnused();
      clipPathManager.markAllUnused();
      shadowManager.markAllUnused();
      var svgRoot = this._svgRoot;
      var visibleList = this._visibleList;
      var listLen = list.length;
      var newVisibleList = [];

      for (var i = 0; i < listLen; i++) {
        var displayable = list[i];
        var svgProxy = getSvgProxy(displayable);
        var svgElement = getSvgElement(displayable);

        if (!displayable.invisible) {
          if (displayable.__dirty || !svgElement) {
            svgProxy && svgProxy.brush(displayable);
            svgElement = getSvgElement(displayable);

            if (svgElement && displayable.style) {
              gradientManager.update(displayable.style.fill);
              gradientManager.update(displayable.style.stroke);
              patternManager.update(displayable.style.fill);
              patternManager.update(displayable.style.stroke);
              shadowManager.update(svgElement, displayable);
            }

            displayable.__dirty = 0;
          }

          if (svgElement) {
            newVisibleList.push(displayable);
          }
        }
      }

      var diff = arrayDiff(visibleList, newVisibleList);
      var prevSvgElement;
      var topPrevSvgElement;

      for (var i = 0; i < diff.length; i++) {
        var item = diff[i];

        if (item.removed) {
          for (var k = 0; k < item.count; k++) {
            var displayable = visibleList[item.indices[k]];
            var svgElement = getSvgElement(displayable);
            hasClipPath(displayable) ? removeFromMyParent(svgElement) : remove(svgRoot, svgElement);
          }
        }
      }

      var prevDisplayable;
      var currentClipGroup;

      for (var i = 0; i < diff.length; i++) {
        var item = diff[i];
        var isAdd = item.added;

        if (item.removed) {
          continue;
        }

        for (var k = 0; k < item.count; k++) {
          var displayable = newVisibleList[item.indices[k]];
          var clipGroup = clipPathManager.update(displayable, prevDisplayable);

          if (clipGroup !== currentClipGroup) {
            prevSvgElement = topPrevSvgElement;

            if (clipGroup) {
              prevSvgElement ? insertAfter(svgRoot, clipGroup, prevSvgElement) : prepend(svgRoot, clipGroup);
              topPrevSvgElement = clipGroup;
              prevSvgElement = null;
            }

            currentClipGroup = clipGroup;
          }

          var svgElement = getSvgElement(displayable);
          prevSvgElement ? insertAfter(currentClipGroup || svgRoot, svgElement, prevSvgElement) : prepend(currentClipGroup || svgRoot, svgElement);
          prevSvgElement = svgElement || prevSvgElement;

          if (!currentClipGroup) {
            topPrevSvgElement = prevSvgElement;
          }

          gradientManager.markUsed(displayable);
          gradientManager.addWithoutUpdate(svgElement, displayable);
          patternManager.markUsed(displayable);
          patternManager.addWithoutUpdate(svgElement, displayable);
          clipPathManager.markUsed(displayable);
          prevDisplayable = displayable;
        }
      }

      gradientManager.removeUnused();
      patternManager.removeUnused();
      clipPathManager.removeUnused();
      shadowManager.removeUnused();
      this._visibleList = newVisibleList;
    };

    SVGPainter.prototype._getDefs = function (isForceCreating) {
      var svgRoot = this._svgDom;
      var defs = svgRoot.getElementsByTagName('defs');

      if (defs.length === 0) {
        if (isForceCreating) {
          var defs_1 = svgRoot.insertBefore(createElement('defs'), svgRoot.firstChild);

          if (!defs_1.contains) {
            defs_1.contains = function (el) {
              var children = defs_1.children;

              if (!children) {
                return false;
              }

              for (var i = children.length - 1; i >= 0; --i) {
                if (children[i] === el) {
                  return true;
                }
              }

              return false;
            };
          }

          return defs_1;
        } else {
          return null;
        }
      } else {
        return defs[0];
      }
    };

    SVGPainter.prototype.resize = function (width, height) {
      var viewport = this._viewport;
      viewport.style.display = 'none';
      var opts = this._opts;
      width != null && (opts.width = width);
      height != null && (opts.height = height);
      width = this._getSize(0);
      height = this._getSize(1);
      viewport.style.display = '';

      if (this._width !== width || this._height !== height) {
        this._width = width;
        this._height = height;
        var viewportStyle = viewport.style;
        viewportStyle.width = width + 'px';
        viewportStyle.height = height + 'px';
        var svgRoot = this._svgDom;
        svgRoot.setAttribute('width', width + '');
        svgRoot.setAttribute('height', height + '');
      }

      if (this._backgroundNode) {
        this._backgroundNode.setAttribute('width', width);

        this._backgroundNode.setAttribute('height', height);
      }
    };

    SVGPainter.prototype.getWidth = function () {
      return this._width;
    };

    SVGPainter.prototype.getHeight = function () {
      return this._height;
    };

    SVGPainter.prototype._getSize = function (whIdx) {
      var opts = this._opts;
      var wh = ['width', 'height'][whIdx];
      var cwh = ['clientWidth', 'clientHeight'][whIdx];
      var plt = ['paddingLeft', 'paddingTop'][whIdx];
      var prb = ['paddingRight', 'paddingBottom'][whIdx];

      if (opts[wh] != null && opts[wh] !== 'auto') {
        return parseFloat(opts[wh]);
      }

      var root = this.root;
      var stl = document.defaultView.getComputedStyle(root);
      return (root[cwh] || parseInt10$1(stl[wh]) || parseInt10$1(root.style[wh])) - (parseInt10$1(stl[plt]) || 0) - (parseInt10$1(stl[prb]) || 0) | 0;
    };

    SVGPainter.prototype.dispose = function () {
      this.root.innerHTML = '';
      this._svgRoot = this._backgroundRoot = this._svgDom = this._backgroundNode = this._viewport = this.storage = null;
    };

    SVGPainter.prototype.clear = function () {
      var viewportNode = this._viewport;

      if (viewportNode && viewportNode.parentNode) {
        viewportNode.parentNode.removeChild(viewportNode);
      }
    };

    SVGPainter.prototype.toDataURL = function () {
      this.refresh();
      var html = encodeURIComponent(this._svgDom.outerHTML.replace(/></g, '>\n\r<'));
      return 'data:image/svg+xml;charset=UTF-8,' + html;
    };

    return SVGPainter;
  }();

  function createMethodNotSupport(method) {
    return function () {
      logError('In SVG mode painter not support method "' + method + '"');
    };
  }

  registerPainter('svg', SVGPainter);
  exports.Axis = Axis;
  exports.List = List;
  exports.Model = Model;
  exports.PRIORITY = PRIORITY;
  exports.color = color;
  exports.connect = connect;
  exports.dataTool = dataTool;
  exports.dependencies = dependencies;
  exports.disConnect = disConnect;
  exports.disconnect = disconnect;
  exports.dispose = dispose$1;
  exports.env = env;
  exports.extendChartView = extendChartView;
  exports.extendComponentModel = extendComponentModel;
  exports.extendComponentView = extendComponentView;
  exports.extendSeriesModel = extendSeriesModel;
  exports.format = format$1;
  exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions;
  exports.getInstanceByDom = getInstanceByDom;
  exports.getInstanceById = getInstanceById;
  exports.getMap = getMap;
  exports.graphic = graphic$1;
  exports.helper = helper;
  exports.init = init$1;
  exports.innerDrawElementOnCanvas = brushSingle;
  exports.matrix = matrix;
  exports.number = number;
  exports.parseGeoJSON = parseGeoJSON;
  exports.parseGeoJson = parseGeoJson;
  exports.registerAction = registerAction;
  exports.registerCoordinateSystem = registerCoordinateSystem;
  exports.registerLayout = registerLayout;
  exports.registerLoading = registerLoading;
  exports.registerLocale = registerLocale;
  exports.registerMap = registerMap;
  exports.registerPostInit = registerPostInit;
  exports.registerPostUpdate = registerPostUpdate;
  exports.registerPreprocessor = registerPreprocessor;
  exports.registerProcessor = registerProcessor;
  exports.registerTheme = registerTheme;
  exports.registerTransform = registerTransform;
  exports.registerVisual = registerVisual;
  exports.setCanvasCreator = setCanvasCreator;
  exports.throttle = throttle;
  exports.time = time;
  exports.util = ecUtil;
  exports.vector = vector;
  exports.version = version$1;
  exports.zrender = zrender;
  Object.defineProperty(exports, '__esModule', {
    value: true
  });
});