(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(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) {
        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';

  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 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 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.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.0';
  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 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 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 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 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;
    }
  });

  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 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);
        }

    }
  }

  var PI2$6 = Math.PI * 2;
  var CMD$3 = 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$6 < 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$6;
    }

    var angle = Math.atan2(y, x);

    if (angle < 0) {
      angle += PI2$6;
    }

    if (angle >= startAngle && angle <= endAngle || angle + PI2$6 >= startAngle && angle + PI2$6 <= 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$3.M:
          x0 = data[i++];
          y0 = data[i++];
          xi = x0;
          yi = y0;
          break;

        case CMD$3.L:
          d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true);
          xi = data[i++];
          yi = data[i++];
          break;

        case CMD$3.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$3.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$3.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$3.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$3.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 = [];
  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, false);
      tmpProjPoint.fromArray(tmpArr);
      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, false);
      tmpProjPoint.fromArray(tmpArr);
      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$1 = 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$1();
  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.0'
  };
  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 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 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$7 = 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$7;
      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$7 / 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$7 && validDataCount) {
        if (restAngle <= 1e-3) {
          var angle_1 = PI2$7 / 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'));

  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);
  }

  var inner$6 = 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(id, targetElParent, elOptionCleaned, elMap);
        } else if ($action === 'replace') {
          removeEl(elExisting, elMap);
          createEl(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$6(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$6(el);
        var parentElInner = inner$6(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$6(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(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$6(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$6(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;
    }
  }

  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$7 = 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$7(zr)[highDownKey] || {};
    var newHighlights = inner$7(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$8 = makeInner();
  var each$4 = each;

  function register(key, api, handler) {
    if (env.node) {
      return;
    }

    var zr = api.getZr();
    inner$8(zr).records || (inner$8(zr).records = {});
    initGlobalListeners(zr, api);
    var record = inner$8(zr).records[key] || (inner$8(zr).records[key] = {});
    record.handler = handler;
  }

  function initGlobalListeners(zr, api) {
    if (inner$8(zr).initialized) {
      return;
    }

    inner$8(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$4(inner$8(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$8(zr).records || {})[key];

    if (record) {
      inner$8(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$9 = 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$9(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$9(group).labelEl = new ZRText(clone$3(elOption.label));
        group.add(labelEl);
        updateLabelShowHide(labelEl, axisPointerModel);
      }
    };

    BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) {
      var pointerEl = inner$9(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$9(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$9(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$9(el).lastProp, props)) {
      inner$9(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]
    };
  }

  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 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$5 = 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$5(dataByCoordSys, function (itemCoordSys) {
        each$5(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$5(lastCoordSys, function (lastItemCoordSys, indexCoordSys) {
        var lastDataByAxis = lastItemCoordSys.dataByAxis || [];
        var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {};
        var thisDataByAxis = thisItemCoordSys.dataByAxis || [];
        contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length;
        contentNotChanged && each$5(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$5(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 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'));

  function layout$2(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 curry$1 = curry;
  var each$6 = each;
  var Group$1 = 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$1());
      this.group.add(this._selectorGroup = new Group$1());
      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$6(legendModel.getData(), function (itemModel, dataIndex) {
        var name = itemModel.get('name');

        if (!this.newlineDisabled && (name === '' || name === '\n')) {
          var g = new Group$1();
          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$6(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$1();
      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(this, option, inputPositionParams);
    };

    ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) {
      _super.prototype.mergeOption.call(this, option, ecModel);

      mergeAndNormalizeLayoutParams(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(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$2 = Group;
  var WH = ['width', 'height'];
  var XY = ['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$2());

      this._containerGroup.add(this.getContentGroup());

      this.group.add(this._controllerGroup = new Group$2());
    };

    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[orientIdx];
      var xy = XY[orientIdx];
      var hw = WH[1 - orientIdx];
      var yx = XY[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[orientIdx];
      var xy = XY[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 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 fillLabel(opt) {
    defaultEmphasis(opt, 'label', ['show']);
  }

  var inner$a = 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$a(seriesModel)[componentType];

          if (!markerOpt || !markerOpt.data) {
            inner$a(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$a(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$a(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$b = 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$b(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$b(item).keep && _this.group.remove(item.group);
      });
    };

    MarkerView.prototype.markKeep = function (drawGroup) {
      inner$b(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 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]);
  }

  var inner$c = 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$c(mlModel).from;
          var toData_1 = inner$c(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$c(mlModel).from = fromData;
      inner$c(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$d = 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$d(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$d(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$d(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$d(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 || {};
  });
  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 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);

  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 Rect$1 = 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$1({
        silent: true,
        shape: {
          x: 0,
          y: 0,
          width: size[0],
          height: size[1]
        },
        style: {
          fill: dataZoomModel.get('backgroundColor')
        },
        z2: -40
      }));
      var clickPanel = new Rect$1({
        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$1({
        silent: brushSelect,
        style: {
          fill: dataZoomModel.get('fillerColor')
        },
        textConfig: {
          position: 'inside'
        }
      });
      sliderGroup.add(filler);
      sliderGroup.add(new Rect$1({
        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$1({
          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 each$7 = 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$7(['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$7(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$7(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$7(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$7(['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$7(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 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 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']);
  }

  var inner$e = makeInner();
  registerProcessor(PRIORITY.PROCESSOR.FILTER, function (ecModel, api) {
    var apiInner = inner$e(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$e(api).coordSysRecordMap.each(function (coordSysRecord) {
      var dzInfo = coordSysRecord.dataZoomInfoMap.get(dataZoomModel.uid);

      if (dzInfo) {
        dzInfo.getRange = getRange;
      }
    });
  }

  function disposeCoordSysRecordIfNeeded(api, dataZoomModel) {
    var coordSysRecordMap = inner$e(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, 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(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 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);

  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$2(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 BRUSH_PANEL_GLOBAL = true;
  var mathMin$7 = Math.min;
  var mathMax$7 = 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$7(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$7(x, x2), mathMin$7(y, y2)];
    var max = [mathMax$7(x, x2), mathMax$7(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$7(points[0][0], points[1][0]);
    var ymin = mathMin$7(points[0][1], points[1][1]);
    var xmax = mathMax$7(points[0][0], points[1][0]);
    var ymax = mathMax$7(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$7(ends[0][xyIndex], ends[1][xyIndex]);
        var max = mathMax$7(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
    };
  }

  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 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 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$8 = each;
  var inner$f = makeInner();

  function push(ecModel, newSnapshot) {
    var storedSnapshots = getStoreSnapshots(ecModel);
    each$8(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$8(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$f(ecModel).snapshots = null;
  }

  function count(ecModel) {
    return getStoreSnapshots(ecModel).length;
  }

  function getStoreSnapshots(ecModel) {
    var store = inner$f(ecModel);

    if (!store.snapshots) {
      store.snapshots = [{}];
    }

    return store.snapshots;
  }

  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$9 = 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[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$9(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 = {
    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$9(finderResult.xAxisModels, function (axisModel) {
      return buildInternalOptions(axisModel, 'xAxis', 'xAxisIndex');
    });
    each$9(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 DEFAULT_OPTION = {
    label: {
      enabled: true
    },
    decal: {
      show: false
    }
  };
  var inner$g = 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$g(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$g(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$7 = Math.PI;
  var PI2$8 = Math.PI * 2;
  var degree = 180 / PI$7;
  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$8) || (clockwise ? dTheta >= PI2$8 : -dTheta >= PI2$8);
      var unifiedTheta = dTheta > 0 ? dTheta % PI2$8 : dTheta % PI2$8 + PI2$8;
      var large = false;

      if (isCircle) {
        large = true;
      } else if (isAroundZero$1(dThetaPositive)) {
        large = false;
      } else {
        large = unifiedTheta >= PI$7 === !!clockwise;
      }

      var x0 = round4(cx + rx * mathCos$4(startAngle));
      var y0 = round4(cy + ry * mathSin$4(startAngle));

      if (isCircle) {
        if (clockwise) {
          dTheta = PI2$8 - 1e-4;
        } else {
          dTheta = -PI2$8 + 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';
  }

  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 (value && (value.type === 'linear' || value.type === 'radial')) {
            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) {
      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.fill));
        }
      }
    };

    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
  });
});