(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["echarts"],{

/***/ "./node_modules/echarts/dist/echarts-en.common.js":
/*!********************************************************!*\
  !*** ./node_modules/echarts/dist/echarts-en.common.js ***!
  \********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

;
eval("/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj){\"@babel/helpers - typeof\";if(typeof Symbol===\"function\"&&typeof Symbol.iterator===\"symbol\"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol===\"function\"&&obj.constructor===Symbol&&obj!==Symbol.prototype?\"symbol\":typeof obj;};}return _typeof(obj);}(function(global,factory){( false?undefined:_typeof(exports))==='object'&&typeof module!=='undefined'?factory(exports): true?!(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)):undefined;})(void 0,function(exports){'use strict';/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // (1) The code `if (__DEV__) ...` can be removed by build tool.\n// (2) If intend to use `__DEV__`, this module should be imported. Use a global\n// variable `__DEV__` may cause that miss the declaration (see #6535), or the\n// declaration is behind of the using position (for example in `Model.extent`,\n// And tools like rollup can not analysis the dependency if not import).\nvar dev;// In browser\nif(typeof window!=='undefined'){dev=window.__DEV__;}// In node\nelse if(typeof global!=='undefined'){dev=global.__DEV__;}if(typeof dev==='undefined'){dev=true;}var __DEV__=dev;/**\n * zrender: 生成唯一id\n *\n * @author errorrik (errorrik@gmail.com)\n */var idStart=0x0907;var guid=function guid(){return idStart++;};/**\n * echarts设备环境识别\n *\n * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。\n * @author firede[firede@firede.us]\n * @desc thanks zepto.\n */ /* global wx */var env={};if((typeof wx===\"undefined\"?\"undefined\":_typeof(wx))==='object'&&typeof wx.getSystemInfoSync==='function'){// In Weixin Application\nenv={browser:{},os:{},node:false,wxa:true,// Weixin Application\ncanvasSupported:true,svgSupported:false,touchEventsSupported:true,domSupported:false};}else if(typeof document==='undefined'&&typeof self!=='undefined'){// In worker\nenv={browser:{},os:{},node:false,worker:true,canvasSupported:true,domSupported:false};}else if(typeof navigator==='undefined'){// In node\nenv={browser:{},os:{},node:true,worker:false,// Assume canvas is supported\ncanvasSupported:true,svgSupported:true,domSupported:false};}else{env=detect(navigator.userAgent);}var env$1=env;// Zepto.js\n// (c) 2010-2013 Thomas Fuchs\n// Zepto.js may be freely distributed under the MIT license.\nfunction detect(ua){var os={};var browser={};// var webkit = ua.match(/Web[kK]it[\\/]{0,1}([\\d.]+)/);\n// var android = ua.match(/(Android);?[\\s\\/]+([\\d.]+)?/);\n// var ipad = ua.match(/(iPad).*OS\\s([\\d_]+)/);\n// var ipod = ua.match(/(iPod)(.*OS\\s([\\d_]+))?/);\n// var iphone = !ipad && ua.match(/(iPhone\\sOS)\\s([\\d_]+)/);\n// var webos = ua.match(/(webOS|hpwOS)[\\s\\/]([\\d.]+)/);\n// var touchpad = webos && ua.match(/TouchPad/);\n// var kindle = ua.match(/Kindle\\/([\\d.]+)/);\n// var silk = ua.match(/Silk\\/([\\d._]+)/);\n// var blackberry = ua.match(/(BlackBerry).*Version\\/([\\d.]+)/);\n// var bb10 = ua.match(/(BB10).*Version\\/([\\d.]+)/);\n// var rimtabletos = ua.match(/(RIM\\sTablet\\sOS)\\s([\\d.]+)/);\n// var playbook = ua.match(/PlayBook/);\n// var chrome = ua.match(/Chrome\\/([\\d.]+)/) || ua.match(/CriOS\\/([\\d.]+)/);\nvar firefox=ua.match(/Firefox\\/([\\d.]+)/);// var safari = webkit && ua.match(/Mobile\\//) && !chrome;\n// var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome;\nvar ie=ua.match(/MSIE\\s([\\d.]+)/)// IE 11 Trident/7.0; rv:11.0\n||ua.match(/Trident\\/.+?rv:(([\\d.]+))/);var edge=ua.match(/Edge\\/([\\d.]+)/);// IE 12 and 12+\nvar weChat=/micromessenger/i.test(ua);// Todo: clean this up with a better OS/browser seperation:\n// - discern (more) between multiple browsers on android\n// - decide if kindle fire in silk mode is android or not\n// - Firefox on Android doesn't specify the Android version\n// - possibly devide in os, device and browser hashes\n// if (browser.webkit = !!webkit) browser.version = webkit[1];\n// if (android) os.android = true, os.version = android[2];\n// if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');\n// if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');\n// if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;\n// if (webos) os.webos = true, os.version = webos[2];\n// if (touchpad) os.touchpad = true;\n// if (blackberry) os.blackberry = true, os.version = blackberry[2];\n// if (bb10) os.bb10 = true, os.version = bb10[2];\n// if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2];\n// if (playbook) browser.playbook = true;\n// if (kindle) os.kindle = true, os.version = kindle[1];\n// if (silk) browser.silk = true, browser.version = silk[1];\n// if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;\n// if (chrome) browser.chrome = true, browser.version = chrome[1];\nif(firefox){browser.firefox=true;browser.version=firefox[1];}// if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true;\n// if (webview) browser.webview = true;\nif(ie){browser.ie=true;browser.version=ie[1];}if(edge){browser.edge=true;browser.version=edge[1];}// It is difficult to detect WeChat in Win Phone precisely, because ua can\n// not be set on win phone. So we do not consider Win Phone.\nif(weChat){browser.weChat=true;}// os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||\n//     (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)));\n// os.phone  = !!(!os.tablet && !os.ipod && (android || iphone || webos ||\n//     (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\\/([\\d.]+)/)) ||\n//     (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))));\nreturn{browser:browser,os:os,node:false,// 原生canvas支持，改极端点了\n// canvasSupported : !(browser.ie && parseFloat(browser.version) < 9)\ncanvasSupported:!!document.createElement('canvas').getContext,svgSupported:typeof SVGRect!=='undefined',// works on most browsers\n// IE10/11 does not support touch event, and MS Edge supports them but not by\n// default, so we dont check navigator.maxTouchPoints for them here.\ntouchEventsSupported:'ontouchstart'in window&&!browser.ie&&!browser.edge,// <http://caniuse.com/#search=pointer%20event>.\npointerEventsSupported:// (1) Firefox supports pointer but not by default, only MS browsers are reliable on pointer\n// events currently. So we dont use that on other browsers unless tested sufficiently.\n// For example, in iOS 13 Mobile Chromium 78, if the touching behavior starts page\n// scroll, the `pointermove` event can not be fired any more. That will break some\n// features like \"pan horizontally to move something and pan vertically to page scroll\".\n// The horizontal pan probably be interrupted by the casually triggered page scroll.\n// (2) Although IE 10 supports pointer event, it use old style and is different from the\n// standard. So we exclude that. (IE 10 is hardly used on touch device)\n'onpointerdown'in window&&(browser.edge||browser.ie&&browser.version>=11),// passiveSupported: detectPassiveSupport()\ndomSupported:typeof document!=='undefined'};}// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection\n// function detectPassiveSupport() {\n//     // Test via a getter in the options object to see if the passive property is accessed\n//     var supportsPassive = false;\n//     try {\n//         var opts = Object.defineProperty({}, 'passive', {\n//             get: function() {\n//                 supportsPassive = true;\n//             }\n//         });\n//         window.addEventListener('testPassive', function() {}, opts);\n//     } catch (e) {\n//     }\n//     return supportsPassive;\n// }\n/**\n * @module zrender/core/util\n */ // 用于处理merge时无法遍历Date等对象的问题\nvar BUILTIN_OBJECT={'[object Function]':1,'[object RegExp]':1,'[object Date]':1,'[object Error]':1,'[object CanvasGradient]':1,'[object CanvasPattern]':1,// For node-canvas\n'[object Image]':1,'[object Canvas]':1};var TYPED_ARRAY={'[object Int8Array]':1,'[object Uint8Array]':1,'[object Uint8ClampedArray]':1,'[object Int16Array]':1,'[object Uint16Array]':1,'[object Int32Array]':1,'[object Uint32Array]':1,'[object Float32Array]':1,'[object Float64Array]':1};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 nativeReduce=arrayProto.reduce;// Avoid assign to an exported variable, for transforming to cjs.\nvar methods={};function $override(name,fn){// Clear ctx instance for different environment\nif(name==='createCanvas'){_ctx=null;}methods[name]=fn;}/**\n * Those data types can be cloned:\n *     Plain object, Array, TypedArray, number, string, null, undefined.\n * Those data types will be assgined using the orginal data:\n *     BUILTIN_OBJECT\n * Instance of user defined class will be cloned to a plain object, without\n * properties in prototype.\n * Other data types is not supported (not sure what will happen).\n *\n * Caution: do not support clone Date, for performance consideration.\n * (There might be a large number of date in `series.data`).\n * So date should not be modified in and out of echarts.\n *\n * @param {*} source\n * @return {*} new\n */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(source.constructor.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;}/**\n * @memberOf module:zrender/core/util\n * @param {*} target\n * @param {*} source\n * @param {boolean} [overwrite=false]\n */function merge(target,source,overwrite){// We should escapse that source is string\n// and enter for ... in ...\nif(!isObject$1(source)||!isObject$1(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$1(sourceProp)&&isObject$1(targetProp)&&!isArray(sourceProp)&&!isArray(targetProp)&&!isDom(sourceProp)&&!isDom(targetProp)&&!isBuiltInObject(sourceProp)&&!isBuiltInObject(targetProp)&&!isPrimitive(sourceProp)&&!isPrimitive(targetProp)){// 如果需要递归覆盖，就递归调用merge\nmerge(targetProp,sourceProp,overwrite);}else if(overwrite||!(key in target)){// 否则只处理overwrite为true，或者在目标对象中没有此属性的情况\n// NOTE，在 target[key] 不存在的时候也是直接覆盖\ntarget[key]=_clone(source[key],true);}}}return target;}/**\n * @param {Array} targetAndSources The first item is target, and the rests are source.\n * @param {boolean} [overwrite=false]\n * @return {*} target\n */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;}/**\n * @param {*} target\n * @param {*} source\n * @memberOf module:zrender/core/util\n */function extend(target,source){for(var key in source){if(source.hasOwnProperty(key)){target[key]=source[key];}}return target;}/**\n * @param {*} target\n * @param {*} source\n * @param {boolean} [overlay=false]\n * @memberOf module:zrender/core/util\n */function defaults(target,source,overlay){for(var key in source){if(source.hasOwnProperty(key)&&(overlay?source[key]!=null:target[key]==null)){target[key]=source[key];}}return target;}var createCanvas=function createCanvas(){return methods.createCanvas();};methods.createCanvas=function(){return document.createElement('canvas');};// FIXME\nvar _ctx;function getContext(){if(!_ctx){// Use util.createCanvas instead of createCanvas\n// because createCanvas may be overwritten in different environment\n_ctx=createCanvas().getContext('2d');}return _ctx;}/**\n * 查询数组中元素的index\n * @memberOf module:zrender/core/util\n */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;}/**\n * 构造类继承关系\n *\n * @memberOf module:zrender/core/util\n * @param {Function} clazz 源类\n * @param {Function} baseClazz 基类\n */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;}/**\n * @memberOf module:zrender/core/util\n * @param {Object|Function} target\n * @param {Object|Function} sorce\n * @param {boolean} overlay\n */function mixin(target,source,overlay){target='prototype'in target?target.prototype:target;source='prototype'in source?source.prototype:source;defaults(target,source,overlay);}/**\n * Consider typed array.\n * @param {Array|TypedArray} data\n */function isArrayLike(data){if(!data){return;}if(typeof data==='string'){return false;}return typeof data.length==='number';}/**\n * 数组或对象遍历\n * @memberOf module:zrender/core/util\n * @param {Object|Array} obj\n * @param {Function} cb\n * @param {*} [context]\n */function each$1(obj,cb,context){if(!(obj&&cb)){return;}if(obj.forEach&&obj.forEach===nativeForEach){obj.forEach(cb,context);}else if(obj.length===+obj.length){for(var i=0,len=obj.length;i<len;i++){cb.call(context,obj[i],i,obj);}}else{for(var key in obj){if(obj.hasOwnProperty(key)){cb.call(context,obj[key],key,obj);}}}}/**\n * 数组映射\n * @memberOf module:zrender/core/util\n * @param {Array} obj\n * @param {Function} cb\n * @param {*} [context]\n * @return {Array}\n */function map(obj,cb,context){if(!(obj&&cb)){return;}if(obj.map&&obj.map===nativeMap){return obj.map(cb,context);}else{var result=[];for(var i=0,len=obj.length;i<len;i++){result.push(cb.call(context,obj[i],i,obj));}return result;}}/**\n * @memberOf module:zrender/core/util\n * @param {Array} obj\n * @param {Function} cb\n * @param {Object} [memo]\n * @param {*} [context]\n * @return {Array}\n */function reduce(obj,cb,memo,context){if(!(obj&&cb)){return;}if(obj.reduce&&obj.reduce===nativeReduce){return obj.reduce(cb,memo,context);}else{for(var i=0,len=obj.length;i<len;i++){memo=cb.call(context,memo,obj[i],i,obj);}return memo;}}/**\n * 数组过滤\n * @memberOf module:zrender/core/util\n * @param {Array} obj\n * @param {Function} cb\n * @param {*} [context]\n * @return {Array}\n */function filter(obj,cb,context){if(!(obj&&cb)){return;}if(obj.filter&&obj.filter===nativeFilter){return obj.filter(cb,context);}else{var result=[];for(var i=0,len=obj.length;i<len;i++){if(cb.call(context,obj[i],i,obj)){result.push(obj[i]);}}return result;}}/**\n * 数组项查找\n * @memberOf module:zrender/core/util\n * @param {Array} obj\n * @param {Function} cb\n * @param {*} [context]\n * @return {*}\n */function find(obj,cb,context){if(!(obj&&cb)){return;}for(var i=0,len=obj.length;i<len;i++){if(cb.call(context,obj[i],i,obj)){return obj[i];}}}/**\n * @memberOf module:zrender/core/util\n * @param {Function} func\n * @param {*} context\n * @return {Function}\n */function bind(func,context){var args=nativeSlice.call(arguments,2);return function(){return func.apply(context,args.concat(nativeSlice.call(arguments)));};}/**\n * @memberOf module:zrender/core/util\n * @param {Function} func\n * @return {Function}\n */function curry(func){var args=nativeSlice.call(arguments,1);return function(){return func.apply(this,args.concat(nativeSlice.call(arguments)));};}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isArray(value){return objToString.call(value)==='[object Array]';}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isFunction$1(value){return typeof value==='function';}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isString(value){return objToString.call(value)==='[object String]';}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isObject$1(value){// Avoid a V8 JIT bug in Chrome 19-20.\n// See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\nvar type=_typeof(value);return type==='function'||!!value&&type==='object';}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isBuiltInObject(value){return!!BUILTIN_OBJECT[objToString.call(value)];}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isTypedArray(value){return!!TYPED_ARRAY[objToString.call(value)];}/**\n * @memberOf module:zrender/core/util\n * @param {*} value\n * @return {boolean}\n */function isDom(value){return _typeof(value)==='object'&&typeof value.nodeType==='number'&&_typeof(value.ownerDocument)==='object';}/**\n * Whether is exactly NaN. Notice isNaN('a') returns true.\n * @param {*} value\n * @return {boolean}\n */function eqNaN(value){/* eslint-disable-next-line no-self-compare */return value!==value;}/**\n * If value1 is not null, then return value1, otherwise judget rest of values.\n * Low performance.\n * @memberOf module:zrender/core/util\n * @return {*} Final value\n */function retrieve(values){for(var i=0,len=arguments.length;i<len;i++){if(arguments[i]!=null){return arguments[i];}}}function retrieve2(value0,value1){return value0!=null?value0:value1;}function retrieve3(value0,value1,value2){return value0!=null?value0:value1!=null?value1:value2;}/**\n * @memberOf module:zrender/core/util\n * @param {Array} arr\n * @param {number} startIndex\n * @param {number} endIndex\n * @return {Array}\n */function slice(){return Function.call.apply(nativeSlice,arguments);}/**\n * Normalize css liked array configuration\n * e.g.\n *  3 => [3, 3, 3, 3]\n *  [4, 2] => [4, 2, 4, 2]\n *  [4, 3, 2] => [4, 3, 2, 3]\n * @param {number|Array.<number>} val\n * @return {Array.<number>}\n */function normalizeCssArray(val){if(typeof val==='number'){return[val,val,val,val];}var len=val.length;if(len===2){// vertical | horizontal\nreturn[val[0],val[1],val[0],val[1]];}else if(len===3){// top | horizontal | bottom\nreturn[val[0],val[1],val[2],val[1]];}return val;}/**\n * @memberOf module:zrender/core/util\n * @param {boolean} condition\n * @param {string} message\n */function assert$1(condition,message){if(!condition){throw new Error(message);}}/**\n * @memberOf module:zrender/core/util\n * @param {string} str string to be trimed\n * @return {string} trimed string\n */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__';/**\n * Set an object as primitive to be ignored traversing children in clone or merge\n */function setAsPrimitive(obj){obj[primitiveKey]=true;}function isPrimitive(obj){return obj[primitiveKey];}/**\n * @constructor\n * @param {Object} obj Only apply `ownProperty`.\n */function HashMap(obj){var isArr=isArray(obj);// Key should not be set on this, otherwise\n// methods get/set/... may be overrided.\nthis.data={};var thisMap=this;obj instanceof HashMap?obj.each(visit):obj&&each$1(obj,visit);function visit(value,key){isArr?thisMap.set(value,key):thisMap.set(key,value);}}HashMap.prototype={constructor:HashMap,// Do not provide `has` method to avoid defining what is `has`.\n// (We usually treat `null` and `undefined` as the same, different\n// from ES6 Map).\nget:function get(key){return this.data.hasOwnProperty(key)?this.data[key]:null;},set:function set(key,value){// Comparing with invocation chaining, `return value` is more commonly\n// used in this case: `var someVal = map.set('a', genVal());`\nreturn this.data[key]=value;},// Although util.each can be performed on this hashMap directly, user\n// should not use the exposed keys, who are prefixed.\neach:function each(cb,context){context!==void 0&&(cb=bind(cb,context));/* eslint-disable guard-for-in */for(var key in this.data){this.data.hasOwnProperty(key)&&cb(this.data[key],key);}/* eslint-enable guard-for-in */},// Do not use this method if performance sensitive.\nremoveKey:function removeKey(key){delete this.data[key];}};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(i=0;i<b.length;i++){newArray[i+offset]=b[i];}return newArray;}function noop(){}var zrUtil=(Object.freeze||Object)({$override:$override,clone:_clone,merge:merge,mergeAll:mergeAll,extend:extend,defaults:defaults,createCanvas:createCanvas,getContext:getContext,indexOf:indexOf,inherits:inherits,mixin:mixin,isArrayLike:isArrayLike,each:each$1,map:map,reduce:reduce,filter:filter,find:find,bind:bind,curry:curry,isArray:isArray,isFunction:isFunction$1,isString:isString,isObject:isObject$1,isBuiltInObject:isBuiltInObject,isTypedArray:isTypedArray,isDom:isDom,eqNaN:eqNaN,retrieve:retrieve,retrieve2:retrieve2,retrieve3:retrieve3,slice:slice,normalizeCssArray:normalizeCssArray,assert:assert$1,trim:trim,setAsPrimitive:setAsPrimitive,isPrimitive:isPrimitive,createHashMap:createHashMap,concatArray:concatArray,noop:noop});/* global Float32Array */var ArrayCtor=typeof Float32Array==='undefined'?Array:Float32Array;/**\n * 创建一个向量\n * @param {number} [x=0]\n * @param {number} [y=0]\n * @return {Vector2}\n */function create(x,y){var out=new ArrayCtor(2);if(x==null){x=0;}if(y==null){y=0;}out[0]=x;out[1]=y;return out;}/**\n * 复制向量数据\n * @param {Vector2} out\n * @param {Vector2} v\n * @return {Vector2}\n */function copy(out,v){out[0]=v[0];out[1]=v[1];return out;}/**\n * 克隆一个向量\n * @param {Vector2} v\n * @return {Vector2}\n */function clone$1(v){var out=new ArrayCtor(2);out[0]=v[0];out[1]=v[1];return out;}/**\n * 设置向量的两个项\n * @param {Vector2} out\n * @param {number} a\n * @param {number} b\n * @return {Vector2} 结果\n */function set(out,a,b){out[0]=a;out[1]=b;return out;}/**\n * 向量相加\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n */function add(out,v1,v2){out[0]=v1[0]+v2[0];out[1]=v1[1]+v2[1];return out;}/**\n * 向量缩放后相加\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n * @param {number} a\n */function scaleAndAdd(out,v1,v2,a){out[0]=v1[0]+v2[0]*a;out[1]=v1[1]+v2[1]*a;return out;}/**\n * 向量相减\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n */function sub(out,v1,v2){out[0]=v1[0]-v2[0];out[1]=v1[1]-v2[1];return out;}/**\n * 向量长度\n * @param {Vector2} v\n * @return {number}\n */function len(v){return Math.sqrt(lenSquare(v));}var length=len;// jshint ignore:line\n/**\n * 向量长度平方\n * @param {Vector2} v\n * @return {number}\n */function lenSquare(v){return v[0]*v[0]+v[1]*v[1];}var lengthSquare=lenSquare;/**\n * 向量乘法\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n */function mul(out,v1,v2){out[0]=v1[0]*v2[0];out[1]=v1[1]*v2[1];return out;}/**\n * 向量除法\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n */function div(out,v1,v2){out[0]=v1[0]/v2[0];out[1]=v1[1]/v2[1];return out;}/**\n * 向量点乘\n * @param {Vector2} v1\n * @param {Vector2} v2\n * @return {number}\n */function dot(v1,v2){return v1[0]*v2[0]+v1[1]*v2[1];}/**\n * 向量缩放\n * @param {Vector2} out\n * @param {Vector2} v\n * @param {number} s\n */function scale(out,v,s){out[0]=v[0]*s;out[1]=v[1]*s;return out;}/**\n * 向量归一化\n * @param {Vector2} out\n * @param {Vector2} v\n */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;}/**\n * 计算向量间距离\n * @param {Vector2} v1\n * @param {Vector2} v2\n * @return {number}\n */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;/**\n * 向量距离平方\n * @param {Vector2} v1\n * @param {Vector2} v2\n * @return {number}\n */function distanceSquare(v1,v2){return(v1[0]-v2[0])*(v1[0]-v2[0])+(v1[1]-v2[1])*(v1[1]-v2[1]);}var distSquare=distanceSquare;/**\n * 求负向量\n * @param {Vector2} out\n * @param {Vector2} v\n */function negate(out,v){out[0]=-v[0];out[1]=-v[1];return out;}/**\n * 插值两个点\n * @param {Vector2} out\n * @param {Vector2} v1\n * @param {Vector2} v2\n * @param {number} t\n */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;}/**\n * 矩阵左乘向量\n * @param {Vector2} out\n * @param {Vector2} v\n * @param {Vector2} m\n */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;}/**\n * 求两个向量最小值\n * @param  {Vector2} out\n * @param  {Vector2} v1\n * @param  {Vector2} v2\n */function min(out,v1,v2){out[0]=Math.min(v1[0],v2[0]);out[1]=Math.min(v1[1],v2[1]);return out;}/**\n * 求两个向量最大值\n * @param  {Vector2} out\n * @param  {Vector2} v1\n * @param  {Vector2} v2\n */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=(Object.freeze||Object)({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});// TODO Draggable for group\n// FIXME Draggable on element which has parent rotation or scale\nfunction Draggable(){this.on('mousedown',this._dragStart,this);this.on('mousemove',this._drag,this);this.on('mouseup',this._dragEnd,this);// `mosuemove` and `mouseup` can be continue to fire when dragging.\n// See [Drag outside] in `Handler.js`. So we do not need to trigger\n// `_dragEnd` when globalout. That would brings better user experience.\n// this.on('globalout', this._dragEnd, this);\n// this._dropTarget = null;\n// this._draggingTarget = null;\n// this._x = 0;\n// this._y = 0;\n}Draggable.prototype={constructor:Draggable,_dragStart:function _dragStart(e){var draggingTarget=e.target;// Find if there is draggable in the ancestor\nwhile(draggingTarget&&!draggingTarget.draggable){draggingTarget=draggingTarget.parent;}if(draggingTarget){this._draggingTarget=draggingTarget;draggingTarget.dragging=true;this._x=e.offsetX;this._y=e.offsetY;this.dispatchToElement(param(draggingTarget,e),'dragstart',e.event);}},_drag:function _drag(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.dispatchToElement(param(draggingTarget,e),'drag',e.event);var dropTarget=this.findHover(x,y,draggingTarget).target;var lastDropTarget=this._dropTarget;this._dropTarget=dropTarget;if(draggingTarget!==dropTarget){if(lastDropTarget&&dropTarget!==lastDropTarget){this.dispatchToElement(param(lastDropTarget,e),'dragleave',e.event);}if(dropTarget&&dropTarget!==lastDropTarget){this.dispatchToElement(param(dropTarget,e),'dragenter',e.event);}}}},_dragEnd:function _dragEnd(e){var draggingTarget=this._draggingTarget;if(draggingTarget){draggingTarget.dragging=false;}this.dispatchToElement(param(draggingTarget,e),'dragend',e.event);if(this._dropTarget){this.dispatchToElement(param(this._dropTarget,e),'drop',e.event);}this._draggingTarget=null;this._dropTarget=null;}};function param(target,e){return{target:target,topTarget:e&&e.topTarget};}/**\n * Event Mixin\n * @module zrender/mixin/Eventful\n * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)\n *         pissang (https://www.github.com/pissang)\n */var arrySlice=Array.prototype.slice;/**\n * Event dispatcher.\n *\n * @alias module:zrender/mixin/Eventful\n * @constructor\n * @param {Object} [eventProcessor] The object eventProcessor is the scope when\n *        `eventProcessor.xxx` called.\n * @param {Function} [eventProcessor.normalizeQuery]\n *        param: {string|Object} Raw query.\n *        return: {string|Object} Normalized query.\n * @param {Function} [eventProcessor.filter] Event will be dispatched only\n *        if it returns `true`.\n *        param: {string} eventType\n *        param: {string|Object} query\n *        return: {boolean}\n * @param {Function} [eventProcessor.afterTrigger] Called after all handlers called.\n *        param: {string} eventType\n */var Eventful=function Eventful(eventProcessor){this._$handlers={};this._$eventProcessor=eventProcessor;};Eventful.prototype={constructor:Eventful,/**\n     * The handler can only be triggered once, then removed.\n     *\n     * @param {string} event The event name.\n     * @param {string|Object} [query] Condition used on event filter.\n     * @param {Function} handler The event handler.\n     * @param {Object} context\n     */one:function one(event,query,handler,context){return _on(this,event,query,handler,context,true);},/**\n     * Bind a handler.\n     *\n     * @param {string} event The event name.\n     * @param {string|Object} [query] Condition used on event filter.\n     * @param {Function} handler The event handler.\n     * @param {Object} [context]\n     */on:function on(event,query,handler,context){return _on(this,event,query,handler,context,false);},/**\n     * Whether any handler has bound.\n     *\n     * @param  {string}  event\n     * @return {boolean}\n     */isSilent:function isSilent(event){var _h=this._$handlers;return!_h[event]||!_h[event].length;},/**\n     * Unbind a event.\n     *\n     * @param {string} [event] The event name.\n     *        If no `event` input, \"off\" all listeners.\n     * @param {Function} [handler] The event handler.\n     *        If no `handler` input, \"off\" all listeners of the `event`.\n     */off:function off(event,handler){var _h=this._$handlers;if(!event){this._$handlers={};return this;}if(handler){if(_h[event]){var newList=[];for(var i=0,l=_h[event].length;i<l;i++){if(_h[event][i].h!==handler){newList.push(_h[event][i]);}}_h[event]=newList;}if(_h[event]&&_h[event].length===0){delete _h[event];}}else{delete _h[event];}return this;},/**\n     * Dispatch a event.\n     *\n     * @param {string} type The event name.\n     */trigger:function trigger(type){var _h=this._$handlers[type];var eventProcessor=this._$eventProcessor;if(_h){var args=arguments;var argLen=args.length;if(argLen>3){args=arrySlice.call(args,1);}var len=_h.length;for(var i=0;i<len;){var hItem=_h[i];if(eventProcessor&&eventProcessor.filter&&hItem.query!=null&&!eventProcessor.filter(type,hItem.query)){i++;continue;}// Optimize advise from backbone\nswitch(argLen){case 1:hItem.h.call(hItem.ctx);break;case 2:hItem.h.call(hItem.ctx,args[1]);break;case 3:hItem.h.call(hItem.ctx,args[1],args[2]);break;default:// have more than 2 given arguments\nhItem.h.apply(hItem.ctx,args);break;}if(hItem.one){_h.splice(i,1);len--;}else{i++;}}}eventProcessor&&eventProcessor.afterTrigger&&eventProcessor.afterTrigger(type);return this;},/**\n     * Dispatch a event with context, which is specified at the last parameter.\n     *\n     * @param {string} type The event name.\n     */triggerWithContext:function triggerWithContext(type){var _h=this._$handlers[type];var eventProcessor=this._$eventProcessor;if(_h){var args=arguments;var argLen=args.length;if(argLen>4){args=arrySlice.call(args,1,args.length-1);}var ctx=args[args.length-1];var len=_h.length;for(var i=0;i<len;){var hItem=_h[i];if(eventProcessor&&eventProcessor.filter&&hItem.query!=null&&!eventProcessor.filter(type,hItem.query)){i++;continue;}// Optimize advise from backbone\nswitch(argLen){case 1:hItem.h.call(ctx);break;case 2:hItem.h.call(ctx,args[1]);break;case 3:hItem.h.call(ctx,args[1],args[2]);break;default:// have more than 2 given arguments\nhItem.h.apply(ctx,args);break;}if(hItem.one){_h.splice(i,1);len--;}else{i++;}}}eventProcessor&&eventProcessor.afterTrigger&&eventProcessor.afterTrigger(type);return this;}};function normalizeQuery(host,query){var eventProcessor=host._$eventProcessor;if(query!=null&&eventProcessor&&eventProcessor.normalizeQuery){query=eventProcessor.normalizeQuery(query);}return query;}function _on(eventful,event,query,handler,context,isOnce){var _h=eventful._$handlers;if(typeof query==='function'){context=handler;handler=query;query=null;}if(!handler||!event){return eventful;}query=normalizeQuery(eventful,query);if(!_h[event]){_h[event]=[];}for(var i=0;i<_h[event].length;i++){if(_h[event][i].h===handler){return eventful;}}var wrap={h:handler,one:isOnce,query:query,ctx:context||eventful,// FIXME\n// Do not publish this feature util it is proved that it makes sense.\ncallAtLast: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 eventful;}/**\n * The algoritm is learnt from\n * https://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/\n * And we made some optimization for matrix inversion.\n * Other similar approaches:\n * \"cv::getPerspectiveTransform\", \"Direct Linear Transformation\".\n */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){// In this case the colMask must be like: `11101111`. We can find the place of `0`.\nvar 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]// det(subMatrix(0, j))\n*determinant(rows,rank-1,subRowStart,subRowMask,colMask|colTag,detCache);colLocalIdx++;}}detCache[cacheKey]=sum;return sum;}/**\n * Usage:\n * ```js\n * var transformer = buildTransformer(\n *     [10, 44, 100, 44, 100, 300, 10, 300],\n *     [50, 54, 130, 14, 140, 330, 14, 220]\n * );\n * var out = [];\n * transformer && transformer([11, 33], out);\n * ```\n *\n * Notice: `buildTransformer` may take more than 10ms in some Android device.\n *\n * @param {Array.<number>} src source four points, [x0, y0, x1, y1, x2, y2, x3, y3]\n * @param {Array.<number>} dest destination four points, [x0, y0, x1, y1, x2, y2, x3, y3]\n * @return {Function} transformer If fail, return null/undefined.\n */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){// can not make transformer when and only when\n// any three of the markers are collinear.\nreturn;}// `invert(mA) * dest`, that is, `adj(mA) / det * dest`.\nvar 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)*// det(subMatrix(i, j))\ndeterminant(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$1=[];/**\n * Transform \"local coord\" from `elFrom` to `elTarget`.\n * \"local coord\": the coord based on the input `el`. The origin point is at\n *     the position of \"left: 0; top: 0;\" in the `el`.\n *\n * Support when CSS transform is used.\n *\n * Having the `out` (that is, `[outX, outY]`), we can create an DOM element\n * and set the CSS style as \"left: outX; top: outY;\" and append it to `elTarge`\n * to locate the element.\n *\n * For example, this code below positions a child of `document.body` on the event\n * point, no matter whether `body` has `margin`/`paddin`/`transfrom`/... :\n * ```js\n * transformLocalCoord(out, container, document.body, event.offsetX, event.offsetY);\n * if (!eqNaN(out[0])) {\n *     // Then locate the tip element on the event point.\n *     var tipEl = document.createElement('div');\n *     tipEl.style.cssText = 'position: absolute; left:' + out[0] + ';top:' + out[1] + ';';\n *     document.body.appendChild(tipEl);\n * }\n * ```\n *\n * Notice: In some env this method is not supported. If called, `out` will be `[NaN, NaN]`.\n *\n * @param {Array.<number>} out [inX: number, inY: number] The output..\n *        If can not transform, `out` will not be modified but return `false`.\n * @param {HTMLElement} elFrom The `[inX, inY]` is based on elFrom.\n * @param {HTMLElement} elTarget The `out` is based on elTarget.\n * @param {number} inX\n * @param {number} inY\n * @return {boolean} Whether transform successfully.\n */function transformLocalCoord(out,elFrom,elTarget,inX,inY){return transformCoordWithViewport(_calcOut$1,elFrom,inX,inY,true)&&transformCoordWithViewport(out,elTarget,_calcOut$1[0],_calcOut$1[1]);}/**\n * Transform between a \"viewport coord\" and a \"local coord\".\n * \"viewport coord\": the coord based on the left-top corner of the viewport\n *     of the browser.\n * \"local coord\": the coord based on the input `el`. The origin point is at\n *     the position of \"left: 0; top: 0;\" in the `el`.\n *\n * Support the case when CSS transform is used on el.\n *\n * @param {Array.<number>} out [inX: number, inY: number] The output. If `inverse: false`,\n *        it represents \"local coord\", otherwise \"vireport coord\".\n *        If can not transform, `out` will not be modified but return `false`.\n * @param {HTMLElement} el The \"local coord\" is based on the `el`, see comment above.\n * @param {number} inX If `inverse: false`,\n *        it represents \"vireport coord\", otherwise \"local coord\".\n * @param {number} inY If `inverse: false`,\n *        it represents \"vireport coord\", otherwise \"local coord\".\n * @param {boolean} [inverse=false]\n *        `true`: from \"viewport coord\" to \"local coord\".\n *        `false`: from \"local coord\" to \"viewport coord\".\n * @return {boolean} Whether transform successfully.\n */function transformCoordWithViewport(out,el,inX,inY,inverse){if(el.getBoundingClientRect&&env$1.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',// 'width: 5px',\n// 'height: 5px',\npropLR[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 oldCoordTheSame=true;var srcCoords=[];var destCoords=[];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);}// Cache to avoid time consuming of `buildTransformer`.\nreturn oldCoordTheSame&&transformer?transformer:(saved.srcCoords=srcCoords,saved[transformerName]=inverse?buildTransformer(destCoords,srcCoords):buildTransformer(srcCoords,destCoords));}function isCanvasEl(el){return el.nodeName.toUpperCase()==='CANVAS';}/**\n * Utilities for mouse or touch events.\n */var isDomLevel2=typeof window!=='undefined'&&!!window.addEventListener;var MOUSE_EVENT_REG=/^(?:mouse|pointer|contextmenu|drag|drop)|click/;var _calcOut=[];/**\n * Get the `zrX` and `zrY`, which are relative to the top-left of\n * the input `el`.\n * CSS transform (2D & 3D) is supported.\n *\n * The strategy to fetch the coords:\n * + If `calculate` is not set as `true`, users of this method should\n * ensure that `el` is the same or the same size & location as `e.target`.\n * Otherwise the result coords are probably not expected. Because we\n * firstly try to get coords from e.offsetX/e.offsetY.\n * + If `calculate` is set as `true`, the input `el` can be any element\n * and we force to calculate the coords based on `el`.\n * + The input `el` should be positionable (not position:static).\n *\n * The force `calculate` can be used in case like:\n * When mousemove event triggered on ec tooltip, `e.target` is not `el`(zr painter.dom).\n *\n * @param {HTMLElement} el DOM element.\n * @param {Event} e Mouse event or touch event.\n * @param {Object} out Get `out.zrX` and `out.zrY` as the result.\n * @param {boolean} [calculate=false] Whether to force calculate\n *        the coordinates but not use ones provided by browser.\n */function clientToLocal(el,e,out,calculate){out=out||{};// According to the W3C Working Draft, offsetX and offsetY should be relative\n// to the padding edge of the target element. The only browser using this convention\n// is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does\n// not support the properties.\n// (see http://www.jacklmoore.com/notes/mouse-position/)\n// In zr painter.dom, padding edge equals to border edge.\nif(calculate||!env$1.canvasSupported){calculateZrXY(el,e,out);}// Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned\n// ancestor element, so we should make sure el is positioned (e.g., not position:static).\n// BTW1, Webkit don't return the same results as FF in non-simple cases (like add\n// zoom-factor, overflow / opacity layers, transforms ...)\n// BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.\n// <https://bugs.jquery.com/ticket/8523#comment:14>\n// BTW3, In ff, offsetX/offsetY is always 0.\nelse if(env$1.browser.firefox&&e.layerX!=null&&e.layerX!==e.offsetX){out.zrX=e.layerX;out.zrY=e.layerY;}// For IE6+, chrome, safari, opera. (When will ff support offsetX?)\nelse if(e.offsetX!=null){out.zrX=e.offsetX;out.zrY=e.offsetY;}// For some other device, e.g., IOS safari.\nelse{calculateZrXY(el,e,out);}return out;}function calculateZrXY(el,e,out){// BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.\nif(env$1.domSupported&&el.getBoundingClientRect){var ex=e.clientX;var ey=e.clientY;if(isCanvasEl(el)){// Original approach, which do not support CSS transform.\n// marker can not be locationed in a canvas container\n// (getBoundingClientRect is always 0). We do not support\n// that input a pre-created canvas to zr while using css\n// transform in iOS.\nvar box=el.getBoundingClientRect();out.zrX=ex-box.left;out.zrY=ey-box.top;return;}else{if(transformCoordWithViewport(_calcOut,el,ex,ey)){out.zrX=_calcOut[0];out.zrY=_calcOut[1];return;}}}out.zrX=out.zrY=0;}/**\n * Find native event compat for legency IE.\n * Should be called at the begining of a native event listener.\n *\n * @param {Event} [e] Mouse event or touch event or pointer event.\n *        For lagency IE, we use `window.event` is used.\n * @return {Event} The native event.\n */function getNativeEvent(e){return e||window.event;}/**\n * Normalize the coordinates of the input event.\n *\n * Get the `e.zrX` and `e.zrY`, which are relative to the top-left of\n * the input `el`.\n * Get `e.zrDelta` if using mouse wheel.\n * Get `e.which`, see the comment inside this function.\n *\n * Do not calculate repeatly if `zrX` and `zrY` already exist.\n *\n * Notice: see comments in `clientToLocal`. check the relationship\n * between the result coords and the parameters `el` and `calculate`.\n *\n * @param {HTMLElement} el DOM element.\n * @param {Event} [e] See `getNativeEvent`.\n * @param {boolean} [calculate=false] Whether to force calculate\n *        the coordinates but not use ones provided by browser.\n * @return {UIEvent} The normalized native UIEvent.\n */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);e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;}else{var touch=eventType!=='touchend'?e.targetTouches[0]:e.changedTouches[0];touch&&clientToLocal(el,touch,e,calculate);}// Add which for click: 1 === left; 2 === middle; 3 === right; otherwise: 0;\n// See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js\n// If e.which has been defined, it may be readonly,\n// see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which\nvar 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;}// [Caution]: `e.which` from browser is not always reliable. For example,\n// when press left button and `mousemove (pointermove)` in Edge, the `e.which`\n// is 65536 and the `e.button` is -1. But the `mouseup (pointerup)` and\n// `mousedown (pointerdown)` is the same as Chrome does.\nreturn e;}/**\n * @param {HTMLElement} el\n * @param {string} name\n * @param {Function} handler\n * @param {Object|boolean} opt If boolean, means `opt.capture`\n * @param {boolean} [opt.capture=false]\n * @param {boolean} [opt.passive=false]\n */function addEventListener(el,name,handler,opt){if(isDomLevel2){// Reproduct the console warning:\n// [Violation] Added non-passive event listener to a scroll-blocking <some> event.\n// Consider marking event handler as 'passive' to make the page more responsive.\n// Just set console log level: verbose in chrome dev tool.\n// then the warning log will be printed when addEventListener called.\n// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// We have not yet found a neat way to using passive. Because in zrender the dom event\n// listener delegate all of the upper events of element. Some of those events need\n// to prevent default. For example, the feature `preventDefaultMouseMove` of echarts.\n// Before passive can be adopted, these issues should be considered:\n// (1) Whether and how a zrender user specifies an event listener passive. And by default,\n// passive or not.\n// (2) How to tread that some zrender event listener is passive, and some is not. If\n// we use other way but not preventDefault of mousewheel and touchmove, browser\n// compatibility should be handled.\n// var opts = (env.passiveSupported && name === 'mousewheel')\n//     ? {passive: true}\n//     // By default, the third param of el.addEventListener is `capture: false`.\n//     : void 0;\n// el.addEventListener(name, handler /* , opts */);\nel.addEventListener(name,handler,opt);}else{// For simplicity, do not implement `setCapture` for IE9-.\nel.attachEvent('on'+name,handler);}}/**\n * Parameter are the same as `addEventListener`.\n *\n * Notice that if a listener is registered twice, one with capture and one without,\n * remove each one separately. Removal of a capturing listener does not affect a\n * non-capturing version of the same listener, and vice versa.\n */function removeEventListener(el,name,handler,opt){if(isDomLevel2){el.removeEventListener(name,handler,opt);}else{el.detachEvent('on'+name,handler);}}/**\n * preventDefault and stopPropagation.\n * Notice: do not use this method in zrender. It can only be\n * used by upper applications if necessary.\n *\n * @param {Event} e A mouse or touch event.\n */var stop=isDomLevel2?function(e){e.preventDefault();e.stopPropagation();e.cancelBubble=true;}:function(e){e.returnValue=false;e.cancelBubble=true;};/**\n * This method only works for mouseup and mousedown. The functionality is restricted\n * for fault tolerance, See the `e.which` compatibility above.\n *\n * @param {MouseEvent} e\n * @return {boolean}\n */function isMiddleOrRightButtonOnMouseUpDown(e){return e.which===2||e.which===3;}/**\n * To be removed.\n * @deprecated\n */ /**\n * Only implements needed gestures for mobile.\n */var GestureMgr=function GestureMgr(){/**\n     * @private\n     * @type {Array.<Object>}\n     */this._track=[];};GestureMgr.prototype={constructor:GestureMgr,recognize:function recognize(event,target,root){this._doTrack(event,target,root);return this._recognize(event);},clear:function clear(){this._track.length=0;return this;},_doTrack:function _doTrack(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);},_recognize:function _recognize(event){for(var eventName in recognizers){if(recognizers.hasOwnProperty(eventName)){var gestureInfo=recognizers[eventName](this._track,event);if(gestureInfo){return gestureInfo;}}}}};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 pinch(track,event){var trackLen=track.length;if(!trackLen){return;}var pinchEnd=(track[trackLen-1]||{}).points;var pinchPre=(track[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:track[0].target,event:event};}}// Only pinch currently.\n};/**\n * [The interface between `Handler` and `HandlerProxy`]:\n *\n * The default `HandlerProxy` only support the common standard web environment\n * (e.g., standalone browser, headless browser, embed browser in mobild APP, ...).\n * But `HandlerProxy` can be replaced to support more non-standard environment\n * (e.g., mini app), or to support more feature that the default `HandlerProxy`\n * not provided (like echarts-gl did).\n * So the interface between `Handler` and `HandlerProxy` should be stable. Do not\n * make break changes util inevitable. The interface include the public methods\n * of `Handler` and the events listed in `handlerNames` below, by which `HandlerProxy`\n * drives `Handler`.\n */ /**\n * [Drag outside]:\n *\n * That is, triggering `mousemove` and `mouseup` event when the pointer is out of the\n * zrender area when dragging. That is important for the improvement of the user experience\n * when dragging something near the boundary without being terminated unexpectedly.\n *\n * We originally consider to introduce new events like `pagemovemove` and `pagemouseup`\n * to resolve this issue. But some drawbacks of it is described in\n * https://github.com/ecomfe/zrender/pull/536#issuecomment-560286899\n *\n * Instead, we referenced the specifications:\n * https://www.w3.org/TR/touch-events/#the-touchmove-event\n * https://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#event-type-mousemove\n * where the the mousemove/touchmove can be continue to fire if the user began a drag\n * operation and the pointer has left the boundary. (for the mouse event, browsers\n * only do it on `document` and when the pointer has left the boundary of the browser.)\n *\n * So the default `HandlerProxy` supports this feature similarly: if it is in the dragging\n * state (see `pointerCapture` in `HandlerProxy`), the `mousemove` and `mouseup` continue\n * to fire until release the pointer. That is implemented by listen to those event on\n * `document`.\n * If we implement some other `HandlerProxy` only for touch device, that would be easier.\n * The touch event support this feature by default.\n *\n * Note:\n * There might be some cases that the mouse event can not be\n * received on `document`. For example,\n * (A) `useCapture` is not supported and some user defined event listeners on the ancestor\n * of zr dom throw Error .\n * (B) `useCapture` is not supported Some user defined event listeners on the ancestor of\n * zr dom call `stopPropagation`.\n * In these cases, the `mousemove` event might be keep triggered event\n * if the mouse is released. We try to reduce the side-effect in those cases.\n * That is, do nothing (especially, `findHover`) in those cases. See `isOutsideBoundary`.\n *\n * Note:\n * If `HandlerProxy` listens to `document` with `useCapture`, `HandlerProxy` needs to\n * make sure `stopPropagation` and `preventDefault` doing nothing if and only if the event\n * target is not zrender dom. Becuase it is dangerous to enable users to call them in\n * `document` capture phase to prevent the propagation to any listener of the webpage.\n * But they are needed to work when the pointer inside the zrender dom.\n */var SILENT='silent';function makeEventPacket(eveType,targetInfo,event){return{type:eveType,event:event,// target can only be an element that is not silent.\ntarget:targetInfo.target,// topTarget can be a silent element.\ntopTarget: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);}function EmptyProxy(){}EmptyProxy.prototype.dispose=function(){};var handlerNames=['click','dblclick','mousewheel','mouseout','mouseup','mousedown','mousemove','contextmenu'];/**\n * @alias module:zrender/Handler\n * @constructor\n * @extends module:zrender/mixin/Eventful\n * @param {module:zrender/Storage} storage Storage instance.\n * @param {module:zrender/Painter} painter Painter instance.\n * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance.\n * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()).\n */var Handler=function Handler(storage,painter,proxy,painterRoot){Eventful.call(this);this.storage=storage;this.painter=painter;this.painterRoot=painterRoot;proxy=proxy||new EmptyProxy();/**\n     * Proxy of event. can be Dom, WebGLSurface, etc.\n     */this.proxy=null;/**\n     * {target, topTarget, x, y}\n     * @private\n     * @type {Object}\n     */this._hovered={};/**\n     * @private\n     * @type {Date}\n     */this._lastTouchMoment;/**\n     * @private\n     * @type {number}\n     */this._lastX;/**\n     * @private\n     * @type {number}\n     */this._lastY;/**\n     * @private\n     * @type {module:zrender/core/GestureMgr}\n     */this._gestureMgr;Draggable.call(this);this.setHandlerProxy(proxy);};Handler.prototype={constructor:Handler,setHandlerProxy:function setHandlerProxy(proxy){if(this.proxy){this.proxy.dispose();}if(proxy){each$1(handlerNames,function(name){proxy.on&&proxy.on(name,this[name],this);},this);// Attach handler\nproxy.handler=this;}this.proxy=proxy;},mousemove:function mousemove(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 is removed from zr (detected by '__zr') by some API call\n// (like 'setOption' or 'dispatchAction') in event handlers, we should find\n// lastHovered again here. Otherwise 'mouseout' can not be triggered normally.\n// See #6198.\nif(lastHoveredTarget&&!lastHoveredTarget.__zr){lastHovered=this.findHover(lastHovered.x,lastHovered.y);lastHoveredTarget=lastHovered.target;}var hovered=this._hovered=isOutside?{x:x,y:y}:this.findHover(x,y);var hoveredTarget=hovered.target;var proxy=this.proxy;proxy.setCursor&&proxy.setCursor(hoveredTarget?hoveredTarget.cursor:'default');// Mouse out on previous hovered element\nif(lastHoveredTarget&&hoveredTarget!==lastHoveredTarget){this.dispatchToElement(lastHovered,'mouseout',event);}// Mouse moving on one element\nthis.dispatchToElement(hovered,'mousemove',event);// Mouse over on a new element\nif(hoveredTarget&&hoveredTarget!==lastHoveredTarget){this.dispatchToElement(hovered,'mouseover',event);}},mouseout:function mouseout(event){var eventControl=event.zrEventControl;var zrIsToLocalDOM=event.zrIsToLocalDOM;if(eventControl!=='only_globalout'){this.dispatchToElement(this._hovered,'mouseout',event);}if(eventControl!=='no_globalout'){// FIXME: if the pointer moving from the extra doms to realy \"outside\",\n// the `globalout` should have been triggered. But currently not.\n!zrIsToLocalDOM&&this.trigger('globalout',{type:'globalout',event:event});}},/**\n     * Resize\n     */resize:function resize(event){this._hovered={};},/**\n     * Dispatch event\n     * @param {string} eventName\n     * @param {event=} eventArgs\n     */dispatch:function dispatch(eventName,eventArgs){var handler=this[eventName];handler&&handler.call(this,eventArgs);},/**\n     * Dispose\n     */dispose:function dispose(){this.proxy.dispose();this.storage=this.proxy=this.painter=null;},/**\n     * 设置默认的cursor style\n     * @param {string} [cursorStyle='default'] 例如 crosshair\n     */setCursorStyle:function setCursorStyle(cursorStyle){var proxy=this.proxy;proxy.setCursor&&proxy.setCursor(cursorStyle);},/**\n     * 事件分发代理\n     *\n     * @private\n     * @param {Object} targetInfo {target, topTarget} 目标图形元素\n     * @param {string} eventName 事件名称\n     * @param {Object} event 事件对象\n     */dispatchToElement:function dispatchToElement(targetInfo,eventName,event){targetInfo=targetInfo||{};var el=targetInfo.target;if(el&&el.silent){return;}var eventHandler='on'+eventName;var eventPacket=makeEventPacket(eventName,targetInfo,event);while(el){el[eventHandler]&&(eventPacket.cancelBubble=el[eventHandler].call(el,eventPacket));el.trigger(eventName,eventPacket);el=el.parent;if(eventPacket.cancelBubble){break;}}if(!eventPacket.cancelBubble){// 冒泡到顶级 zrender 对象\nthis.trigger(eventName,eventPacket);// 分发事件到用户自定义层\n// 用户有可能在全局 click 事件中 dispose，所以需要判断下 painter 是否存在\nthis.painter&&this.painter.eachOtherLayer(function(layer){if(typeof layer[eventHandler]==='function'){layer[eventHandler].call(layer,eventPacket);}if(layer.trigger){layer.trigger(eventName,eventPacket);}});}},/**\n     * @private\n     * @param {number} x\n     * @param {number} y\n     * @param {module:zrender/graphic/Displayable} exclude\n     * @return {model:zrender/Element}\n     * @method\n     */findHover:function findHover(x,y,exclude){var list=this.storage.getDisplayList();var out={x:x,y:y};for(var i=list.length-1;i>=0;i--){var hoverCheckResult;if(list[i]!==exclude// getDisplayList may include ignored item in VML mode\n&&!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;},processGesture:function processGesture(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();// Do not do any preventDefault here. Upper application do that if necessary.\nif(gestureInfo){var type=gestureInfo.type;event.gestureEvent=type;this.dispatchToElement({target:gestureInfo.target},type,gestureInfo.event);}}};// Common handlers\neach$1(['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){// Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover\nhovered=this.findHover(x,y);hoveredTarget=hovered.target;}if(name==='mousedown'){this._downEl=hoveredTarget;this._downPoint=[event.zrX,event.zrY];// In case click triggered before mouseup\nthis._upEl=hoveredTarget;}else if(name==='mouseup'){this._upEl=hoveredTarget;}else if(name==='click'){if(this._downEl!==this._upEl// Original click event is triggered on the whole canvas element,\n// including the case that `mousedown` - `mousemove` - `mouseup`,\n// which should be filtered, otherwise it will bring trouble to\n// pan and zoom.\n||!this._downPoint// Arbitrary value\n||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;while(el){// If clipped by ancestor.\n// FIXME: If clipPath has neither stroke nor fill,\n// el.clipPath.contain(x, y) will always return false.\nif(el.clipPath&&!el.clipPath.contain(x,y)){return false;}if(el.silent){isSilent=true;}el=el.parent;}return isSilent?SILENT:true;}return false;}/**\n * See [Drag outside].\n */function isOutsideBoundary(handlerInstance,x,y){var painter=handlerInstance.painter;return x<0||x>painter.getWidth()||y<0||y>painter.getHeight();}mixin(Handler,Eventful);mixin(Handler,Draggable);/**\n * 3x2矩阵操作类\n * @exports zrender/tool/matrix\n */ /* global Float32Array */var ArrayCtor$1=typeof Float32Array==='undefined'?Array:Float32Array;/**\n * Create a identity matrix.\n * @return {Float32Array|Array.<number>}\n */function create$1(){var out=new ArrayCtor$1(6);identity(out);return out;}/**\n * 设置矩阵为单位矩阵\n * @param {Float32Array|Array.<number>} out\n */function identity(out){out[0]=1;out[1]=0;out[2]=0;out[3]=1;out[4]=0;out[5]=0;return out;}/**\n * 复制矩阵\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} m\n */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;}/**\n * 矩阵相乘\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} m1\n * @param {Float32Array|Array.<number>} m2\n */function mul$1(out,m1,m2){// Consider matrix.mul(m, m2, m);\n// where out is the same as m2.\n// So use temp variable to escape error.\nvar 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;}/**\n * 平移变换\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} a\n * @param {Float32Array|Array.<number>} v\n */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;}/**\n * 旋转变换\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} a\n * @param {number} rad\n */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;}/**\n * 缩放变换\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} a\n * @param {Float32Array|Array.<number>} v\n */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;}/**\n * 求逆矩阵\n * @param {Float32Array|Array.<number>} out\n * @param {Float32Array|Array.<number>} a\n */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;}/**\n * Clone a new matrix.\n * @param {Float32Array|Array.<number>} a\n */function clone$2(a){var b=create$1();copy$1(b,a);return b;}var matrix=(Object.freeze||Object)({create:create$1,identity:identity,copy:copy$1,mul:mul$1,translate:translate,rotate:rotate,scale:scale$1,invert:invert,clone:clone$2});/**\n * 提供变换扩展\n * @module zrender/mixin/Transformable\n * @author pissang (https://www.github.com/pissang)\n */var mIdentity=identity;var EPSILON=5e-5;function isNotAroundZero(val){return val>EPSILON||val<-EPSILON;}/**\n * @alias module:zrender/mixin/Transformable\n * @constructor\n */var Transformable=function Transformable(opts){opts=opts||{};// If there are no given position, rotation, scale\nif(!opts.position){/**\n         * 平移\n         * @type {Array.<number>}\n         * @default [0, 0]\n         */this.position=[0,0];}if(opts.rotation==null){/**\n         * 旋转\n         * @type {Array.<number>}\n         * @default 0\n         */this.rotation=0;}if(!opts.scale){/**\n         * 缩放\n         * @type {Array.<number>}\n         * @default [1, 1]\n         */this.scale=[1,1];}/**\n     * 旋转和缩放的原点\n     * @type {Array.<number>}\n     * @default null\n     */this.origin=this.origin||null;};var transformableProto=Transformable.prototype;transformableProto.transform=null;/**\n * 判断是否需要有坐标变换\n * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵\n */transformableProto.needLocalTransform=function(){return isNotAroundZero(this.rotation)||isNotAroundZero(this.position[0])||isNotAroundZero(this.position[1])||isNotAroundZero(this.scale[0]-1)||isNotAroundZero(this.scale[1]-1);};var scaleTmp=[];transformableProto.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);}// 应用父节点变换\nif(parentHasTransform){if(needLocalTransform){mul$1(m,parent.transform,m);}else{copy$1(m,parent.transform);}}// 保存这个变换矩阵\nthis.transform=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);};transformableProto.getLocalTransform=function(m){return Transformable.getLocalTransform(this,m);};/**\n * 将自己的transform应用到context上\n * @param {CanvasRenderingContext2D} ctx\n */transformableProto.setTransform=function(ctx){var m=this.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);}};transformableProto.restoreTransform=function(ctx){var dpr=ctx.dpr||1;ctx.setTransform(dpr,0,0,dpr,0,0);};var tmpTransform=[];var originTransform=create$1();transformableProto.setLocalTransform=function(m){if(!m){// TODO return or set identity?\nreturn;}var sx=m[0]*m[0]+m[1]*m[1];var sy=m[2]*m[2]+m[3]*m[3];var position=this.position;var scale$$1=this.scale;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;}position[0]=m[4];position[1]=m[5];scale$$1[0]=sx;scale$$1[1]=sy;this.rotation=Math.atan2(-m[1]/sy,m[0]/sx);};/**\n * 分解`transform`矩阵到`position`, `rotation`, `scale`\n */transformableProto.decomposeTransform=function(){if(!this.transform){return;}var parent=this.parent;var m=this.transform;if(parent&&parent.transform){// Get local transform and decompose them to position, scale, rotation\nmul$1(tmpTransform,parent.invTransform,m);m=tmpTransform;}var origin=this.origin;if(origin&&(origin[0]||origin[1])){originTransform[4]=origin[0];originTransform[5]=origin[1];mul$1(tmpTransform,m,originTransform);tmpTransform[4]-=origin[0];tmpTransform[5]-=origin[1];m=tmpTransform;}this.setLocalTransform(m);};/**\n * Get global scale\n * @return {Array.<number>}\n */transformableProto.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;};/**\n * 变换坐标位置到 shape 的局部坐标空间\n * @method\n * @param {number} x\n * @param {number} y\n * @return {Array.<number>}\n */transformableProto.transformCoordToLocal=function(x,y){var v2=[x,y];var invTransform=this.invTransform;if(invTransform){applyTransform(v2,v2,invTransform);}return v2;};/**\n * 变换局部坐标位置到全局坐标空间\n * @method\n * @param {number} x\n * @param {number} y\n * @return {Array.<number>}\n */transformableProto.transformCoordToGlobal=function(x,y){var v2=[x,y];var transform=this.transform;if(transform){applyTransform(v2,v2,transform);}return v2;};/**\n * @static\n * @param {Object} target\n * @param {Array.<number>} target.origin\n * @param {number} target.rotation\n * @param {Array.<number>} target.position\n * @param {Array.<number>} [m]\n */Transformable.getLocalTransform=function(target,m){m=m||[];mIdentity(m);var origin=target.origin;var scale$$1=target.scale||[1,1];var rotation=target.rotation||0;var position=target.position||[0,0];if(origin){// Translate to origin\nm[4]-=origin[0];m[5]-=origin[1];}scale$1(m,m,scale$$1);if(rotation){rotate(m,m,rotation);}if(origin){// Translate back from origin\nm[4]+=origin[0];m[5]+=origin[1];}m[4]+=position[0];m[5]+=position[1];return m;};/**\n * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js\n * @see http://sole.github.io/tween.js/examples/03_graphs.html\n * @exports zrender/animation/easing\n */var easing={/**\n    * @param {number} k\n    * @return {number}\n    */linear:function linear(k){return k;},/**\n    * @param {number} k\n    * @return {number}\n    */quadraticIn:function quadraticIn(k){return k*k;},/**\n    * @param {number} k\n    * @return {number}\n    */quadraticOut:function quadraticOut(k){return k*(2-k);},/**\n    * @param {number} k\n    * @return {number}\n    */quadraticInOut:function quadraticInOut(k){if((k*=2)<1){return 0.5*k*k;}return-0.5*(--k*(k-2)-1);},// 三次方的缓动（t^3）\n/**\n    * @param {number} k\n    * @return {number}\n    */cubicIn:function cubicIn(k){return k*k*k;},/**\n    * @param {number} k\n    * @return {number}\n    */cubicOut:function cubicOut(k){return--k*k*k+1;},/**\n    * @param {number} k\n    * @return {number}\n    */cubicInOut:function cubicInOut(k){if((k*=2)<1){return 0.5*k*k*k;}return 0.5*((k-=2)*k*k+2);},// 四次方的缓动（t^4）\n/**\n    * @param {number} k\n    * @return {number}\n    */quarticIn:function quarticIn(k){return k*k*k*k;},/**\n    * @param {number} k\n    * @return {number}\n    */quarticOut:function quarticOut(k){return 1- --k*k*k*k;},/**\n    * @param {number} k\n    * @return {number}\n    */quarticInOut:function quarticInOut(k){if((k*=2)<1){return 0.5*k*k*k*k;}return-0.5*((k-=2)*k*k*k-2);},// 五次方的缓动（t^5）\n/**\n    * @param {number} k\n    * @return {number}\n    */quinticIn:function quinticIn(k){return k*k*k*k*k;},/**\n    * @param {number} k\n    * @return {number}\n    */quinticOut:function quinticOut(k){return--k*k*k*k*k+1;},/**\n    * @param {number} k\n    * @return {number}\n    */quinticInOut:function quinticInOut(k){if((k*=2)<1){return 0.5*k*k*k*k*k;}return 0.5*((k-=2)*k*k*k*k+2);},// 正弦曲线的缓动（sin(t)）\n/**\n    * @param {number} k\n    * @return {number}\n    */sinusoidalIn:function sinusoidalIn(k){return 1-Math.cos(k*Math.PI/2);},/**\n    * @param {number} k\n    * @return {number}\n    */sinusoidalOut:function sinusoidalOut(k){return Math.sin(k*Math.PI/2);},/**\n    * @param {number} k\n    * @return {number}\n    */sinusoidalInOut:function sinusoidalInOut(k){return 0.5*(1-Math.cos(Math.PI*k));},// 指数曲线的缓动（2^t）\n/**\n    * @param {number} k\n    * @return {number}\n    */exponentialIn:function exponentialIn(k){return k===0?0:Math.pow(1024,k-1);},/**\n    * @param {number} k\n    * @return {number}\n    */exponentialOut:function exponentialOut(k){return k===1?1:1-Math.pow(2,-10*k);},/**\n    * @param {number} k\n    * @return {number}\n    */exponentialInOut:function exponentialInOut(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);},// 圆形曲线的缓动（sqrt(1-t^2)）\n/**\n    * @param {number} k\n    * @return {number}\n    */circularIn:function circularIn(k){return 1-Math.sqrt(1-k*k);},/**\n    * @param {number} k\n    * @return {number}\n    */circularOut:function circularOut(k){return Math.sqrt(1- --k*k);},/**\n    * @param {number} k\n    * @return {number}\n    */circularInOut:function circularInOut(k){if((k*=2)<1){return-0.5*(Math.sqrt(1-k*k)-1);}return 0.5*(Math.sqrt(1-(k-=2)*k)+1);},// 创建类似于弹簧在停止前来回振荡的动画\n/**\n    * @param {number} k\n    * @return {number}\n    */elasticIn:function elasticIn(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));},/**\n    * @param {number} k\n    * @return {number}\n    */elasticOut:function elasticOut(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;},/**\n    * @param {number} k\n    * @return {number}\n    */elasticInOut:function elasticInOut(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;},// 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动\n/**\n    * @param {number} k\n    * @return {number}\n    */backIn:function backIn(k){var s=1.70158;return k*k*((s+1)*k-s);},/**\n    * @param {number} k\n    * @return {number}\n    */backOut:function backOut(k){var s=1.70158;return--k*k*((s+1)*k+s)+1;},/**\n    * @param {number} k\n    * @return {number}\n    */backInOut:function backInOut(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);},// 创建弹跳效果\n/**\n    * @param {number} k\n    * @return {number}\n    */bounceIn:function bounceIn(k){return 1-easing.bounceOut(1-k);},/**\n    * @param {number} k\n    * @return {number}\n    */bounceOut:function bounceOut(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;}},/**\n    * @param {number} k\n    * @return {number}\n    */bounceInOut:function bounceInOut(k){if(k<0.5){return easing.bounceIn(k*2)*0.5;}return easing.bounceOut(k*2-1)*0.5+0.5;}};/**\n * 动画主控制器\n * @config target 动画对象，可以是数组，如果是数组的话会批量分发onframe等事件\n * @config life(1000) 动画时长\n * @config delay(0) 动画延迟时间\n * @config loop(true)\n * @config gap(0) 循环的间隔时间\n * @config onframe\n * @config easing(optional)\n * @config ondestroy(optional)\n * @config onrestart(optional)\n *\n * TODO pause\n */function Clip(options){this._target=options.target;// 生命周期\nthis._life=options.life||1000;// 延时\nthis._delay=options.delay||0;// 开始时间\n// this._startTime = new Date().getTime() + this._delay;// 单位毫秒\nthis._initialized=false;// 是否循环\nthis.loop=options.loop==null?false:options.loop;this.gap=options.gap||0;this.easing=options.easing||'Linear';this.onframe=options.onframe;this.ondestroy=options.ondestroy;this.onrestart=options.onrestart;this._pausedTime=0;this._paused=false;}Clip.prototype={constructor:Clip,step:function step(globalTime,deltaTime){// Set startTime on first step, or _startTime may has milleseconds different between clips\n// PENDING\nif(!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;// 还没开始\nif(percent<0){return;}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.fire('frame',schedule);// 结束\nif(percent===1){if(this.loop){this.restart(globalTime);// 重新开始周期\n// 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件\nreturn'restart';}// 动画完成将这个控制器标识为待删除\n// 在Animation.update中进行批量删除\nthis._needsRemove=true;return'destroy';}return null;},restart:function restart(globalTime){var remainder=(globalTime-this._startTime-this._pausedTime)%this._life;this._startTime=globalTime-remainder+this.gap;this._pausedTime=0;this._needsRemove=false;},fire:function fire(eventType,arg){eventType='on'+eventType;if(this[eventType]){this[eventType](this._target,arg);}},pause:function pause(){this._paused=true;},resume:function resume(){this._paused=false;}};// Simple LRU cache use doubly linked list\n// @module zrender/core/LRU\n/**\n * Simple double linked list. Compared with array, it has O(1) remove operation.\n * @constructor\n */var LinkedList=function LinkedList(){/**\n     * @type {module:zrender/core/LRU~Entry}\n     */this.head=null;/**\n     * @type {module:zrender/core/LRU~Entry}\n     */this.tail=null;this._len=0;};var linkedListProto=LinkedList.prototype;/**\n * Insert a new value at the tail\n * @param  {} val\n * @return {module:zrender/core/LRU~Entry}\n */linkedListProto.insert=function(val){var entry=new Entry(val);this.insertEntry(entry);return entry;};/**\n * Insert an entry at the tail\n * @param  {module:zrender/core/LRU~Entry} entry\n */linkedListProto.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++;};/**\n * Remove entry.\n * @param  {module:zrender/core/LRU~Entry} entry\n */linkedListProto.remove=function(entry){var prev=entry.prev;var next=entry.next;if(prev){prev.next=next;}else{// Is head\nthis.head=next;}if(next){next.prev=prev;}else{// Is tail\nthis.tail=prev;}entry.next=entry.prev=null;this._len--;};/**\n * @return {number}\n */linkedListProto.len=function(){return this._len;};/**\n * Clear list\n */linkedListProto.clear=function(){this.head=this.tail=null;this._len=0;};/**\n * @constructor\n * @param {} val\n */var Entry=function Entry(val){/**\n     * @type {}\n     */this.value=val;/**\n     * @type {module:zrender/core/LRU~Entry}\n     */this.next;/**\n     * @type {module:zrender/core/LRU~Entry}\n     */this.prev;};/**\n * LRU Cache\n * @constructor\n * @alias module:zrender/core/LRU\n */var LRU=function LRU(maxSize){this._list=new LinkedList();this._map={};this._maxSize=maxSize||10;this._lastRemovedEntry=null;};var LRUProto=LRU.prototype;/**\n * @param  {string} key\n * @param  {} value\n * @return {} Removed value\n */LRUProto.put=function(key,value){var list=this._list;var map=this._map;var removed=null;if(map[key]==null){var len=list.len();// Reuse last removed entry\nvar entry=this._lastRemovedEntry;if(len>=this._maxSize&&len>0){// Remove the least recently used\nvar 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;};/**\n * @param  {string} key\n * @return {}\n */LRUProto.get=function(key){var entry=this._map[key];var list=this._list;if(entry!=null){// Put the latest used entry in the tail\nif(entry!==list.tail){list.remove(entry);list.insertEntry(entry);}return entry.value;}};/**\n * Clear the cache\n */LRUProto.clear=function(){this._list.clear();this._map={};};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){// Clamp to integer 0 .. 255.\ni=Math.round(i);// Seems to be what Chrome does (vs truncation).\nreturn i<0?0:i>255?255:i;}function clampCssAngle(i){// Clamp to integer 0 .. 360.\ni=Math.round(i);// Seems to be what Chrome does (vs truncation).\nreturn i<0?0:i>360?360:i;}function clampCssFloat(f){// Clamp to float 0.0 .. 1.0.\nreturn f<0?0:f>1?1:f;}function parseCssInt(str){// int or percentage.\nif(str.length&&str.charAt(str.length-1)==='%'){return clampCssByte(parseFloat(str)/100*255);}return clampCssByte(parseInt(str,10));}function parseCssFloat(str){// float or percentage.\nif(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){// Reuse removed array\nif(lastRemovedArr){copyRgba(lastRemovedArr,rgbaArr);}lastRemovedArr=colorCache.put(colorStr,lastRemovedArr||rgbaArr.slice());}/**\n * @param {string} colorStr\n * @param {Array.<number>} out\n * @return {Array.<number>}\n * @memberOf module:zrender/util/color\n */function parse(colorStr,rgbaArr){if(!colorStr){return;}rgbaArr=rgbaArr||[];var cached=colorCache.get(colorStr);if(cached){return copyRgba(rgbaArr,cached);}// colorStr may be not string\ncolorStr=colorStr+'';// Remove all whitespace, not compliant, but should just be more accepting.\nvar str=colorStr.replace(/ /g,'').toLowerCase();// Color keywords (and transparent) lookup.\nif(str in kCSSColorTable){copyRgba(rgbaArr,kCSSColorTable[str]);putToCache(colorStr,rgbaArr);return rgbaArr;}// #abc and #abc123 syntax.\nif(str.charAt(0)==='#'){if(str.length===4){var iv=parseInt(str.substr(1),16);// TODO(deanm): Stricter parsing.\nif(!(iv>=0&&iv<=0xfff)){setRgba(rgbaArr,0,0,0,1);return;// Covers NaN.\n}setRgba(rgbaArr,(iv&0xf00)>>4|(iv&0xf00)>>8,iv&0xf0|(iv&0xf0)>>4,iv&0xf|(iv&0xf)<<4,1);putToCache(colorStr,rgbaArr);return rgbaArr;}else if(str.length===7){var iv=parseInt(str.substr(1),16);// TODO(deanm): Stricter parsing.\nif(!(iv>=0&&iv<=0xffffff)){setRgba(rgbaArr,0,0,0,1);return;// Covers NaN.\n}setRgba(rgbaArr,(iv&0xff0000)>>16,(iv&0xff00)>>8,iv&0xff,1);putToCache(colorStr,rgbaArr);return rgbaArr;}return;}var op=str.indexOf('(');var ep=str.indexOf(')');if(op!==-1&&ep+1===str.length){var fname=str.substr(0,op);var params=str.substr(op+1,ep-(op+1)).split(',');var alpha=1;// To allow case fallthrough.\nswitch(fname){case'rgba':if(params.length!==4){setRgba(rgbaArr,0,0,0,1);return;}alpha=parseCssFloat(params.pop());// jshint ignore:line\n// Fall through.\ncase'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;}/**\n * @param {Array.<number>} hsla\n * @param {Array.<number>} rgba\n * @return {Array.<number>} rgba\n */function hsla2rgba(hsla,rgba){var h=(parseFloat(hsla[0])%360+360)%360/360;// 0 .. 1\n// NOTE(deanm): According to the CSS spec s/l should only be\n// percentages, but we don't bother and let float or percentage.\nvar 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;}/**\n * @param {Array.<number>} rgba\n * @return {Array.<number>} hsla\n */function rgba2hsla(rgba){if(!rgba){return;}// RGB from 0 to 255\nvar R=rgba[0]/255;var G=rgba[1]/255;var B=rgba[2]/255;var vMin=Math.min(R,G,B);// Min. value of RGB\nvar vMax=Math.max(R,G,B);// Max. value of RGB\nvar delta=vMax-vMin;// Delta RGB value\nvar L=(vMax+vMin)/2;var H;var S;// HSL results from 0 to 1\nif(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;}/**\n * @param {string} color\n * @param {number} level\n * @return {string}\n * @memberOf module:zrender/util/color\n */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(color[i]<0){colorArr[i]=0;}}return stringify(colorArr,colorArr.length===4?'rgba':'rgb');}}/**\n * @param {string} color\n * @return {string}\n * @memberOf module:zrender/util/color\n */function toHex(color){var colorArr=parse(color);if(colorArr){return((1<<24)+(colorArr[0]<<16)+(colorArr[1]<<8)+ +colorArr[2]).toString(16).slice(1);}}/**\n * Map value to color. Faster than lerp methods because color is represented by rgba array.\n * @param {number} normalizedValue A float between 0 and 1.\n * @param {Array.<Array.<number>>} colors List of rgba color array\n * @param {Array.<number>} [out] Mapped gba color array\n * @return {Array.<number>} will be null/undefined if input illegal.\n */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;}/**\n * @deprecated\n */var fastMapToColor=fastLerp;/**\n * @param {number} normalizedValue A float between 0 and 1.\n * @param {Array.<string>} colors Color list.\n * @param {boolean=} fullOutput Default false.\n * @return {(string|Object)} Result color. If fullOutput,\n *                           return {color: ..., leftIndex: ..., rightIndex: ..., value: ...},\n * @memberOf module:zrender/util/color\n */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;}/**\n * @deprecated\n */var mapToColor=lerp$1;/**\n * @param {string} color\n * @param {number=} h 0 ~ 360, ignore when null.\n * @param {number=} s 0 ~ 1, ignore when null.\n * @param {number=} l 0 ~ 1, ignore when null.\n * @return {string} Color string in rgba format.\n * @memberOf module:zrender/util/color\n */function modifyHSL(color,h,s,l){color=parse(color);if(color){color=rgba2hsla(color);h!=null&&(color[0]=clampCssAngle(h));s!=null&&(color[1]=parseCssFloat(s));l!=null&&(color[2]=parseCssFloat(l));return stringify(hsla2rgba(color),'rgba');}}/**\n * @param {string} color\n * @param {number=} alpha 0 ~ 1\n * @return {string} Color string in rgba format.\n * @memberOf module:zrender/util/color\n */function modifyAlpha(color,alpha){color=parse(color);if(color&&alpha!=null){color[3]=clampCssFloat(alpha);return stringify(color,'rgba');}}/**\n * @param {Array.<number>} arrColor like [12,33,44,0.4]\n * @param {string} type 'rgba', 'hsva', ...\n * @return {string} Result color. (If input illegal, return undefined).\n */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+')';}var color=(Object.freeze||Object)({parse:parse,lift:lift,toHex:toHex,fastLerp:fastLerp,fastMapToColor:fastMapToColor,lerp:lerp$1,mapToColor:mapToColor,modifyHSL:modifyHSL,modifyAlpha:modifyAlpha,stringify:stringify});/**\n * @module echarts/animation/Animator\n */var arraySlice=Array.prototype.slice;function defaultGetter(target,key){return target[key];}function defaultSetter(target,key,value){target[key]=value;}/**\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} percent\n * @return {number}\n */function interpolateNumber(p0,p1,percent){return(p1-p0)*percent+p0;}/**\n * @param  {string} p0\n * @param  {string} p1\n * @param  {number} percent\n * @return {string}\n */function interpolateString(p0,p1,percent){return percent>0.5?p1:p0;}/**\n * @param  {Array} p0\n * @param  {Array} p1\n * @param  {number} percent\n * @param  {Array} out\n * @param  {number} arrDim\n */function interpolateArray(p0,p1,percent,out,arrDim){var len=p0.length;if(arrDim===1){for(var i=0;i<len;i++){out[i]=interpolateNumber(p0[i],p1[i],percent);}}else{var len2=len&&p0[0].length;for(var i=0;i<len;i++){for(var j=0;j<len2;j++){out[i][j]=interpolateNumber(p0[i][j],p1[i][j],percent);}}}}// arr0 is source array, arr1 is target array.\n// Do some preprocess to avoid error happened when interpolating from arr0 to arr1\nfunction fillArr(arr0,arr1,arrDim){var arr0Len=arr0.length;var arr1Len=arr1.length;if(arr0Len!==arr1Len){// FIXME Not work for TypedArray\nvar isPreviousLarger=arr0Len>arr1Len;if(isPreviousLarger){// Cut the previous\narr0.length=arr1Len;}else{// Fill the previous\nfor(var i=arr0Len;i<arr1Len;i++){arr0.push(arrDim===1?arr1[i]:arraySlice.call(arr1[i]));}}}// Handling NaN value\nvar 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];}}}}}/**\n * @param  {Array} arr0\n * @param  {Array} arr1\n * @param  {number} arrDim\n * @return {boolean}\n */function isArraySame(arr0,arr1,arrDim){if(arr0===arr1){return true;}var len=arr0.length;if(len!==arr1.length){return false;}if(arrDim===1){for(var i=0;i<len;i++){if(arr0[i]!==arr1[i]){return false;}}}else{var len2=arr0[0].length;for(var i=0;i<len;i++){for(var j=0;j<len2;j++){if(arr0[i][j]!==arr1[i][j]){return false;}}}}return true;}/**\n * Catmull Rom interpolate array\n * @param  {Array} p0\n * @param  {Array} p1\n * @param  {Array} p2\n * @param  {Array} p3\n * @param  {number} t\n * @param  {number} t2\n * @param  {number} t3\n * @param  {Array} out\n * @param  {number} arrDim\n */function catmullRomInterpolateArray(p0,p1,p2,p3,t,t2,t3,out,arrDim){var len=p0.length;if(arrDim===1){for(var i=0;i<len;i++){out[i]=catmullRomInterpolate(p0[i],p1[i],p2[i],p3[i],t,t2,t3);}}else{var len2=p0[0].length;for(var i=0;i<len;i++){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);}}}}/**\n * Catmull Rom interpolate number\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {number} t\n * @param  {number} t2\n * @param  {number} t3\n * @return {number}\n */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 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 getArrayDim(keyframes){var lastValue=keyframes[keyframes.length-1].value;return isArrayLike(lastValue&&lastValue[0])?2:1;}function createTrackClip(animator,easing,oneTrackDone,keyframes,propName,forceAnimate){var getter=animator._getter;var setter=animator._setter;var useSpline=easing==='spline';var trackLen=keyframes.length;if(!trackLen){return;}// Guess data type\nvar firstVal=keyframes[0].value;var isValueArray=isArrayLike(firstVal);var isValueColor=false;var isValueString=false;// For vertices morphing\nvar arrDim=isValueArray?getArrayDim(keyframes):0;var trackMaxTime;// Sort keyframe as ascending\nkeyframes.sort(function(a,b){return a.time-b.time;});trackMaxTime=keyframes[trackLen-1].time;// Percents of each keyframe\nvar kfPercents=[];// Value of each keyframe\nvar kfValues=[];var prevValue=keyframes[0].value;var isAllValueEqual=true;for(var i=0;i<trackLen;i++){kfPercents.push(keyframes[i].time/trackMaxTime);// Assume value is a color when it is a string\nvar value=keyframes[i].value;// Check if value is equal, deep check if value is array\nif(!(isValueArray&&isArraySame(value,prevValue,arrDim)||!isValueArray&&value===prevValue)){isAllValueEqual=false;}prevValue=value;// Try converting a string to a color array\nif(typeof value==='string'){var colorArray=parse(value);if(colorArray){value=colorArray;isValueColor=true;}else{isValueString=true;}}kfValues.push(value);}if(!forceAnimate&&isAllValueEqual){return;}var lastValue=kfValues[trackLen-1];// Polyfill array and NaN value\nfor(var i=0;i<trackLen-1;i++){if(isValueArray){fillArr(kfValues[i],lastValue,arrDim);}else{if(isNaN(kfValues[i])&&!isNaN(lastValue)&&!isValueString&&!isValueColor){kfValues[i]=lastValue;}}}isValueArray&&fillArr(getter(animator._target,propName),lastValue,arrDim);// Cache the key of last frame to speed up when\n// animation playback is sequency\nvar lastFrame=0;var lastFramePercent=0;var start;var w;var p0;var p1;var p2;var p3;if(isValueColor){var rgba=[0,0,0,0];}var onframe=function onframe(target,percent){// Find the range keyframes\n// kf1-----kf2---------current--------kf3\n// find kf2 and kf3 and do interpolation\nvar frame;// In the easing function like elasticOut, percent may less than 0\nif(percent<0){frame=0;}else if(percent<lastFramePercent){// Start from next key\n// PENDING start from lastFrame ?\nstart=Math.min(lastFrame+1,trackLen-1);for(frame=start;frame>=0;frame--){if(kfPercents[frame]<=percent){break;}}// PENDING really need to do this ?\nframe=Math.min(frame,trackLen-2);}else{for(frame=lastFrame;frame<trackLen;frame++){if(kfPercents[frame]>percent){break;}}frame=Math.min(frame-1,trackLen-2);}lastFrame=frame;lastFramePercent=percent;var range=kfPercents[frame+1]-kfPercents[frame];if(range===0){return;}else{w=(percent-kfPercents[frame])/range;}if(useSpline){p1=kfValues[frame];p0=kfValues[frame===0?frame:frame-1];p2=kfValues[frame>trackLen-2?trackLen-1:frame+1];p3=kfValues[frame>trackLen-3?trackLen-1:frame+2];if(isValueArray){catmullRomInterpolateArray(p0,p1,p2,p3,w,w*w,w*w*w,getter(target,propName),arrDim);}else{var value;if(isValueColor){value=catmullRomInterpolateArray(p0,p1,p2,p3,w,w*w,w*w*w,rgba,1);value=rgba2String(rgba);}else if(isValueString){// String is step(0.5)\nreturn interpolateString(p1,p2,w);}else{value=catmullRomInterpolate(p0,p1,p2,p3,w,w*w,w*w*w);}setter(target,propName,value);}}else{if(isValueArray){interpolateArray(kfValues[frame],kfValues[frame+1],w,getter(target,propName),arrDim);}else{var value;if(isValueColor){interpolateArray(kfValues[frame],kfValues[frame+1],w,rgba,1);value=rgba2String(rgba);}else if(isValueString){// String is step(0.5)\nreturn interpolateString(kfValues[frame],kfValues[frame+1],w);}else{value=interpolateNumber(kfValues[frame],kfValues[frame+1],w);}setter(target,propName,value);}}};var clip=new Clip({target:animator._target,life:trackMaxTime,loop:animator._loop,delay:animator._delay,onframe:onframe,ondestroy:oneTrackDone});if(easing&&easing!=='spline'){clip.easing=easing;}return clip;}/**\n * @alias module:zrender/animation/Animator\n * @constructor\n * @param {Object} target\n * @param {boolean} loop\n * @param {Function} getter\n * @param {Function} setter\n */var Animator=function Animator(target,loop,getter,setter){this._tracks={};this._target=target;this._loop=loop||false;this._getter=getter||defaultGetter;this._setter=setter||defaultSetter;this._clipCount=0;this._delay=0;this._doneList=[];this._onframeList=[];this._clipList=[];};Animator.prototype={/**\n     * Set Animation keyframe\n     * @param  {number} time 关键帧时间，单位是ms\n     * @param  {Object} props 关键帧的属性值，key-value表示\n     * @return {module:zrender/animation/Animator}\n     */when:function when(time/* ms */,props){var tracks=this._tracks;for(var propName in props){if(!props.hasOwnProperty(propName)){continue;}if(!tracks[propName]){tracks[propName]=[];// Invalid value\nvar value=this._getter(this._target,propName);if(value==null){// zrLog('Invalid property ' + propName);\ncontinue;}// If time is 0\n//  Then props is given initialize value\n// Else\n//  Initialize value from current prop value\nif(time!==0){tracks[propName].push({time:0,value:cloneValue(value)});}}tracks[propName].push({time:time,value:props[propName]});}return this;},/**\n     * 添加动画每一帧的回调函数\n     * @param  {Function} callback\n     * @return {module:zrender/animation/Animator}\n     */during:function during(callback){this._onframeList.push(callback);return this;},pause:function pause(){for(var i=0;i<this._clipList.length;i++){this._clipList[i].pause();}this._paused=true;},resume:function resume(){for(var i=0;i<this._clipList.length;i++){this._clipList[i].resume();}this._paused=false;},isPaused:function isPaused(){return!!this._paused;},_doneCallback:function _doneCallback(){// Clear all tracks\nthis._tracks={};// Clear all clips\nthis._clipList.length=0;var doneList=this._doneList;var len=doneList.length;for(var i=0;i<len;i++){doneList[i].call(this);}},/**\n     * Start the animation\n     * @param  {string|Function} [easing]\n     *         动画缓动函数，详见{@link module:zrender/animation/easing}\n     * @param  {boolean} forceAnimate\n     * @return {module:zrender/animation/Animator}\n     */start:function start(easing,forceAnimate){var self=this;var clipCount=0;var oneTrackDone=function oneTrackDone(){clipCount--;if(!clipCount){self._doneCallback();}};var lastClip;for(var propName in this._tracks){if(!this._tracks.hasOwnProperty(propName)){continue;}var clip=createTrackClip(this,easing,oneTrackDone,this._tracks[propName],propName,forceAnimate);if(clip){this._clipList.push(clip);clipCount++;// If start after added to animation\nif(this.animation){this.animation.addClip(clip);}lastClip=clip;}}// Add during callback on the last clip\nif(lastClip){var oldOnFrame=lastClip.onframe;lastClip.onframe=function(target,percent){oldOnFrame(target,percent);for(var i=0;i<self._onframeList.length;i++){self._onframeList[i](target,percent);}};}// This optimization will help the case that in the upper application\n// the view may be refreshed frequently, where animation will be\n// called repeatly but nothing changed.\nif(!clipCount){this._doneCallback();}return this;},/**\n     * Stop animation\n     * @param {boolean} forwardToLast If move to last frame before stop\n     */stop:function stop(forwardToLast){var clipList=this._clipList;var animation=this.animation;for(var i=0;i<clipList.length;i++){var clip=clipList[i];if(forwardToLast){// Move to last frame before stop\nclip.onframe(this._target,1);}animation&&animation.removeClip(clip);}clipList.length=0;},/**\n     * Set when animation delay starts\n     * @param  {number} time 单位ms\n     * @return {module:zrender/animation/Animator}\n     */delay:function delay(time){this._delay=time;return this;},/**\n     * Add callback for animation end\n     * @param  {Function} cb\n     * @return {module:zrender/animation/Animator}\n     */done:function done(cb){if(cb){this._doneList.push(cb);}return this;},/**\n     * @return {Array.<module:zrender/animation/Clip>}\n     */getClips:function getClips(){return this._clipList;}};var dpr=1;// If in browser environment\nif(typeof window!=='undefined'){dpr=Math.max(window.devicePixelRatio||1,1);}/**\n * config默认配置项\n * @exports zrender/config\n * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)\n */ /**\n * Debug log mode:\n * 0: Do nothing, for release.\n * 1: console.error, for debug.\n */var debugMode=0;// retina 屏幕优化\nvar devicePixelRatio=dpr;var logError=function logError(){};if(debugMode===1){logError=console.error;}var logError$1=logError;/**\n * @alias module:zrender/mixin/Animatable\n * @constructor\n */var Animatable=function Animatable(){/**\n     * @type {Array.<module:zrender/animation/Animator>}\n     * @readOnly\n     */this.animators=[];};Animatable.prototype={constructor:Animatable,/**\n     * 动画\n     *\n     * @param {string} path The path to fetch value from object, like 'a.b.c'.\n     * @param {boolean} [loop] Whether to loop animation.\n     * @return {module:zrender/animation/Animator}\n     * @example:\n     *     el.animate('style', false)\n     *         .when(1000, {x: 10} )\n     *         .done(function(){ // Animation done })\n     *         .start()\n     */animate:function animate(path,loop){var target;var animatingShape=false;var el=this;var zr=this.__zr;if(path){var pathSplitted=path.split('.');var prop=el;// If animating shape\nanimatingShape=pathSplitted[0]==='shape';for(var i=0,l=pathSplitted.length;i<l;i++){if(!prop){continue;}prop=prop[pathSplitted[i]];}if(prop){target=prop;}}else{target=el;}if(!target){logError$1('Property \"'+path+'\" is not existed in element '+el.id);return;}var animators=el.animators;var animator=new Animator(target,loop);animator.during(function(target){el.dirty(animatingShape);}).done(function(){// FIXME Animator will not be removed if use `Animator#stop` to stop animation\nanimators.splice(indexOf(animators,animator),1);});animators.push(animator);// If animate after added to the zrender\nif(zr){zr.animation.addAnimator(animator);}return animator;},/**\n     * 停止动画\n     * @param {boolean} forwardToLast If move to last frame before stop\n     */stopAnimation:function stopAnimation(forwardToLast){var animators=this.animators;var len=animators.length;for(var i=0;i<len;i++){animators[i].stop(forwardToLast);}animators.length=0;return this;},/**\n     * Caution: this method will stop previous animation.\n     * So do not use this method to one element twice before\n     * animation starts, unless you know what you are doing.\n     * @param {Object} target\n     * @param {number} [time=500] Time in ms\n     * @param {string} [easing='linear']\n     * @param {number} [delay=0]\n     * @param {Function} [callback]\n     * @param {Function} [forceAnimate] Prevent stop animation and callback\n     *        immediently when target values are the same as current values.\n     *\n     * @example\n     *  // Animate position\n     *  el.animateTo({\n     *      position: [10, 10]\n     *  }, function () { // done })\n     *\n     *  // Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing\n     *  el.animateTo({\n     *      shape: {\n     *          width: 500\n     *      },\n     *      style: {\n     *          fill: 'red'\n     *      }\n     *      position: [10, 10]\n     *  }, 100, 100, 'cubicOut', function () { // done })\n     */ // TODO Return animation key\nanimateTo:function animateTo(target,time,delay,easing,callback,forceAnimate){_animateTo(this,target,time,delay,easing,callback,forceAnimate);},/**\n     * Animate from the target state to current state.\n     * The params and the return value are the same as `this.animateTo`.\n     */animateFrom:function animateFrom(target,time,delay,easing,callback,forceAnimate){_animateTo(this,target,time,delay,easing,callback,forceAnimate,true);}};function _animateTo(animatable,target,time,delay,easing,callback,forceAnimate,reverse){// animateTo(target, time, easing, callback);\nif(isString(delay)){callback=easing;easing=delay;delay=0;}// animateTo(target, time, delay, callback);\nelse if(isFunction$1(easing)){callback=easing;easing='linear';delay=0;}// animateTo(target, time, callback);\nelse if(isFunction$1(delay)){callback=delay;delay=0;}// animateTo(target, callback)\nelse if(isFunction$1(time)){callback=time;time=500;}// animateTo(target)\nelse if(!time){time=500;}// Stop all previous animations\nanimatable.stopAnimation();animateToShallow(animatable,'',animatable,target,time,delay,reverse);// Animators may be removed immediately after start\n// if there is nothing to animate\nvar animators=animatable.animators.slice();var count=animators.length;function done(){count--;if(!count){callback&&callback();}}// No animators. This should be checked before animators[i].start(),\n// because 'done' may be executed immediately if no need to animate.\nif(!count){callback&&callback();}// Start after all animators created\n// Incase any animator is done immediately when all animation properties are not changed\nfor(var i=0;i<animators.length;i++){animators[i].done(done).start(easing,forceAnimate);}}/**\n * @param {string} path=''\n * @param {Object} source=animatable\n * @param {Object} target\n * @param {number} [time=500]\n * @param {number} [delay=0]\n * @param {boolean} [reverse] If `true`, animate\n *        from the `target` to current state.\n *\n * @example\n *  // Animate position\n *  el._animateToShallow({\n *      position: [10, 10]\n *  })\n *\n *  // Animate shape, style and position in 100ms, delayed 100ms\n *  el._animateToShallow({\n *      shape: {\n *          width: 500\n *      },\n *      style: {\n *          fill: 'red'\n *      }\n *      position: [10, 10]\n *  }, 100, 100)\n */function animateToShallow(animatable,path,source,target,time,delay,reverse){var objShallow={};var propertyCount=0;for(var name in target){if(!target.hasOwnProperty(name)){continue;}if(source[name]!=null){if(isObject$1(target[name])&&!isArrayLike(target[name])){animateToShallow(animatable,path?path+'.'+name:name,source[name],target[name],time,delay,reverse);}else{if(reverse){objShallow[name]=source[name];setAttrByPath(animatable,path,name,target[name]);}else{objShallow[name]=target[name];}propertyCount++;}}else if(target[name]!=null&&!reverse){setAttrByPath(animatable,path,name,target[name]);}}if(propertyCount>0){animatable.animate(path,false).when(time==null?500:time,objShallow).delay(delay||0);}}function setAttrByPath(el,path,name,value){// Attr directly if not has property\n// FIXME, if some property not needed for element ?\nif(!path){el.attr(name,value);}else{// Only support set shape or style\nvar props={};props[path]={};props[path][name]=value;el.attr(props);}}/**\n * @alias module:zrender/Element\n * @constructor\n * @extends {module:zrender/mixin/Animatable}\n * @extends {module:zrender/mixin/Transformable}\n * @extends {module:zrender/mixin/Eventful}\n */var Element=function Element(opts){// jshint ignore:line\nTransformable.call(this,opts);Eventful.call(this,opts);Animatable.call(this,opts);/**\n     * 画布元素ID\n     * @type {string}\n     */this.id=opts.id||guid();};Element.prototype={/**\n     * 元素类型\n     * Element type\n     * @type {string}\n     */type:'element',/**\n     * 元素名字\n     * Element name\n     * @type {string}\n     */name:'',/**\n     * ZRender 实例对象，会在 element 添加到 zrender 实例中后自动赋值\n     * ZRender instance will be assigned when element is associated with zrender\n     * @name module:/zrender/Element#__zr\n     * @type {module:zrender/ZRender}\n     */__zr:null,/**\n     * 图形是否忽略，为true时忽略图形的绘制以及事件触发\n     * If ignore drawing and events of the element object\n     * @name module:/zrender/Element#ignore\n     * @type {boolean}\n     * @default false\n     */ignore:false,/**\n     * 用于裁剪的路径(shape)，所有 Group 内的路径在绘制时都会被这个路径裁剪\n     * 该路径会继承被裁减对象的变换\n     * @type {module:zrender/graphic/Path}\n     * @see http://www.w3.org/TR/2dcontext/#clipping-region\n     * @readOnly\n     */clipPath:null,/**\n     * 是否是 Group\n     * @type {boolean}\n     */isGroup:false,/**\n     * Drift element\n     * @param  {number} dx dx on the global space\n     * @param  {number} dy dy on the global space\n     */drift:function drift(dx,dy){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.dirty(false);},/**\n     * Hook before update\n     */beforeUpdate:function beforeUpdate(){},/**\n     * Hook after update\n     */afterUpdate:function afterUpdate(){},/**\n     * Update each frame\n     */update:function update(){this.updateTransform();},/**\n     * @param  {Function} cb\n     * @param  {}   context\n     */traverse:function traverse(cb,context){},/**\n     * @protected\n     */attrKV:function attrKV(key,value){if(key==='position'||key==='scale'||key==='origin'){// Copy the array\nif(value){var target=this[key];if(!target){target=this[key]=[];}target[0]=value[0];target[1]=value[1];}}else{this[key]=value;}},/**\n     * Hide the element\n     */hide:function hide(){this.ignore=true;this.__zr&&this.__zr.refresh();},/**\n     * Show the element\n     */show:function show(){this.ignore=false;this.__zr&&this.__zr.refresh();},/**\n     * @param {string|Object} key\n     * @param {*} value\n     */attr:function attr(key,value){if(typeof key==='string'){this.attrKV(key,value);}else if(isObject$1(key)){for(var name in key){if(key.hasOwnProperty(name)){this.attrKV(name,key[name]);}}}this.dirty(false);return this;},/**\n     * @param {module:zrender/graphic/Path} clipPath\n     */setClipPath:function setClipPath(clipPath){var zr=this.__zr;if(zr){clipPath.addSelfToZr(zr);}// Remove previous clip path\nif(this.clipPath&&this.clipPath!==clipPath){this.removeClipPath();}this.clipPath=clipPath;clipPath.__zr=zr;clipPath.__clipTarget=this;this.dirty(false);},/**\n     */removeClipPath:function removeClipPath(){var clipPath=this.clipPath;if(clipPath){if(clipPath.__zr){clipPath.removeSelfFromZr(clipPath.__zr);}clipPath.__zr=null;clipPath.__clipTarget=null;this.clipPath=null;this.dirty(false);}},/**\n     * Add self from zrender instance.\n     * Not recursively because it will be invoked when element added to storage.\n     * @param {module:zrender/ZRender} zr\n     */addSelfToZr:function addSelfToZr(zr){this.__zr=zr;// 添加动画\nvar 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);}},/**\n     * Remove self from zrender instance.\n     * Not recursively because it will be invoked when element added to storage.\n     * @param {module:zrender/ZRender} zr\n     */removeSelfFromZr:function removeSelfFromZr(zr){this.__zr=null;// 移除动画\nvar 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);}}};mixin(Element,Animatable);mixin(Element,Transformable);mixin(Element,Eventful);/**\n * @module echarts/core/BoundingRect\n */var v2ApplyTransform=applyTransform;var mathMin=Math.min;var mathMax=Math.max;/**\n * @alias module:echarts/core/BoundingRect\n */function BoundingRect(x,y,width,height){if(width<0){x=x+width;width=-width;}if(height<0){y=y+height;height=-height;}/**\n     * @type {number}\n     */this.x=x;/**\n     * @type {number}\n     */this.y=y;/**\n     * @type {number}\n     */this.width=width;/**\n     * @type {number}\n     */this.height=height;}BoundingRect.prototype={constructor:BoundingRect,/**\n     * @param {module:echarts/core/BoundingRect} other\n     */union:function union(other){var x=mathMin(other.x,this.x);var y=mathMin(other.y,this.y);this.width=mathMax(other.x+other.width,this.x+this.width)-x;this.height=mathMax(other.y+other.height,this.y+this.height)-y;this.x=x;this.y=y;},/**\n     * @param {Array.<number>} m\n     * @methods\n     */applyTransform:function(){var lt=[];var rb=[];var lb=[];var rt=[];return function(m){// In case usage like this\n// el.getBoundingRect().applyTransform(el.transform)\n// And element has no transform\nif(!m){return;}lt[0]=lb[0]=this.x;lt[1]=rt[1]=this.y;rb[0]=rt[0]=this.x+this.width;rb[1]=lb[1]=this.y+this.height;v2ApplyTransform(lt,lt,m);v2ApplyTransform(rb,rb,m);v2ApplyTransform(lb,lb,m);v2ApplyTransform(rt,rt,m);this.x=mathMin(lt[0],rb[0],lb[0],rt[0]);this.y=mathMin(lt[1],rb[1],lb[1],rt[1]);var maxX=mathMax(lt[0],rb[0],lb[0],rt[0]);var maxY=mathMax(lt[1],rb[1],lb[1],rt[1]);this.width=maxX-this.x;this.height=maxY-this.y;};}(),/**\n     * Calculate matrix of transforming from self to target rect\n     * @param  {module:zrender/core/BoundingRect} b\n     * @return {Array.<number>}\n     */calculateTransform:function calculateTransform(b){var a=this;var sx=b.width/a.width;var sy=b.height/a.height;var m=create$1();// 矩阵右乘\ntranslate(m,m,[-a.x,-a.y]);scale$1(m,m,[sx,sy]);translate(m,m,[b.x,b.y]);return m;},/**\n     * @param {(module:echarts/core/BoundingRect|Object)} b\n     * @return {boolean}\n     */intersect:function intersect(b){if(!b){return false;}if(!(b instanceof BoundingRect)){// Normalize negative width/height.\nb=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;return!(ax1<bx0||bx1<ax0||ay1<by0||by1<ay0);},contain:function contain(x,y){var rect=this;return x>=rect.x&&x<=rect.x+rect.width&&y>=rect.y&&y<=rect.y+rect.height;},/**\n     * @return {module:echarts/core/BoundingRect}\n     */clone:function clone(){return new BoundingRect(this.x,this.y,this.width,this.height);},/**\n     * Copy from another rect\n     */copy:function copy(other){this.x=other.x;this.y=other.y;this.width=other.width;this.height=other.height;},plain:function plain(){return{x:this.x,y:this.y,width:this.width,height:this.height};}};/**\n * @param {Object|module:zrender/core/BoundingRect} rect\n * @param {number} rect.x\n * @param {number} rect.y\n * @param {number} rect.width\n * @param {number} rect.height\n * @return {module:zrender/core/BoundingRect}\n */BoundingRect.create=function(rect){return new BoundingRect(rect.x,rect.y,rect.width,rect.height);};/**\n * Group是一个容器，可以插入子节点，Group的变换也会被应用到子节点上\n * @module zrender/graphic/Group\n * @example\n *     var Group = require('zrender/container/Group');\n *     var Circle = require('zrender/graphic/shape/Circle');\n *     var g = new Group();\n *     g.position[0] = 100;\n *     g.position[1] = 100;\n *     g.add(new Circle({\n *         style: {\n *             x: 100,\n *             y: 100,\n *             r: 20,\n *         }\n *     }));\n *     zr.add(g);\n */ /**\n * @alias module:zrender/graphic/Group\n * @constructor\n * @extends module:zrender/mixin/Transformable\n * @extends module:zrender/mixin/Eventful\n */var Group=function Group(opts){opts=opts||{};Element.call(this,opts);for(var key in opts){if(opts.hasOwnProperty(key)){this[key]=opts[key];}}this._children=[];this.__storage=null;this.__dirty=true;};Group.prototype={constructor:Group,isGroup:true,/**\n     * @type {string}\n     */type:'group',/**\n     * 所有子孙元素是否响应鼠标事件\n     * @name module:/zrender/container/Group#silent\n     * @type {boolean}\n     * @default false\n     */silent:false,/**\n     * @return {Array.<module:zrender/Element>}\n     */children:function children(){return this._children.slice();},/**\n     * 获取指定 index 的儿子节点\n     * @param  {number} idx\n     * @return {module:zrender/Element}\n     */childAt:function childAt(idx){return this._children[idx];},/**\n     * 获取指定名字的儿子节点\n     * @param  {string} name\n     * @return {module:zrender/Element}\n     */childOfName:function childOfName(name){var children=this._children;for(var i=0;i<children.length;i++){if(children[i].name===name){return children[i];}}},/**\n     * @return {number}\n     */childCount:function childCount(){return this._children.length;},/**\n     * 添加子节点到最后\n     * @param {module:zrender/Element} child\n     */add:function add(child){if(child&&child!==this&&child.parent!==this){this._children.push(child);this._doAdd(child);}return this;},/**\n     * 添加子节点在 nextSibling 之前\n     * @param {module:zrender/Element} child\n     * @param {module:zrender/Element} nextSibling\n     */addBefore:function addBefore(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;},_doAdd:function _doAdd(child){if(child.parent){child.parent.remove(child);}child.parent=this;var storage=this.__storage;var zr=this.__zr;if(storage&&storage!==child.__storage){storage.addToStorage(child);if(child instanceof Group){child.addChildrenToStorage(storage);}}zr&&zr.refresh();},/**\n     * 移除子节点\n     * @param {module:zrender/Element} child\n     */remove:function remove(child){var zr=this.__zr;var storage=this.__storage;var children=this._children;var idx=indexOf(children,child);if(idx<0){return this;}children.splice(idx,1);child.parent=null;if(storage){storage.delFromStorage(child);if(child instanceof Group){child.delChildrenFromStorage(storage);}}zr&&zr.refresh();return this;},/**\n     * 移除所有子节点\n     */removeAll:function removeAll(){var children=this._children;var storage=this.__storage;var child;var i;for(i=0;i<children.length;i++){child=children[i];if(storage){storage.delFromStorage(child);if(child instanceof Group){child.delChildrenFromStorage(storage);}}child.parent=null;}children.length=0;return this;},/**\n     * 遍历所有子节点\n     * @param  {Function} cb\n     * @param  {}   context\n     */eachChild:function eachChild(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;},/**\n     * 深度优先遍历所有子孙节点\n     * @param  {Function} cb\n     * @param  {}   context\n     */traverse:function traverse(cb,context){for(var i=0;i<this._children.length;i++){var child=this._children[i];cb.call(context,child);if(child.type==='group'){child.traverse(cb,context);}}return this;},addChildrenToStorage:function addChildrenToStorage(storage){for(var i=0;i<this._children.length;i++){var child=this._children[i];storage.addToStorage(child);if(child instanceof Group){child.addChildrenToStorage(storage);}}},delChildrenFromStorage:function delChildrenFromStorage(storage){for(var i=0;i<this._children.length;i++){var child=this._children[i];storage.delFromStorage(child);if(child instanceof Group){child.delChildrenFromStorage(storage);}}},dirty:function dirty(){this.__dirty=true;this.__zr&&this.__zr.refresh();return this;},/**\n     * @return {module:zrender/core/BoundingRect}\n     */getBoundingRect:function getBoundingRect(includeChildren){// TODO Caching\nvar rect=null;var tmpRect=new BoundingRect(0,0,0,0);var children=includeChildren||this._children;var tmpMat=[];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);// TODO\n// The boundingRect cacluated by transforming original\n// rect may be bigger than the actual bundingRect when rotation\n// is used. (Consider a circle rotated aginst its center, where\n// the actual boundingRect should be the same as that not be\n// rotated.) But we can not find better approach to calculate\n// actual boundingRect yet, considering performance.\nif(transform){tmpRect.copy(childRect);tmpRect.applyTransform(transform);rect=rect||tmpRect.clone();rect.union(tmpRect);}else{rect=rect||childRect.clone();rect.union(childRect);}}return rect||tmpRect;}};inherits(Group,Element);// https://github.com/mziccard/node-timsort\nvar 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 runStart;var runLength;var stackSize=0;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();// throw new Error('mergeLow preconditions were not respected');\n}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();// throw new Error('mergeHigh preconditions were not respected');\n}else{customCursor=dest-(length2-1);for(i=0;i<length2;i++){array[customCursor+i]=tmp[i];}}}this.mergeRuns=mergeRuns;this.forceMergeRuns=forceMergeRuns;this.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=new 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();}// Use timsort because in most case elements are partially sorted\n// https://jsfiddle.net/pissang/jr4x7mdm/8/\nfunction shapeCompareFunc(a,b){if(a.zlevel===b.zlevel){if(a.z===b.z){// if (a.z2 === b.z2) {\n//     // FIXME Slow has renderidx compare\n//     // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement\n//     // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012\n//     return a.__renderidx - b.__renderidx;\n// }\nreturn a.z2-b.z2;}return a.z-b.z;}return a.zlevel-b.zlevel;}/**\n * 内容仓库 (M)\n * @alias module:zrender/Storage\n * @constructor\n */var Storage=function Storage(){// jshint ignore:line\nthis._roots=[];this._displayList=[];this._displayListLen=0;};Storage.prototype={constructor:Storage,/**\n     * @param  {Function} cb\n     *\n     */traverse:function traverse(cb,context){for(var i=0;i<this._roots.length;i++){this._roots[i].traverse(cb,context);}},/**\n     * 返回所有图形的绘制队列\n     * @param {boolean} [update=false] 是否在返回前更新该数组\n     * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效\n     *\n     * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}\n     * @return {Array.<module:zrender/graphic/Displayable>}\n     */getDisplayList:function getDisplayList(update,includeIgnore){includeIgnore=includeIgnore||false;if(update){this.updateDisplayList(includeIgnore);}return this._displayList;},/**\n     * 更新图形的绘制队列。\n     * 每次绘制前都会调用，该方法会先深度优先遍历整个树，更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中，\n     * 最后根据绘制的优先级（zlevel > z > 插入顺序）排序得到绘制队列\n     * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组\n     */updateDisplayList:function updateDisplayList(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$1.canvasSupported&&sort(displayList,shapeCompareFunc);},_updateAndAddDisplayable:function _updateAndAddDisplayable(el,clipPaths,includeIgnore){if(el.ignore&&!includeIgnore){return;}el.beforeUpdate();if(el.__dirty){el.update();}el.afterUpdate();var userSetClipPath=el.clipPath;if(userSetClipPath){// FIXME 效率影响\nif(clipPaths){clipPaths=clipPaths.slice();}else{clipPaths=[];}var currentClipPath=userSetClipPath;var parentClipPath=el;// Recursively add clip path\nwhile(currentClipPath){// clipPath 的变换是基于使用这个 clipPath 的元素\ncurrentClipPath.parent=parentClipPath;currentClipPath.updateTransform();clipPaths.push(currentClipPath);parentClipPath=currentClipPath;currentClipPath=currentClipPath.clipPath;}}if(el.isGroup){var children=el._children;for(var i=0;i<children.length;i++){var child=children[i];// Force to mark as dirty if group is dirty\n// FIXME __dirtyPath ?\nif(el.__dirty){child.__dirty=true;}this._updateAndAddDisplayable(child,clipPaths,includeIgnore);}// Mark group clean here\nel.__dirty=false;}else{el.__clipPaths=clipPaths;this._displayList[this._displayListLen++]=el;}},/**\n     * 添加图形(Shape)或者组(Group)到根节点\n     * @param {module:zrender/Element} el\n     */addRoot:function addRoot(el){if(el.__storage===this){return;}if(el instanceof Group){el.addChildrenToStorage(this);}this.addToStorage(el);this._roots.push(el);},/**\n     * 删除指定的图形(Shape)或者组(Group)\n     * @param {string|Array.<string>} [el] 如果为空清空整个Storage\n     */delRoot:function delRoot(el){if(el==null){// 不指定el清空\nfor(var i=0;i<this._roots.length;i++){var root=this._roots[i];if(root instanceof Group){root.delChildrenFromStorage(this);}}this._roots=[];this._displayList=[];this._displayListLen=0;return;}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.delFromStorage(el);this._roots.splice(idx,1);if(el instanceof Group){el.delChildrenFromStorage(this);}}},addToStorage:function addToStorage(el){if(el){el.__storage=this;el.dirty(false);}return this;},delFromStorage:function delFromStorage(el){if(el){el.__storage=null;}return this;},/**\n     * 清空并且释放Storage\n     */dispose:function dispose(){this._renderList=this._roots=null;},displayableSortFunc:shapeCompareFunc};var SHADOW_PROPS={'shadowBlur':1,'shadowOffsetX':1,'shadowOffsetY':1,'textShadowBlur':1,'textShadowOffsetX':1,'textShadowOffsetY':1,'textBoxShadowBlur':1,'textBoxShadowOffsetX':1,'textBoxShadowOffsetY':1};var fixShadow=function fixShadow(ctx,propName,value){if(SHADOW_PROPS.hasOwnProperty(propName)){return value*=ctx.dpr;}return value;};var ContextCachedBy={NONE:0,STYLE_BIND:1,PLAIN_TEXT:2};// Avoid confused with 0/false.\nvar WILL_BE_RESTORED=9;var STYLE_COMMON_PROPS=[['shadowBlur',0],['shadowOffsetX',0],['shadowOffsetY',0],['shadowColor','#000'],['lineCap','butt'],['lineJoin','miter'],['miterLimit',10]];// var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4);\n// var LINE_PROPS = STYLE_COMMON_PROPS.slice(4);\nvar Style=function Style(opts){this.extendFrom(opts,false);};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;}// Fix NaN when rect is Infinity\nx=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;}Style.prototype={constructor:Style,/**\n     * @type {string}\n     */fill:'#000',/**\n     * @type {string}\n     */stroke:null,/**\n     * @type {number}\n     */opacity:1,/**\n     * @type {number}\n     */fillOpacity:null,/**\n     * @type {number}\n     */strokeOpacity:null,/**\n     * `true` is not supported.\n     * `false`/`null`/`undefined` are the same.\n     * `false` is used to remove lineDash in some\n     * case that `null`/`undefined` can not be set.\n     * (e.g., emphasis.lineStyle in echarts)\n     * @type {Array.<number>|boolean}\n     */lineDash:null,/**\n     * @type {number}\n     */lineDashOffset:0,/**\n     * @type {number}\n     */shadowBlur:0,/**\n     * @type {number}\n     */shadowOffsetX:0,/**\n     * @type {number}\n     */shadowOffsetY:0,/**\n     * @type {number}\n     */lineWidth:1,/**\n     * If stroke ignore scale\n     * @type {Boolean}\n     */strokeNoScale:false,// Bounding rect text configuration\n// Not affected by element transform\n/**\n     * @type {string}\n     */text:null,/**\n     * If `fontSize` or `fontFamily` exists, `font` will be reset by\n     * `fontSize`, `fontStyle`, `fontWeight`, `fontFamily`.\n     * So do not visit it directly in upper application (like echarts),\n     * but use `contain/text#makeFont` instead.\n     * @type {string}\n     */font:null,/**\n     * The same as font. Use font please.\n     * @deprecated\n     * @type {string}\n     */textFont:null,/**\n     * It helps merging respectively, rather than parsing an entire font string.\n     * @type {string}\n     */fontStyle:null,/**\n     * It helps merging respectively, rather than parsing an entire font string.\n     * @type {string}\n     */fontWeight:null,/**\n     * It helps merging respectively, rather than parsing an entire font string.\n     * Should be 12 but not '12px'.\n     * @type {number}\n     */fontSize:null,/**\n     * It helps merging respectively, rather than parsing an entire font string.\n     * @type {string}\n     */fontFamily:null,/**\n     * Reserved for special functinality, like 'hr'.\n     * @type {string}\n     */textTag:null,/**\n     * @type {string}\n     */textFill:'#000',/**\n     * @type {string}\n     */textStroke:null,/**\n     * @type {number}\n     */textWidth:null,/**\n     * Only for textBackground.\n     * @type {number}\n     */textHeight:null,/**\n     * textStroke may be set as some color as a default\n     * value in upper applicaion, where the default value\n     * of textStrokeWidth should be 0 to make sure that\n     * user can choose to do not use text stroke.\n     * @type {number}\n     */textStrokeWidth:0,/**\n     * @type {number}\n     */textLineHeight:null,/**\n     * 'inside', 'left', 'right', 'top', 'bottom'\n     * [x, y]\n     * Based on x, y of rect.\n     * @type {string|Array.<number>}\n     * @default 'inside'\n     */textPosition:'inside',/**\n     * If not specified, use the boundingRect of a `displayable`.\n     * @type {Object}\n     */textRect:null,/**\n     * [x, y]\n     * @type {Array.<number>}\n     */textOffset:null,/**\n     * @type {string}\n     */textAlign:null,/**\n     * @type {string}\n     */textVerticalAlign:null,/**\n     * @type {number}\n     */textDistance:5,/**\n     * @type {string}\n     */textShadowColor:'transparent',/**\n     * @type {number}\n     */textShadowBlur:0,/**\n     * @type {number}\n     */textShadowOffsetX:0,/**\n     * @type {number}\n     */textShadowOffsetY:0,/**\n     * @type {string}\n     */textBoxShadowColor:'transparent',/**\n     * @type {number}\n     */textBoxShadowBlur:0,/**\n     * @type {number}\n     */textBoxShadowOffsetX:0,/**\n     * @type {number}\n     */textBoxShadowOffsetY:0,/**\n     * Whether transform text.\n     * Only available in Path and Image element,\n     * where the text is called as `RectText`.\n     * @type {boolean}\n     */transformText:false,/**\n     * Text rotate around position of Path or Image.\n     * The origin of the rotation can be specified by `textOrigin`.\n     * Only available in Path and Image element,\n     * where the text is called as `RectText`.\n     */textRotation:0,/**\n     * Text origin of text rotation.\n     * Useful in the case like label rotation of circular symbol.\n     * Only available in Path and Image element, where the text is called\n     * as `RectText` and the element is called as \"host element\".\n     * The value can be:\n     * + If specified as a coordinate like `[10, 40]`, it is the `[x, y]`\n     * base on the left-top corner of the rect of its host element.\n     * + If specified as a string `center`, it is the center of the rect of\n     * its host element.\n     * + By default, this origin is the `textPosition`.\n     * @type {string|Array.<number>}\n     */textOrigin:null,/**\n     * @type {string}\n     */textBackgroundColor:null,/**\n     * @type {string}\n     */textBorderColor:null,/**\n     * @type {number}\n     */textBorderWidth:0,/**\n     * @type {number}\n     */textBorderRadius:0,/**\n     * Can be `2` or `[2, 4]` or `[2, 3, 4, 5]`\n     * @type {number|Array.<number>}\n     */textPadding:null,/**\n     * Text styles for rich text.\n     * @type {Object}\n     */rich:null,/**\n     * {outerWidth, outerHeight, ellipsis, placeholder}\n     * @type {Object}\n     */truncate:null,/**\n     * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation\n     * @type {string}\n     */blend:null,/**\n     * @param {CanvasRenderingContext2D} ctx\n     */bind:function bind(ctx,el,prevEl){var style=this;var prevStyle=prevEl&&prevEl.style;// If no prevStyle, it means first draw.\n// Only apply cache if the last time cachced by this function.\nvar notCheckCache=!prevStyle||ctx.__attrCachedBy!==ContextCachedBy.STYLE_BIND;ctx.__attrCachedBy=ContextCachedBy.STYLE_BIND;for(var i=0;i<STYLE_COMMON_PROPS.length;i++){var prop=STYLE_COMMON_PROPS[i];var styleName=prop[0];if(notCheckCache||style[styleName]!==prevStyle[styleName]){// FIXME Invalid property value will cause style leak from previous element.\nctx[styleName]=fixShadow(ctx,styleName,style[styleName]||prop[1]);}}if(notCheckCache||style.fill!==prevStyle.fill){ctx.fillStyle=style.fill;}if(notCheckCache||style.stroke!==prevStyle.stroke){ctx.strokeStyle=style.stroke;}if(notCheckCache||style.opacity!==prevStyle.opacity){ctx.globalAlpha=style.opacity==null?1:style.opacity;}if(notCheckCache||style.blend!==prevStyle.blend){ctx.globalCompositeOperation=style.blend||'source-over';}if(this.hasStroke()){var lineWidth=style.lineWidth;ctx.lineWidth=lineWidth/(this.strokeNoScale&&el&&el.getLineScale?el.getLineScale():1);}},hasFill:function hasFill(){var fill=this.fill;return fill!=null&&fill!=='none';},hasStroke:function hasStroke(){var stroke=this.stroke;return stroke!=null&&stroke!=='none'&&this.lineWidth>0;},/**\n     * Extend from other style\n     * @param {zrender/graphic/Style} otherStyle\n     * @param {boolean} overwrite true: overwrirte any way.\n     *                            false: overwrite only when !target.hasOwnProperty\n     *                            others: overwrite when property is not null/undefined.\n     */extendFrom:function extendFrom(otherStyle,overwrite){if(otherStyle){for(var name in otherStyle){if(otherStyle.hasOwnProperty(name)&&(overwrite===true||(overwrite===false?!this.hasOwnProperty(name):otherStyle[name]!=null))){this[name]=otherStyle[name];}}}},/**\n     * Batch setting style with a given object\n     * @param {Object|string} obj\n     * @param {*} [obj]\n     */set:function set(obj,value){if(typeof obj==='string'){this[obj]=value;}else{this.extendFrom(obj,true);}},/**\n     * Clone\n     * @return {zrender/graphic/Style} [description]\n     */clone:function clone(){var newStyle=new this.constructor();newStyle.extendFrom(this,true);return newStyle;},getGradient:function getGradient(ctx,obj,rect){var method=obj.type==='radial'?createRadialGradient:createLinearGradient;var canvasGradient=method(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;}};var styleProto=Style.prototype;for(var i=0;i<STYLE_COMMON_PROPS.length;i++){var prop=STYLE_COMMON_PROPS[i];if(!(prop[0]in styleProto)){styleProto[prop[0]]=prop[1];}}// Provide for others\nStyle.getGradient=styleProto.getGradient;var Pattern=function Pattern(image,repeat){// Should do nothing more in this constructor. Because gradient can be\n// declard by `color: {image: ...}`, where this constructor will not be called.\nthis.image=image;this.repeat=repeat;// Can be cloned\nthis.type='pattern';};Pattern.prototype.getCanvasPattern=function(ctx){return ctx.createPattern(this.image,this.repeat||'repeat');};/**\n * @module zrender/Layer\n * @author pissang(https://www.github.com/pissang)\n */function returnFalse(){return false;}/**\n * 创建dom\n *\n * @inner\n * @param {string} id dom id 待用\n * @param {Painter} painter painter instance\n * @param {number} number\n */function createDom(id,painter,dpr){var newDom=createCanvas();var width=painter.getWidth();var height=painter.getHeight();var newDomStyle=newDom.style;if(newDomStyle){// In node or some other non-browser environment\nnewDomStyle.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;}/**\n * @alias module:zrender/Layer\n * @constructor\n * @extends module:zrender/mixin/Transformable\n * @param {string} id\n * @param {module:zrender/Painter} painter\n * @param {number} [dpr]\n */var Layer=function Layer(id,painter,dpr){var dom;dpr=dpr||devicePixelRatio;if(typeof id==='string'){dom=createDom(id,painter,dpr);}// Not using isDom because in node it will return false\nelse if(isObject$1(id)){dom=id;id=dom.id;}this.id=id;this.dom=dom;var domStyle=dom.style;if(domStyle){// Not in node\ndom.onselectstart=returnFalse;// 避免页面选中的尴尬\ndomStyle['-webkit-user-select']='none';domStyle['user-select']='none';domStyle['-webkit-touch-callout']='none';domStyle['-webkit-tap-highlight-color']='rgba(0,0,0,0)';domStyle['padding']=0;// eslint-disable-line dot-notation\ndomStyle['margin']=0;// eslint-disable-line dot-notation\ndomStyle['border-width']=0;}this.domBack=null;this.ctxBack=null;this.painter=painter;this.config=null;// Configs\n/**\n     * 每次清空画布的颜色\n     * @type {string}\n     * @default 0\n     */this.clearColor=0;/**\n     * 是否开启动态模糊\n     * @type {boolean}\n     * @default false\n     */this.motionBlur=false;/**\n     * 在开启动态模糊的时候使用，与上一帧混合的alpha值，值越大尾迹越明显\n     * @type {number}\n     * @default 0.7\n     */this.lastFrameAlpha=0.7;/**\n     * Layer dpr\n     * @type {number}\n     */this.dpr=dpr;};Layer.prototype={constructor:Layer,__dirty:true,__used:false,__drawIndex:0,__startIndex:0,__endIndex:0,incremental:false,getElementCount:function getElementCount(){return this.__endIndex-this.__startIndex;},initContext:function initContext(){this.ctx=this.dom.getContext('2d');this.ctx.dpr=this.dpr;},createBackBuffer:function createBackBuffer(){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);}},/**\n     * @param  {number} width\n     * @param  {number} height\n     */resize:function resize(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);}}},/**\n     * 清空该层画布\n     * @param {boolean} [clearAll]=false Clear all with out motion blur\n     * @param {Color} [clearColor]\n     */clear:function clear(clearAll,clearColor){var dom=this.dom;var ctx=this.ctx;var width=dom.width;var height=dom.height;var clearColor=clearColor||this.clearColor;var haveMotionBLur=this.motionBlur&&!clearAll;var lastFrameAlpha=this.lastFrameAlpha;var dpr=this.dpr;if(haveMotionBLur){if(!this.domBack){this.createBackBuffer();}this.ctxBack.globalCompositeOperation='copy';this.ctxBack.drawImage(dom,0,0,width/dpr,height/dpr);}ctx.clearRect(0,0,width,height);if(clearColor&&clearColor!=='transparent'){var clearColorGradientOrPattern;// Gradient\nif(clearColor.colorStops){// Cache canvas gradient\nclearColorGradientOrPattern=clearColor.__canvasGradient||Style.getGradient(ctx,clearColor,{x:0,y:0,width:width,height:height});clearColor.__canvasGradient=clearColorGradientOrPattern;}// Pattern\nelse if(clearColor.image){clearColorGradientOrPattern=Pattern.prototype.getCanvasPattern.call(clearColor,ctx);}ctx.save();ctx.fillStyle=clearColorGradientOrPattern||clearColor;ctx.fillRect(0,0,width,height);ctx.restore();}if(haveMotionBLur){var domBack=this.domBack;ctx.save();ctx.globalAlpha=lastFrameAlpha;ctx.drawImage(domBack,0,0,width,height);ctx.restore();}}};var requestAnimationFrame=typeof window!=='undefined'&&(window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||// https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809\nwindow.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window)||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame)||function(func){setTimeout(func,16);};var globalImageCache=new LRU(50);/**\n * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc\n * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image\n */function findExistImage(newImageOrSrc){if(typeof newImageOrSrc==='string'){var cachedImgObj=globalImageCache.get(newImageOrSrc);return cachedImgObj&&cachedImgObj.image;}else{return newImageOrSrc;}}/**\n * Caution: User should cache loaded images, but not just count on LRU.\n * Consider if required images more than LRU size, will dead loop occur?\n *\n * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc\n * @param {HTMLImageElement|HTMLCanvasElement|Canvas} image Existent image.\n * @param {module:zrender/Element} [hostEl] For calling `dirty`.\n * @param {Function} [cb] params: (image, cbPayload)\n * @param {Object} [cbPayload] Payload on cb calling.\n * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image\n */function createOrUpdateImage(newImageOrSrc,image,hostEl,cb,cbPayload){if(!newImageOrSrc){return image;}else if(typeof newImageOrSrc==='string'){// Image should not be loaded repeatly.\nif(image&&image.__zrImageSrc===newImageOrSrc||!hostEl){return image;}// Only when there is no existent image or existent image src\n// is different, this method is responsible for load.\nvar cachedImgObj=globalImageCache.get(newImageOrSrc);var pendingWrap={hostEl:hostEl,cb:cb,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;}// newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvas\nelse{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 textWidthCache={};var textWidthCacheCounter=0;var TEXT_CACHE_MAX=5000;var STYLE_REG=/\\{([a-zA-Z0-9_]+)\\|([^}]*)\\}/g;var DEFAULT_FONT$1='12px sans-serif';// Avoid assign to an exported variable, for transforming to cjs.\nvar methods$1={};function $override$1(name,fn){methods$1[name]=fn;}/**\n * @public\n * @param {string} text\n * @param {string} font\n * @return {number} width\n */function getWidth(text,font){font=font||DEFAULT_FONT$1;var key=text+':'+font;if(textWidthCache[key]){return textWidthCache[key];}var textLines=(text+'').split('\\n');var width=0;for(var i=0,l=textLines.length;i<l;i++){// textContain.measureText may be overrided in SVG or VML\nwidth=Math.max(measureText(textLines[i],font).width,width);}if(textWidthCacheCounter>TEXT_CACHE_MAX){textWidthCacheCounter=0;textWidthCache={};}textWidthCacheCounter++;textWidthCache[key]=width;return width;}/**\n * @public\n * @param {string} text\n * @param {string} font\n * @param {string} [textAlign='left']\n * @param {string} [textVerticalAlign='top']\n * @param {Array.<number>} [textPadding]\n * @param {Object} [rich]\n * @param {Object} [truncate]\n * @return {Object} {x, y, width, height, lineHeight}\n */function _getBoundingRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,rich,truncate){return rich?getRichTextRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,rich,truncate):getPlainTextRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,truncate);}function getPlainTextRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,truncate){var contentBlock=parsePlainText(text,font,textPadding,textLineHeight,truncate);var outerWidth=getWidth(text,font);if(textPadding){outerWidth+=textPadding[1]+textPadding[3];}var outerHeight=contentBlock.outerHeight;var x=adjustTextX(0,outerWidth,textAlign);var y=adjustTextY(0,outerHeight,textVerticalAlign);var rect=new BoundingRect(x,y,outerWidth,outerHeight);rect.lineHeight=contentBlock.lineHeight;return rect;}function getRichTextRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,rich,truncate){var contentBlock=parseRichText(text,{rich:rich,truncate:truncate,font:font,textAlign:textAlign,textPadding:textPadding,textLineHeight:textLineHeight});var outerWidth=contentBlock.outerWidth;var outerHeight=contentBlock.outerHeight;var x=adjustTextX(0,outerWidth,textAlign);var y=adjustTextY(0,outerHeight,textVerticalAlign);return new BoundingRect(x,y,outerWidth,outerHeight);}/**\n * @public\n * @param {number} x\n * @param {number} width\n * @param {string} [textAlign='left']\n * @return {number} Adjusted x.\n */function adjustTextX(x,width,textAlign){// FIXME Right to left language\nif(textAlign==='right'){x-=width;}else if(textAlign==='center'){x-=width/2;}return x;}/**\n * @public\n * @param {number} y\n * @param {number} height\n * @param {string} [textVerticalAlign='top']\n * @return {number} Adjusted y.\n */function adjustTextY(y,height,textVerticalAlign){if(textVerticalAlign==='middle'){y-=height/2;}else if(textVerticalAlign==='bottom'){y-=height;}return y;}/**\n * Follow same interface to `Displayable.prototype.calculateTextPosition`.\n * @public\n * @param {Obejct} [out] Prepared out object. If not input, auto created in the method.\n * @param {module:zrender/graphic/Style} style where `textPosition` and `textDistance` are visited.\n * @param {Object} rect {x, y, width, height} Rect of the host elment, according to which the text positioned.\n * @return {Object} The input `out`. Set: {x, y, textAlign, textVerticalAlign}\n */function _calculateTextPosition(out,style,rect){var textPosition=style.textPosition;var distance=style.textDistance;var x=rect.x;var y=rect.y;distance=distance||0;var height=rect.height;var width=rect.width;var halfHeight=height/2;var textAlign='left';var textVerticalAlign='top';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.textAlign=textAlign;out.textVerticalAlign=textVerticalAlign;return out;}/**\n * To be removed. But still do not remove in case that some one has imported it.\n * @deprecated\n * @public\n * @param {stirng} textPosition\n * @param {Object} rect {x, y, width, height}\n * @param {number} distance\n * @return {Object} {x, y, textAlign, textVerticalAlign}\n */ /**\n * Show ellipsis if overflow.\n *\n * @public\n * @param  {string} text\n * @param  {string} containerWidth\n * @param  {string} font\n * @param  {number} [ellipsis='...']\n * @param  {Object} [options]\n * @param  {number} [options.maxIterations=3]\n * @param  {number} [options.minChar=0] If truncate result are less\n *                  then minChar, ellipsis will not show, which is\n *                  better for user hint in some cases.\n * @param  {number} [options.placeholder=''] When all truncated, use the placeholder.\n * @return {string}\n */function truncateText(text,containerWidth,font,ellipsis,options){if(!containerWidth){return'';}var textLines=(text+'').split('\\n');options=prepareTruncateOptions(containerWidth,font,ellipsis,options);// FIXME\n// It is not appropriate that every line has '...' when truncate multiple lines.\nfor(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=extend({},options);options.font=font;var ellipsis=retrieve2(ellipsis,'...');options.maxIterations=retrieve2(options.maxIterations,2);var minChar=options.minChar=retrieve2(options.minChar,0);// FIXME\n// Other languages?\noptions.cnCharWidth=getWidth('国',font);// FIXME\n// Consider proportional font?\nvar ascCharWidth=options.ascCharWidth=getWidth('a',font);options.placeholder=retrieve2(options.placeholder,'');// Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'.\n// Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'.\nvar contentWidth=containerWidth=Math.max(0,containerWidth-1);// Reserve some gap.\nfor(var i=0;i<minChar&&contentWidth>=ascCharWidth;i++){contentWidth-=ascCharWidth;}var ellipsisWidth=getWidth(ellipsis,font);if(ellipsisWidth>contentWidth){ellipsis='';ellipsisWidth=0;}contentWidth=containerWidth-ellipsisWidth;options.ellipsis=ellipsis;options.ellipsisWidth=ellipsisWidth;options.contentWidth=contentWidth;options.containerWidth=containerWidth;return options;}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;}/**\n * @public\n * @param {string} font\n * @return {number} line height\n */function getLineHeight(font){// FIXME A rough approach.\nreturn getWidth('国',font);}/**\n * @public\n * @param {string} text\n * @param {string} font\n * @return {Object} width\n */function measureText(text,font){return methods$1.measureText(text,font);}// Avoid assign to an exported variable, for transforming to cjs.\nmethods$1.measureText=function(text,font){var ctx=getContext();ctx.font=font||DEFAULT_FONT$1;return ctx.measureText(text);};/**\n * @public\n * @param {string} text\n * @param {string} font\n * @param {Object} [truncate]\n * @return {Object} block: {lineHeight, lines, height, outerHeight, canCacheByTextString}\n *  Notice: for performance, do not calculate outerWidth util needed.\n *  `canCacheByTextString` means the result `lines` is only determined by the input `text`.\n *  Thus we can simply comparing the `input` text to determin whether the result changed,\n *  without travel the result `lines`.\n */function parsePlainText(text,font,padding,textLineHeight,truncate){text!=null&&(text+='');var lineHeight=retrieve2(textLineHeight,getLineHeight(font));var lines=text?text.split('\\n'):[];var height=lines.length*lineHeight;var outerHeight=height;var canCacheByTextString=true;if(padding){outerHeight+=padding[0]+padding[2];}if(text&&truncate){canCacheByTextString=false;var truncOuterHeight=truncate.outerHeight;var truncOuterWidth=truncate.outerWidth;if(truncOuterHeight!=null&&outerHeight>truncOuterHeight){text='';lines=[];}else if(truncOuterWidth!=null){var options=prepareTruncateOptions(truncOuterWidth-(padding?padding[1]+padding[3]:0),font,truncate.ellipsis,{minChar:truncate.minChar,placeholder:truncate.placeholder});// FIXME\n// It is not appropriate that every line has '...' when truncate multiple lines.\nfor(var i=0,len=lines.length;i<len;i++){lines[i]=truncateSingleLine(lines[i],options);}}}return{lines:lines,height:height,outerHeight:outerHeight,lineHeight:lineHeight,canCacheByTextString:canCacheByTextString};}/**\n * For example: 'some text {a|some text}other text{b|some text}xxx{c|}xxx'\n * Also consider 'bbbb{a|xxx\\nzzz}xxxx\\naaaa'.\n *\n * @public\n * @param {string} text\n * @param {Object} style\n * @return {Object} block\n * {\n *      width,\n *      height,\n *      lines: [{\n *          lineHeight,\n *          width,\n *          tokens: [[{\n *              styleName,\n *              text,\n *              width,      // include textPadding\n *              height,     // include textPadding\n *              textWidth, // pure text width\n *              textHeight, // pure text height\n *              lineHeihgt,\n *              font,\n *              textAlign,\n *              textVerticalAlign\n *          }], [...], ...]\n *      }, ...]\n * }\n * If styleName is undefined, it is plain text.\n */function parseRichText(text,style){var contentBlock={lines:[],width:0,height:0};text!=null&&(text+='');if(!text){return contentBlock;}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));}pushTokens(contentBlock,result[2],result[1]);lastIndex=STYLE_REG.lastIndex;}if(lastIndex<text.length){pushTokens(contentBlock,text.substring(lastIndex,text.length));}var lines=contentBlock.lines;var contentHeight=0;var contentWidth=0;// For `textWidth: 100%`\nvar pendingList=[];var stlPadding=style.textPadding;var truncate=style.truncate;var truncateWidth=truncate&&truncate.outerWidth;var truncateHeight=truncate&&truncate.outerHeight;if(stlPadding){truncateWidth!=null&&(truncateWidth-=stlPadding[1]+stlPadding[3]);truncateHeight!=null&&(truncateHeight-=stlPadding[0]+stlPadding[2]);}// Calculate layout info of tokens.\nfor(var i=0;i<lines.length;i++){var line=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]||{};// textPadding should not inherit from style.\nvar textPadding=token.textPadding=tokenStyle.textPadding;// textFont has been asigned to font by `normalizeStyle`.\nvar font=token.font=tokenStyle.font||style.font;// textHeight can be used when textVerticalAlign is specified in token.\nvar tokenHeight=token.textHeight=retrieve2(// textHeight should not be inherited, consider it can be specified\n// as box height of the block.\ntokenStyle.textHeight,getLineHeight(font));textPadding&&(tokenHeight+=textPadding[0]+textPadding[2]);token.height=tokenHeight;token.lineHeight=retrieve3(tokenStyle.textLineHeight,style.textLineHeight,tokenHeight);token.textAlign=tokenStyle&&tokenStyle.textAlign||style.textAlign;token.textVerticalAlign=tokenStyle&&tokenStyle.textVerticalAlign||'middle';if(truncateHeight!=null&&contentHeight+token.lineHeight>truncateHeight){return{lines:[],width:0,height:0};}token.textWidth=getWidth(token.text,font);var tokenWidth=tokenStyle.textWidth;var tokenWidthNotSpecified=tokenWidth==null||tokenWidth==='auto';// Percent width, can be `100%`, can be used in drawing separate\n// line when box width is needed to be auto.\nif(typeof tokenWidth==='string'&&tokenWidth.charAt(tokenWidth.length-1)==='%'){token.percentWidth=tokenWidth;pendingList.push(token);tokenWidth=0;// Do not truncate in this case, because there is no user case\n// and it is too complicated.\n}else{if(tokenWidthNotSpecified){tokenWidth=token.textWidth;// FIXME: If image is not loaded and textWidth is not specified, calling\n// `getBoundingRect()` will not get correct result.\nvar textBackgroundColor=tokenStyle.textBackgroundColor;var bgImg=textBackgroundColor&&textBackgroundColor.image;// Use cases:\n// (1) If image is not loaded, it will be loaded at render phase and call\n// `dirty()` and `textBackgroundColor.image` will be replaced with the loaded\n// image, and then the right size will be calculated here at the next tick.\n// See `graphic/helper/text.js`.\n// (2) If image loaded, and `textBackgroundColor.image` is image src string,\n// use `imageHelper.findExistImage` to find cached image.\n// `imageHelper.findExistImage` will always be called here before\n// `imageHelper.createOrUpdateImage` in `graphic/helper/text.js#renderRichText`\n// which ensures that image will not be rendered before correct size calcualted.\nif(bgImg){bgImg=findExistImage(bgImg);if(isImageReady(bgImg)){tokenWidth=Math.max(tokenWidth,bgImg.width*tokenHeight/bgImg.height);}}}var paddingW=textPadding?textPadding[1]+textPadding[3]:0;tokenWidth+=paddingW;var remianTruncWidth=truncateWidth!=null?truncateWidth-lineWidth:null;if(remianTruncWidth!=null&&remianTruncWidth<tokenWidth){if(!tokenWidthNotSpecified||remianTruncWidth<paddingW){token.text='';token.textWidth=tokenWidth=0;}else{token.text=truncateText(token.text,remianTruncWidth-paddingW,font,truncate.ellipsis,{minChar:truncate.minChar});token.textWidth=getWidth(token.text,font);tokenWidth=token.textWidth+paddingW;}}}lineWidth+=token.width=tokenWidth;tokenStyle&&(lineHeight=Math.max(lineHeight,token.lineHeight));}line.width=lineWidth;line.lineHeight=lineHeight;contentHeight+=lineHeight;contentWidth=Math.max(contentWidth,lineWidth);}contentBlock.outerWidth=contentBlock.width=retrieve2(style.textWidth,contentWidth);contentBlock.outerHeight=contentBlock.height=retrieve2(style.textHeight,contentHeight);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;// Should not base on outerWidth, because token can not be placed out of padding.\ntoken.width=parseInt(percentWidth,10)/100*contentWidth;}return contentBlock;}function pushTokens(block,str,styleName){var isEmptyStr=str==='';var strs=str.split('\\n');var lines=block.lines;for(var i=0;i<strs.length;i++){var text=strs[i];var token={styleName:styleName,text:text,isLineHolder:!text&&!isEmptyStr};// The first token should be appended to the last line.\nif(!i){var tokens=(lines[lines.length-1]||(lines[0]={tokens:[]})).tokens;// Consider cases:\n// (1) ''.split('\\n') => ['', '\\n', ''], the '' at the first item\n// (which is a placeholder) should be replaced by new token.\n// (2) A image backage, where token likes {a|}.\n// (3) A redundant '' will affect textAlign in line.\n// (4) tokens with the same tplName should not be merged, because\n// they should be displayed in different box (with border and padding).\nvar tokensLen=tokens.length;tokensLen===1&&tokens[0].isLineHolder?tokens[0]=token:// Consider text is '', only insert when it is the \"lineHolder\" or\n// \"emptyStr\". Otherwise a redundant '' will affect textAlign in line.\n(text||!tokensLen||isEmptyStr)&&tokens.push(token);}// Other tokens always start a new line.\nelse{// If there is '', insert it as a placeholder.\nlines.push({tokens:[token]});}}}function makeFont(style){// FIXME in node-canvas fontWeight is before fontStyle\n// Use `fontSize` `fontFamily` to check whether font properties are defined.\nvar font=(style.fontSize||style.fontFamily)&&[style.fontStyle,style.fontWeight,(style.fontSize||12)+'px',// If font properties are defined, `fontFamily` should not be ignored.\nstyle.fontFamily||'sans-serif'].join(' ');return font&&trim(font)||style.textFont||style.font;}/**\n * @param {Object} ctx\n * @param {Object} shape\n * @param {number} shape.x\n * @param {number} shape.y\n * @param {number} shape.width\n * @param {number} shape.height\n * @param {number} shape.r\n */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;// Convert width and height to positive for better borderRadius\nif(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 DEFAULT_FONT=DEFAULT_FONT$1;// TODO: Have not support 'start', 'end' yet.\nvar VALID_TEXT_ALIGN={left:1,right:1,center:1};var VALID_TEXT_VERTICAL_ALIGN={top:1,bottom:1,middle:1};// Different from `STYLE_COMMON_PROPS` of `graphic/Style`,\n// the default value of shadowColor is `'transparent'`.\nvar SHADOW_STYLE_COMMON_PROPS=[['textShadowBlur','shadowBlur',0],['textShadowOffsetX','shadowOffsetX',0],['textShadowOffsetY','shadowOffsetY',0],['textShadowColor','shadowColor','transparent']];var _tmpTextPositionResult={};var _tmpBoxPositionResult={};/**\n * @param {module:zrender/graphic/Style} style\n * @return {module:zrender/graphic/Style} The input style.\n */function normalizeTextStyle(style){normalizeStyle(style);each$1(style.rich,normalizeStyle);return style;}function normalizeStyle(style){if(style){style.font=makeFont(style);var textAlign=style.textAlign;textAlign==='middle'&&(textAlign='center');style.textAlign=textAlign==null||VALID_TEXT_ALIGN[textAlign]?textAlign:'left';// Compatible with textBaseline.\nvar textVerticalAlign=style.textVerticalAlign||style.textBaseline;textVerticalAlign==='center'&&(textVerticalAlign='middle');style.textVerticalAlign=textVerticalAlign==null||VALID_TEXT_VERTICAL_ALIGN[textVerticalAlign]?textVerticalAlign:'top';var textPadding=style.textPadding;if(textPadding){style.textPadding=normalizeCssArray(style.textPadding);}}}/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {string} text\n * @param {module:zrender/graphic/Style} style\n * @param {Object|boolean} [rect] {x, y, width, height}\n *                  If set false, rect text is not used.\n * @param {Element|module:zrender/graphic/helper/constant.WILL_BE_RESTORED} [prevEl] For ctx prop cache.\n */function renderText(hostEl,ctx,text,style,rect,prevEl){style.rich?renderRichText(hostEl,ctx,text,style,rect,prevEl):renderPlainText(hostEl,ctx,text,style,rect,prevEl);}// Avoid setting to ctx according to prevEl if possible for\n// performance in scenarios of large amount text.\nfunction renderPlainText(hostEl,ctx,text,style,rect,prevEl){'use strict';var needDrawBg=needDrawBackground(style);var prevStyle;var checkCache=false;var cachedByMe=ctx.__attrCachedBy===ContextCachedBy.PLAIN_TEXT;// Only take and check cache for `Text` el, but not RectText.\nif(prevEl!==WILL_BE_RESTORED){if(prevEl){prevStyle=prevEl.style;checkCache=!needDrawBg&&cachedByMe&&prevStyle;}// Prevent from using cache in `Style::bind`, because of the case:\n// ctx property is modified by other properties than `Style::bind`\n// used, and Style::bind is called next.\nctx.__attrCachedBy=needDrawBg?ContextCachedBy.NONE:ContextCachedBy.PLAIN_TEXT;}// Since this will be restored, prevent from using these props to check cache in the next\n// entering of this method. But do not need to clear other cache like `Style::bind`.\nelse if(cachedByMe){ctx.__attrCachedBy=ContextCachedBy.NONE;}var styleFont=style.font||DEFAULT_FONT;// PENDING\n// Only `Text` el set `font` and keep it (`RectText` will restore). So theoretically\n// we can make font cache on ctx, which can cache for text el that are discontinuous.\n// But layer save/restore needed to be considered.\n// if (styleFont !== ctx.__fontCache) {\n//     ctx.font = styleFont;\n//     if (prevEl !== WILL_BE_RESTORED) {\n//         ctx.__fontCache = styleFont;\n//     }\n// }\nif(!checkCache||styleFont!==(prevStyle.font||DEFAULT_FONT)){ctx.font=styleFont;}// Use the final font from context-2d, because the final\n// font might not be the style.font when it is illegal.\n// But get `ctx.font` might be time consuming.\nvar computedFont=hostEl.__computedFont;if(hostEl.__styleFont!==styleFont){hostEl.__styleFont=styleFont;computedFont=hostEl.__computedFont=ctx.font;}var textPadding=style.textPadding;var textLineHeight=style.textLineHeight;var contentBlock=hostEl.__textCotentBlock;if(!contentBlock||hostEl.__dirtyText){contentBlock=hostEl.__textCotentBlock=parsePlainText(text,computedFont,textPadding,textLineHeight,style.truncate);}var outerHeight=contentBlock.outerHeight;var textLines=contentBlock.lines;var lineHeight=contentBlock.lineHeight;var boxPos=getBoxPosition(_tmpBoxPositionResult,hostEl,style,rect);var baseX=boxPos.baseX;var baseY=boxPos.baseY;var textAlign=boxPos.textAlign||'left';var textVerticalAlign=boxPos.textVerticalAlign;// Origin of textRotation should be the base point of text drawing.\napplyTextRotation(ctx,style,rect,baseX,baseY);var boxY=adjustTextY(baseY,outerHeight,textVerticalAlign);var textX=baseX;var textY=boxY;if(needDrawBg||textPadding){// Consider performance, do not call getTextWidth util necessary.\nvar textWidth=getWidth(text,computedFont);var outerWidth=textWidth;textPadding&&(outerWidth+=textPadding[1]+textPadding[3]);var boxX=adjustTextX(baseX,outerWidth,textAlign);needDrawBg&&drawBackground(hostEl,ctx,style,boxX,boxY,outerWidth,outerHeight);if(textPadding){textX=getTextXForPadding(baseX,textAlign,textPadding);textY+=textPadding[0];}}// Always set textAlign and textBase line, because it is difficute to calculate\n// textAlign from prevEl, and we dont sure whether textAlign will be reset if\n// font set happened.\nctx.textAlign=textAlign;// Force baseline to be \"middle\". Otherwise, if using \"top\", the\n// text will offset downward a little bit in font \"Microsoft YaHei\".\nctx.textBaseline='middle';// Set text opacity\nctx.globalAlpha=style.opacity||1;// Always set shadowBlur and shadowOffset to avoid leak from displayable.\nfor(var i=0;i<SHADOW_STYLE_COMMON_PROPS.length;i++){var propItem=SHADOW_STYLE_COMMON_PROPS[i];var styleProp=propItem[0];var ctxProp=propItem[1];var val=style[styleProp];if(!checkCache||val!==prevStyle[styleProp]){ctx[ctxProp]=fixShadow(ctx,ctxProp,val||propItem[2]);}}// `textBaseline` is set as 'middle'.\ntextY+=lineHeight/2;var textStrokeWidth=style.textStrokeWidth;var textStrokeWidthPrev=checkCache?prevStyle.textStrokeWidth:null;var strokeWidthChanged=!checkCache||textStrokeWidth!==textStrokeWidthPrev;var strokeChanged=!checkCache||strokeWidthChanged||style.textStroke!==prevStyle.textStroke;var textStroke=getStroke(style.textStroke,textStrokeWidth);var textFill=getFill(style.textFill);if(textStroke){if(strokeWidthChanged){ctx.lineWidth=textStrokeWidth;}if(strokeChanged){ctx.strokeStyle=textStroke;}}if(textFill){if(!checkCache||style.textFill!==prevStyle.textFill){ctx.fillStyle=textFill;}}// Optimize simply, in most cases only one line exists.\nif(textLines.length===1){// Fill after stroke so the outline will not cover the main part.\ntextStroke&&ctx.strokeText(textLines[0],textX,textY);textFill&&ctx.fillText(textLines[0],textX,textY);}else{for(var i=0;i<textLines.length;i++){// Fill after stroke so the outline will not cover the main part.\ntextStroke&&ctx.strokeText(textLines[i],textX,textY);textFill&&ctx.fillText(textLines[i],textX,textY);textY+=lineHeight;}}}function renderRichText(hostEl,ctx,text,style,rect,prevEl){// Do not do cache for rich text because of the complexity.\n// But `RectText` this will be restored, do not need to clear other cache like `Style::bind`.\nif(prevEl!==WILL_BE_RESTORED){ctx.__attrCachedBy=ContextCachedBy.NONE;}var contentBlock=hostEl.__textCotentBlock;if(!contentBlock||hostEl.__dirtyText){contentBlock=hostEl.__textCotentBlock=parseRichText(text,style);}drawRichText(hostEl,ctx,contentBlock,style,rect);}function drawRichText(hostEl,ctx,contentBlock,style,rect){var contentWidth=contentBlock.width;var outerWidth=contentBlock.outerWidth;var outerHeight=contentBlock.outerHeight;var textPadding=style.textPadding;var boxPos=getBoxPosition(_tmpBoxPositionResult,hostEl,style,rect);var baseX=boxPos.baseX;var baseY=boxPos.baseY;var textAlign=boxPos.textAlign;var textVerticalAlign=boxPos.textVerticalAlign;// Origin of textRotation should be the base point of text drawing.\napplyTextRotation(ctx,style,rect,baseX,baseY);var boxX=adjustTextX(baseX,outerWidth,textAlign);var boxY=adjustTextY(baseY,outerHeight,textVerticalAlign);var xLeft=boxX;var lineTop=boxY;if(textPadding){xLeft+=textPadding[3];lineTop+=textPadding[0];}var xRight=xLeft+contentWidth;needDrawBackground(style)&&drawBackground(hostEl,ctx,style,boxX,boxY,outerWidth,outerHeight);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 usedWidth=line.width;var leftIndex=0;var lineXLeft=xLeft;var lineXRight=xRight;var rightIndex=tokenCount-1;var token;while(leftIndex<tokenCount&&(token=tokens[leftIndex],!token.textAlign||token.textAlign==='left')){placeToken(hostEl,ctx,token,style,lineHeight,lineTop,lineXLeft,'left');usedWidth-=token.width;lineXLeft+=token.width;leftIndex++;}while(rightIndex>=0&&(token=tokens[rightIndex],token.textAlign==='right')){placeToken(hostEl,ctx,token,style,lineHeight,lineTop,lineXRight,'right');usedWidth-=token.width;lineXRight-=token.width;rightIndex--;}// The other tokens are placed as textAlign 'center' if there is enough space.\nlineXLeft+=(contentWidth-(lineXLeft-xLeft)-(xRight-lineXRight)-usedWidth)/2;while(leftIndex<=rightIndex){token=tokens[leftIndex];// Consider width specified by user, use 'center' rather than 'left'.\nplaceToken(hostEl,ctx,token,style,lineHeight,lineTop,lineXLeft+token.width/2,'center');lineXLeft+=token.width;leftIndex++;}lineTop+=lineHeight;}}function applyTextRotation(ctx,style,rect,x,y){// textRotation only apply in RectText.\nif(rect&&style.textRotation){var origin=style.textOrigin;if(origin==='center'){x=rect.width/2+rect.x;y=rect.height/2+rect.y;}else if(origin){x=origin[0]+rect.x;y=origin[1]+rect.y;}ctx.translate(x,y);// Positive: anticlockwise\nctx.rotate(-style.textRotation);ctx.translate(-x,-y);}}function placeToken(hostEl,ctx,token,style,lineHeight,lineTop,x,textAlign){var tokenStyle=style.rich[token.styleName]||{};tokenStyle.text=token.text;// 'ctx.textBaseline' is always set as 'middle', for sake of\n// the bias of \"Microsoft YaHei\".\nvar textVerticalAlign=token.textVerticalAlign;var y=lineTop+lineHeight/2;if(textVerticalAlign==='top'){y=lineTop+token.height/2;}else if(textVerticalAlign==='bottom'){y=lineTop+lineHeight-token.height/2;}!token.isLineHolder&&needDrawBackground(tokenStyle)&&drawBackground(hostEl,ctx,tokenStyle,textAlign==='right'?x-token.width:textAlign==='center'?x-token.width/2:x,y-token.height/2,token.width,token.height);var textPadding=token.textPadding;if(textPadding){x=getTextXForPadding(x,textAlign,textPadding);y-=token.height/2-textPadding[2]-token.textHeight/2;}setCtx(ctx,'shadowBlur',retrieve3(tokenStyle.textShadowBlur,style.textShadowBlur,0));setCtx(ctx,'shadowColor',tokenStyle.textShadowColor||style.textShadowColor||'transparent');setCtx(ctx,'shadowOffsetX',retrieve3(tokenStyle.textShadowOffsetX,style.textShadowOffsetX,0));setCtx(ctx,'shadowOffsetY',retrieve3(tokenStyle.textShadowOffsetY,style.textShadowOffsetY,0));setCtx(ctx,'textAlign',textAlign);// Force baseline to be \"middle\". Otherwise, if using \"top\", the\n// text will offset downward a little bit in font \"Microsoft YaHei\".\nsetCtx(ctx,'textBaseline','middle');setCtx(ctx,'font',token.font||DEFAULT_FONT);var textStroke=getStroke(tokenStyle.textStroke||style.textStroke,textStrokeWidth);var textFill=getFill(tokenStyle.textFill||style.textFill);var textStrokeWidth=retrieve2(tokenStyle.textStrokeWidth,style.textStrokeWidth);// Fill after stroke so the outline will not cover the main part.\nif(textStroke){setCtx(ctx,'lineWidth',textStrokeWidth);setCtx(ctx,'strokeStyle',textStroke);ctx.strokeText(token.text,x,y);}if(textFill){setCtx(ctx,'fillStyle',textFill);ctx.fillText(token.text,x,y);}}function needDrawBackground(style){return!!(style.textBackgroundColor||style.textBorderWidth&&style.textBorderColor);}// style: {textBackgroundColor, textBorderWidth, textBorderColor, textBorderRadius, text}\n// shape: {x, y, width, height}\nfunction drawBackground(hostEl,ctx,style,x,y,width,height){var textBackgroundColor=style.textBackgroundColor;var textBorderWidth=style.textBorderWidth;var textBorderColor=style.textBorderColor;var isPlainBg=isString(textBackgroundColor);setCtx(ctx,'shadowBlur',style.textBoxShadowBlur||0);setCtx(ctx,'shadowColor',style.textBoxShadowColor||'transparent');setCtx(ctx,'shadowOffsetX',style.textBoxShadowOffsetX||0);setCtx(ctx,'shadowOffsetY',style.textBoxShadowOffsetY||0);if(isPlainBg||textBorderWidth&&textBorderColor){ctx.beginPath();var textBorderRadius=style.textBorderRadius;if(!textBorderRadius){ctx.rect(x,y,width,height);}else{_buildPath(ctx,{x:x,y:y,width:width,height:height,r:textBorderRadius});}ctx.closePath();}if(isPlainBg){setCtx(ctx,'fillStyle',textBackgroundColor);if(style.fillOpacity!=null){var originalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.fillOpacity*style.opacity;ctx.fill();ctx.globalAlpha=originalGlobalAlpha;}else{ctx.fill();}}else if(isObject$1(textBackgroundColor)){var image=textBackgroundColor.image;image=createOrUpdateImage(image,null,hostEl,onBgImageLoaded,textBackgroundColor);if(image&&isImageReady(image)){ctx.drawImage(image,x,y,width,height);}}if(textBorderWidth&&textBorderColor){setCtx(ctx,'lineWidth',textBorderWidth);setCtx(ctx,'strokeStyle',textBorderColor);if(style.strokeOpacity!=null){var originalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.strokeOpacity*style.opacity;ctx.stroke();ctx.globalAlpha=originalGlobalAlpha;}else{ctx.stroke();}}}function onBgImageLoaded(image,textBackgroundColor){// Replace image, so that `contain/text.js#parseRichText`\n// will get correct result in next tick.\ntextBackgroundColor.image=image;}function getBoxPosition(out,hostEl,style,rect){var baseX=style.x||0;var baseY=style.y||0;var textAlign=style.textAlign;var textVerticalAlign=style.textVerticalAlign;// Text position represented by coord\nif(rect){var textPosition=style.textPosition;if(textPosition instanceof Array){// Percent\nbaseX=rect.x+parsePercent(textPosition[0],rect.width);baseY=rect.y+parsePercent(textPosition[1],rect.height);}else{var res=hostEl&&hostEl.calculateTextPosition?hostEl.calculateTextPosition(_tmpTextPositionResult,style,rect):_calculateTextPosition(_tmpTextPositionResult,style,rect);baseX=res.x;baseY=res.y;// Default align and baseline when has textPosition\ntextAlign=textAlign||res.textAlign;textVerticalAlign=textVerticalAlign||res.textVerticalAlign;}// textOffset is only support in RectText, otherwise\n// we have to adjust boundingRect for textOffset.\nvar textOffset=style.textOffset;if(textOffset){baseX+=textOffset[0];baseY+=textOffset[1];}}out=out||{};out.baseX=baseX;out.baseY=baseY;out.textAlign=textAlign;out.textVerticalAlign=textVerticalAlign;return out;}function setCtx(ctx,prop,value){ctx[prop]=fixShadow(ctx,prop,value);return ctx[prop];}/**\n * @param {string} [stroke] If specified, do not check style.textStroke.\n * @param {string} [lineWidth] If specified, do not check style.textStroke.\n * @param {number} style\n */function getStroke(stroke,lineWidth){return stroke==null||lineWidth<=0||stroke==='transparent'||stroke==='none'?null// TODO pattern and gradient?\n:stroke.image||stroke.colorStops?'#000':stroke;}function getFill(fill){return fill==null||fill==='none'?null// TODO pattern and gradient?\n:fill.image||fill.colorStops?'#000':fill;}function parsePercent(value,maxValue){if(typeof value==='string'){if(value.lastIndexOf('%')>=0){return parseFloat(value)/100*maxValue;}return parseFloat(value);}return value;}function getTextXForPadding(x,textAlign,textPadding){return textAlign==='right'?x-textPadding[1]:textAlign==='center'?x+textPadding[3]/2-textPadding[1]/2:x+textPadding[3];}/**\n * @param {string} text\n * @param {module:zrender/Style} style\n * @return {boolean}\n */function needDrawText(text,style){return text!=null&&(text||style.textBackgroundColor||style.textBorderWidth&&style.textBorderColor||style.textPadding);}/**\n * Mixin for drawing text in a element bounding rect\n * @module zrender/mixin/RectText\n */var tmpRect$1=new BoundingRect();var RectText=function RectText(){};RectText.prototype={constructor:RectText,/**\n     * Draw text in a rect with specified position.\n     * @param  {CanvasRenderingContext2D} ctx\n     * @param  {Object} rect Displayable rect\n     */drawRectText:function drawRectText(ctx,rect){var style=this.style;rect=style.textRect||rect;// Optimize, avoid normalize every time.\nthis.__dirty&&normalizeTextStyle(style,true);var text=style.text;// Convert to string\ntext!=null&&(text+='');if(!needDrawText(text,style)){return;}// FIXME\n// Do not provide prevEl to `textHelper.renderText` for ctx prop cache,\n// but use `ctx.save()` and `ctx.restore()`. Because the cache for rect\n// text propably break the cache for its host elements.\nctx.save();// Transform rect to view space\nvar transform=this.transform;if(!style.transformText){if(transform){tmpRect$1.copy(rect);tmpRect$1.applyTransform(transform);rect=tmpRect$1;}}else{this.setTransform(ctx);}// transformText and textRotation can not be used at the same time.\nrenderText(this,ctx,text,style,rect,WILL_BE_RESTORED);ctx.restore();}};/**\n * Base class of all displayable graphic objects\n * @module zrender/graphic/Displayable\n */ /**\n * @alias module:zrender/graphic/Displayable\n * @extends module:zrender/Element\n * @extends module:zrender/graphic/mixin/RectText\n */function Displayable(opts){opts=opts||{};Element.call(this,opts);// Extend properties\nfor(var name in opts){if(opts.hasOwnProperty(name)&&name!=='style'){this[name]=opts[name];}}/**\n     * @type {module:zrender/graphic/Style}\n     */this.style=new Style(opts.style,this);this._rect=null;// Shapes for cascade clipping.\n// Can only be `null`/`undefined` or an non-empty array, MUST NOT be an empty array.\n// because it is easy to only using null to check whether clipPaths changed.\nthis.__clipPaths=null;// FIXME Stateful must be mixined after style is setted\n// Stateful.call(this, opts);\n}Displayable.prototype={constructor:Displayable,type:'displayable',/**\n     * Dirty flag. From which painter will determine if this displayable object needs brush.\n     * @name module:zrender/graphic/Displayable#__dirty\n     * @type {boolean}\n     */__dirty:true,/**\n     * Whether the displayable object is visible. when it is true, the displayable object\n     * is not drawn, but the mouse event can still trigger the object.\n     * @name module:/zrender/graphic/Displayable#invisible\n     * @type {boolean}\n     * @default false\n     */invisible:false,/**\n     * @name module:/zrender/graphic/Displayable#z\n     * @type {number}\n     * @default 0\n     */z:0,/**\n     * @name module:/zrender/graphic/Displayable#z\n     * @type {number}\n     * @default 0\n     */z2:0,/**\n     * The z level determines the displayable object can be drawn in which layer canvas.\n     * @name module:/zrender/graphic/Displayable#zlevel\n     * @type {number}\n     * @default 0\n     */zlevel:0,/**\n     * Whether it can be dragged.\n     * @name module:/zrender/graphic/Displayable#draggable\n     * @type {boolean}\n     * @default false\n     */draggable:false,/**\n     * Whether is it dragging.\n     * @name module:/zrender/graphic/Displayable#draggable\n     * @type {boolean}\n     * @default false\n     */dragging:false,/**\n     * Whether to respond to mouse events.\n     * @name module:/zrender/graphic/Displayable#silent\n     * @type {boolean}\n     * @default false\n     */silent:false,/**\n     * If enable culling\n     * @type {boolean}\n     * @default false\n     */culling:false,/**\n     * Mouse cursor when hovered\n     * @name module:/zrender/graphic/Displayable#cursor\n     * @type {string}\n     */cursor:'pointer',/**\n     * If hover area is bounding rect\n     * @name module:/zrender/graphic/Displayable#rectHover\n     * @type {string}\n     */rectHover:false,/**\n     * Render the element progressively when the value >= 0,\n     * usefull for large data.\n     * @type {boolean}\n     */progressive:false,/**\n     * @type {boolean}\n     */incremental:false,/**\n     * Scale ratio for global scale.\n     * @type {boolean}\n     */globalScaleRatio:1,beforeBrush:function beforeBrush(ctx){},afterBrush:function afterBrush(ctx){},/**\n     * Graphic drawing method.\n     * @param {CanvasRenderingContext2D} ctx\n     */ // Interface\nbrush:function brush(ctx,prevEl){},/**\n     * Get the minimum bounding box.\n     * @return {module:zrender/core/BoundingRect}\n     */ // Interface\ngetBoundingRect:function getBoundingRect(){},/**\n     * If displayable element contain coord x, y\n     * @param  {number} x\n     * @param  {number} y\n     * @return {boolean}\n     */contain:function contain(x,y){return this.rectContain(x,y);},/**\n     * @param  {Function} cb\n     * @param  {}   context\n     */traverse:function traverse(cb,context){cb.call(context,this);},/**\n     * If bounding rect of element contain coord x, y\n     * @param  {number} x\n     * @param  {number} y\n     * @return {boolean}\n     */rectContain:function rectContain(x,y){var coord=this.transformCoordToLocal(x,y);var rect=this.getBoundingRect();return rect.contain(coord[0],coord[1]);},/**\n     * Mark displayable element dirty and refresh next frame\n     */dirty:function dirty(){this.__dirty=this.__dirtyText=true;this._rect=null;this.__zr&&this.__zr.refresh();},/**\n     * If displayable object binded any event\n     * @return {boolean}\n     */ // TODO, events bound by bind\n// isSilent: function () {\n//     return !(\n//         this.hoverable || this.draggable\n//         || this.onmousemove || this.onmouseover || this.onmouseout\n//         || this.onmousedown || this.onmouseup || this.onclick\n//         || this.ondragenter || this.ondragover || this.ondragleave\n//         || this.ondrop\n//     );\n// },\n/**\n     * Alias for animate('style')\n     * @param {boolean} loop\n     */animateStyle:function animateStyle(loop){return this.animate('style',loop);},attrKV:function attrKV(key,value){if(key!=='style'){Element.prototype.attrKV.call(this,key,value);}else{this.style.set(value);}},/**\n     * @param {Object|string} key\n     * @param {*} value\n     */setStyle:function setStyle(key,value){this.style.set(key,value);this.dirty(false);return this;},/**\n     * Use given style object\n     * @param  {Object} obj\n     */useStyle:function useStyle(obj){this.style=new Style(obj,this);this.dirty(false);return this;},/**\n     * The string value of `textPosition` needs to be calculated to a real postion.\n     * For example, `'inside'` is calculated to `[rect.width/2, rect.height/2]`\n     * by default. See `contain/text.js#calculateTextPosition` for more details.\n     * But some coutom shapes like \"pin\", \"flag\" have center that is not exactly\n     * `[width/2, height/2]`. So we provide this hook to customize the calculation\n     * for those shapes. It will be called if the `style.textPosition` is a string.\n     * @param {Obejct} [out] Prepared out object. If not provided, this method should\n     *        be responsible for creating one.\n     * @param {module:zrender/graphic/Style} style\n     * @param {Object} rect {x, y, width, height}\n     * @return {Obejct} out The same as the input out.\n     *         {\n     *             x: number. mandatory.\n     *             y: number. mandatory.\n     *             textAlign: string. optional. use style.textAlign by default.\n     *             textVerticalAlign: string. optional. use style.textVerticalAlign by default.\n     *         }\n     */calculateTextPosition:null};inherits(Displayable,Element);mixin(Displayable,RectText);/**\n * @alias zrender/graphic/Image\n * @extends module:zrender/graphic/Displayable\n * @constructor\n * @param {Object} opts\n */function ZImage(opts){Displayable.call(this,opts);}ZImage.prototype={constructor:ZImage,type:'image',brush:function brush(ctx,prevEl){var style=this.style;var src=style.image;// Must bind each time\nstyle.bind(ctx,this,prevEl);var image=this._image=createOrUpdateImage(src,this._image,this,this.onload);if(!image||!isImageReady(image)){return;}// 图片已经加载完成\n// if (image.nodeName.toUpperCase() == 'IMG') {\n//     if (!image.complete) {\n//         return;\n//     }\n// }\n// Else is canvas\nvar x=style.x||0;var y=style.y||0;var width=style.width;var height=style.height;var aspect=image.width/image.height;if(width==null&&height!=null){// Keep image/height ratio\nwidth=height*aspect;}else if(height==null&&width!=null){height=width/aspect;}else if(width==null&&height==null){width=image.width;height=image.height;}// 设置transform\nthis.setTransform(ctx);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);}// Draw rect text\nif(style.text!=null){// Only restore transform when needs draw text.\nthis.restoreTransform(ctx);this.drawRectText(ctx,this.getBoundingRect());}},getBoundingRect:function getBoundingRect(){var style=this.style;if(!this._rect){this._rect=new BoundingRect(style.x||0,style.y||0,style.width||0,style.height||0);}return this._rect;}};inherits(ZImage,Displayable);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;}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);}function isClipPathChanged(clipPaths,prevClipPaths){// displayable.__clipPaths can only be `null`/`undefined` or an non-empty array.\nif(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 doClip(clipPaths,ctx){for(var i=0;i<clipPaths.length;i++){var clipPath=clipPaths[i];clipPath.setTransform(ctx);ctx.beginPath();clipPath.buildPath(ctx,clipPath.shape);ctx.clip();// Transform back\nclipPath.restoreTransform(ctx);}}function createRoot(width,height){var domRoot=document.createElement('div');// domRoot.onselectstart = returnFalse; // Avoid page selected\ndomRoot.style.cssText=['position:relative',// IOS13 safari probably has a compositing bug (z order of the canvas and the consequent\n// dom does not act as expected) when some of the parent dom has\n// `-webkit-overflow-scrolling: touch;` and the webpage is longer than one screen and\n// the canvas is not at the top part of the page.\n// Check `https://bugs.webkit.org/show_bug.cgi?id=203681` for more details. We remove\n// this `overflow:hidden` to avoid the bug.\n// 'overflow:hidden',\n'width:'+width+'px','height:'+height+'px','padding:0','margin:0','border-width:0'].join(';')+';';return domRoot;}/**\n * @alias module:zrender/Painter\n * @constructor\n * @param {HTMLElement} root 绘图容器\n * @param {module:zrender/Storage} storage\n * @param {Object} opts\n */var Painter=function Painter(root,storage,opts){this.type='canvas';// In node environment using node-canvas\nvar singleCanvas=!root.nodeName// In node ?\n||root.nodeName.toUpperCase()==='CANVAS';this._opts=opts=extend({},opts||{});/**\n     * @type {number}\n     */this.dpr=opts.devicePixelRatio||devicePixelRatio;/**\n     * @type {boolean}\n     * @private\n     */this._singleCanvas=singleCanvas;/**\n     * 绘图容器\n     * @type {HTMLElement}\n     */this.root=root;var rootStyle=root.style;if(rootStyle){rootStyle['-webkit-tap-highlight-color']='transparent';rootStyle['-webkit-user-select']=rootStyle['user-select']=rootStyle['-webkit-touch-callout']='none';root.innerHTML='';}/**\n     * @type {module:zrender/Storage}\n     */this.storage=storage;/**\n     * @type {Array.<number>}\n     * @private\n     */var zlevelList=this._zlevelList=[];/**\n     * @type {Object.<string, module:zrender/Layer>}\n     * @private\n     */var layers=this._layers={};/**\n     * @type {Object.<string, Object>}\n     * @private\n     */this._layerConfig={};/**\n     * zrender will do compositing when root is a canvas and have multiple zlevels.\n     */this._needsManuallyCompositing=false;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 width=root.width;var height=root.height;if(opts.width!=null){width=opts.width;}if(opts.height!=null){height=opts.height;}this.dpr=opts.devicePixelRatio||1;// Use canvas width and height directly\nroot.width=width*this.dpr;root.height=height*this.dpr;this._width=width;this._height=height;// Create layer if only one given canvas\n// Device can be specified to create a high dpi image.\nvar mainLayer=new Layer(root,this,this.dpr);mainLayer.__builtin__=true;mainLayer.initContext();// FIXME Use canvas width and height\n// mainLayer.resize(width, height);\nlayers[CANVAS_ZLEVEL]=mainLayer;mainLayer.zlevel=CANVAS_ZLEVEL;// Not use common zlevel.\nzlevelList.push(CANVAS_ZLEVEL);this._domRoot=root;}/**\n     * @type {module:zrender/Layer}\n     * @private\n     */this._hoverlayer=null;this._hoverElements=[];};Painter.prototype={constructor:Painter,getType:function getType(){return'canvas';},/**\n     * If painter use a single canvas\n     * @return {boolean}\n     */isSingleCanvas:function isSingleCanvas(){return this._singleCanvas;},/**\n     * @return {HTMLDivElement}\n     */getViewportRoot:function getViewportRoot(){return this._domRoot;},getViewportRootOffset:function getViewportRootOffset(){var viewportRoot=this.getViewportRoot();if(viewportRoot){return{offsetLeft:viewportRoot.offsetLeft||0,offsetTop:viewportRoot.offsetTop||0};}},/**\n     * 刷新\n     * @param {boolean} [paintAll=false] 强制绘制所有displayable\n     */refresh:function refresh(paintAll){var list=this.storage.getDisplayList(true);var zlevelList=this._zlevelList;this._redrawId=Math.random();this._paintList(list,paintAll,this._redrawId);// Paint custum layers\nfor(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);}}this.refreshHover();return this;},addHover:function addHover(el,hoverStyle){if(el.__hoverMir){return;}var elMirror=new el.constructor({style:el.style,shape:el.shape,z:el.z,z2:el.z2,silent:el.silent});elMirror.__from=el;el.__hoverMir=elMirror;hoverStyle&&elMirror.setStyle(hoverStyle);this._hoverElements.push(elMirror);return elMirror;},removeHover:function removeHover(el){var elMirror=el.__hoverMir;var hoverElements=this._hoverElements;var idx=indexOf(hoverElements,elMirror);if(idx>=0){hoverElements.splice(idx,1);}el.__hoverMir=null;},clearHover:function clearHover(el){var hoverElements=this._hoverElements;for(var i=0;i<hoverElements.length;i++){var from=hoverElements[i].__from;if(from){from.__hoverMir=null;}}hoverElements.length=0;},refreshHover:function refreshHover(){var hoverElements=this._hoverElements;var len=hoverElements.length;var hoverLayer=this._hoverlayer;hoverLayer&&hoverLayer.clear();if(!len){return;}sort(hoverElements,this.storage.displayableSortFunc);// Use a extream large zlevel\n// FIXME?\nif(!hoverLayer){hoverLayer=this._hoverlayer=this.getLayer(HOVER_LAYER_ZLEVEL);}var scope={};hoverLayer.ctx.save();for(var i=0;i<len;){var el=hoverElements[i];var originalEl=el.__from;// Original el is removed\n// PENDING\nif(!(originalEl&&originalEl.__zr)){hoverElements.splice(i,1);originalEl.__hoverMir=null;len--;continue;}i++;// Use transform\n// FIXME style and shape ?\nif(!originalEl.invisible){el.transform=originalEl.transform;el.invTransform=originalEl.invTransform;el.__clipPaths=originalEl.__clipPaths;// el.\nthis._doPaintEl(el,hoverLayer,true,scope);}}hoverLayer.ctx.restore();},getHoverLayer:function getHoverLayer(){return this.getLayer(HOVER_LAYER_ZLEVEL);},_paintList:function _paintList(list,paintAll,redrawId){if(this._redrawId!==redrawId){return;}paintAll=paintAll||false;this._updateLayerStatus(list);var finished=this._doPaintList(list,paintAll);if(this._needsManuallyCompositing){this._compositeManually();}if(!finished){var self=this;requestAnimationFrame(function(){self._paintList(list,paintAll,redrawId);});}},_compositeManually:function _compositeManually(){var ctx=this.getLayer(CANVAS_ZLEVEL).ctx;var width=this._domRoot.width;var height=this._domRoot.height;ctx.clearRect(0,0,width,height);// PENDING, If only builtin layer?\nthis.eachBuiltinLayer(function(layer){if(layer.virtual){ctx.drawImage(layer.dom,0,0,width,height);}});},_doPaintList:function _doPaintList(list,paintAll){var layerList=[];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;for(var k=0;k<layerList.length;k++){var layer=layerList[k];var ctx=layer.ctx;var scope={};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._zlevelList[0]?this._backgroundColor:null;// All elements in this layer are cleared.\nif(layer.__startIndex===layer.__endIndex){layer.clear(false,clearColor);}else if(start===layer.__startIndex){var firstEl=list[start];if(!firstEl.incremental||!firstEl.notClear||paintAll){layer.clear(false,clearColor);}}if(start===-1){console.error('For some unknown reason. drawIndex is -1');start=layer.__startIndex;}for(var i=start;i<layer.__endIndex;i++){var el=list[i];this._doPaintEl(el,layer,paintAll,scope);el.__dirty=el.__dirtyText=false;if(useTimer){// Date.now can be executed in 13,025,305 ops/second.\nvar dTime=Date.now()-startTime;// Give 15 millisecond to draw.\n// The rest elements will be drawn in the next frame.\nif(dTime>15){break;}}}layer.__drawIndex=i;if(layer.__drawIndex<layer.__endIndex){finished=false;}if(scope.prevElClipPaths){// Needs restore the state. If last drawn element is in the clipping area.\nctx.restore();}ctx.restore();}if(env$1.wxa){// Flush for weixin application\neach$1(this._layers,function(layer){if(layer&&layer.ctx&&layer.ctx.draw){layer.ctx.draw();}});}return finished;},_doPaintEl:function _doPaintEl(el,currentLayer,forcePaint,scope){var ctx=currentLayer.ctx;var m=el.transform;if((currentLayer.__dirty||forcePaint)&&// Ignore invisible element\n!el.invisible// Ignore transparent element\n&&el.style.opacity!==0// Ignore scale 0 element, in some environment like node-canvas\n// Draw a scale 0 element can cause all following draw wrong\n// And setTransform with scale 0 will cause set back transform failed.\n&&!(m&&!m[0]&&!m[3])// Ignore culled element\n&&!(el.culling&&isDisplayableCulled(el,this._width,this._height))){var clipPaths=el.__clipPaths;var prevElClipPaths=scope.prevElClipPaths;// Optimize when clipping on group with several elements\nif(!prevElClipPaths||isClipPathChanged(clipPaths,prevElClipPaths)){// If has previous clipping state, restore from it\nif(prevElClipPaths){ctx.restore();scope.prevElClipPaths=null;// Reset prevEl since context has been restored\nscope.prevEl=null;}// New clipping state\nif(clipPaths){ctx.save();doClip(clipPaths,ctx);scope.prevElClipPaths=clipPaths;}}el.beforeBrush&&el.beforeBrush(ctx);el.brush(ctx,scope.prevEl||null);scope.prevEl=el;el.afterBrush&&el.afterBrush(ctx);}},/**\n     * 获取 zlevel 所在层，如果不存在则会创建一个新的层\n     * @param {number} zlevel\n     * @param {boolean} virtual Virtual layer will not be inserted into dom.\n     * @return {module:zrender/Layer}\n     */getLayer:function getLayer(zlevel,virtual){if(this._singleCanvas&&!this._needsManuallyCompositing){zlevel=CANVAS_ZLEVEL;}var layer=this._layers[zlevel];if(!layer){// Create a new layer\nlayer=new Layer('zr_'+zlevel,this,this.dpr);layer.zlevel=zlevel;layer.__builtin__=true;if(this._layerConfig[zlevel]){merge(layer,this._layerConfig[zlevel],true);}// TODO Remove EL_AFTER_INCREMENTAL_INC magic number\nelse 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);// Context is created after dom inserted to document\n// Or excanvas will get 0px clientWidth and clientHeight\nlayer.initContext();}return layer;},insertLayer:function insertLayer(zlevel,layer){var layersMap=this._layers;var zlevelList=this._zlevelList;var len=zlevelList.length;var prevLayer=null;var i=-1;var domRoot=this._domRoot;if(layersMap[zlevel]){logError$1('ZLevel '+zlevel+' has been used already');return;}// Check if is a valid layer\nif(!isLayerValid(layer)){logError$1('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;// Vitual layer will not directly show on the screen.\n// (It can be a WebGL layer and assigned to a ZImage element)\n// But it still under management of zrender.\nif(!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);}}}},// Iterate each layer\neachLayer:function eachLayer(cb,context){var zlevelList=this._zlevelList;var z;var i;for(i=0;i<zlevelList.length;i++){z=zlevelList[i];cb.call(context,this._layers[z],z);}},// Iterate each buildin layer\neachBuiltinLayer:function eachBuiltinLayer(cb,context){var zlevelList=this._zlevelList;var layer;var z;var i;for(i=0;i<zlevelList.length;i++){z=zlevelList[i];layer=this._layers[z];if(layer.__builtin__){cb.call(context,layer,z);}}},// Iterate each other layer except buildin layer\neachOtherLayer:function eachOtherLayer(cb,context){var zlevelList=this._zlevelList;var layer;var z;var i;for(i=0;i<zlevelList.length;i++){z=zlevelList[i];layer=this._layers[z];if(!layer.__builtin__){cb.call(context,layer,z);}}},/**\n     * 获取所有已创建的层\n     * @param {Array.<module:zrender/Layer>} [prevLayer]\n     */getLayers:function getLayers(){return this._layers;},_updateLayerStatus:function _updateLayerStatus(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;i<list.length;i++){var el=list[i];if(el.zlevel!==list[i-1].zlevel||el.incremental){this._needsManuallyCompositing=true;break;}}}var prevLayer=null;var incrementalLayerCount=0;var prevZlevel;for(var i=0;i<list.length;i++){var el=list[i];var zlevel=el.zlevel;var layer;if(prevZlevel!==zlevel){prevZlevel=zlevel;incrementalLayerCount=0;}// TODO Not use magic number on zlevel.\n// Each layer with increment element can be separated to 3 layers.\n//          (Other Element drawn after incremental element)\n// -----------------zlevel + EL_AFTER_INCREMENTAL_INC--------------------\n//                      (Incremental element)\n// ----------------------zlevel + INCREMENTAL_INC------------------------\n//              (Element drawn before incremental element)\n// --------------------------------zlevel--------------------------------\nif(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$1('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{// Mark layer draw index needs to update.\nlayer.__drawIndex=-1;}updatePrevLayer(i);prevLayer=layer;}if(el.__dirty){layer.__dirty=true;if(layer.incremental&&layer.__drawIndex<0){// Start draw from the first dirty element.\nlayer.__drawIndex=i;}}}updatePrevLayer(i);this.eachBuiltinLayer(function(layer,z){// Used in last frame but not in this frame. Needs clear\nif(!layer.__used&&layer.getElementCount()>0){layer.__dirty=true;layer.__startIndex=layer.__endIndex=layer.__drawIndex=0;}// For incremental layer. In case start index changed and no elements are dirty.\nif(layer.__dirty&&layer.__drawIndex<0){layer.__drawIndex=layer.__startIndex;}});},/**\n     * 清除hover层外所有内容\n     */clear:function clear(){this.eachBuiltinLayer(this._clearLayer);return this;},_clearLayer:function _clearLayer(layer){layer.clear();},setBackgroundColor:function setBackgroundColor(backgroundColor){this._backgroundColor=backgroundColor;},/**\n     * 修改指定zlevel的绘制参数\n     *\n     * @param {string} zlevel\n     * @param {Object} config 配置对象\n     * @param {string} [config.clearColor=0] 每次清空画布的颜色\n     * @param {string} [config.motionBlur=false] 是否开启动态模糊\n     * @param {number} [config.lastFrameAlpha=0.7]\n     *                 在开启动态模糊的时候使用，与上一帧混合的alpha值，值越大尾迹越明显\n     */configLayer:function configLayer(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];// TODO Remove EL_AFTER_INCREMENTAL_INC magic number\nif(_zlevel===zlevel||_zlevel===zlevel+EL_AFTER_INCREMENTAL_INC){var layer=this._layers[_zlevel];merge(layer,layerConfig[zlevel],true);}}}},/**\n     * 删除指定层\n     * @param {number} zlevel 层所在的zlevel\n     */delLayer:function delLayer(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);},/**\n     * 区域大小变化后重绘\n     */resize:function resize(width,height){if(!this._domRoot.style){// Maybe in node or worker\nif(width==null||height==null){return;}this._width=width;this._height=height;this.getLayer(CANVAS_ZLEVEL).resize(width,height);}else{var domRoot=this._domRoot;// FIXME Why ?\ndomRoot.style.display='none';// Save input w/h\nvar opts=this._opts;width!=null&&(opts.width=width);height!=null&&(opts.height=height);width=this._getSize(0);height=this._getSize(1);domRoot.style.display='';// 优化没有实际改变的resize\nif(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);}}each$1(this._progressiveLayers,function(layer){layer.resize(width,height);});this.refresh(true);}this._width=width;this._height=height;}return this;},/**\n     * 清除单独的一个层\n     * @param {number} zlevel\n     */clearLayer:function clearLayer(zlevel){var layer=this._layers[zlevel];if(layer){layer.clear();}},/**\n     * 释放\n     */dispose:function dispose(){this.root.innerHTML='';this.root=this.storage=this._domRoot=this._layers=null;},/**\n     * Get canvas which has all thing rendered\n     * @param {Object} opts\n     * @param {string} [opts.backgroundColor]\n     * @param {number} [opts.pixelRatio]\n     */getRenderedCanvas:function getRenderedCanvas(opts){opts=opts||{};if(this._singleCanvas&&!this._compositeManually){return this._layers[CANVAS_ZLEVEL].dom;}var imageLayer=new Layer('image',this,opts.pixelRatio||this.dpr);imageLayer.initContext();imageLayer.clear(false,opts.backgroundColor||this._backgroundColor);if(opts.pixelRatio<=this.dpr){this.refresh();var width=imageLayer.dom.width;var height=imageLayer.dom.height;var ctx=imageLayer.ctx;this.eachLayer(function(layer){if(layer.__builtin__){ctx.drawImage(layer.dom,0,0,width,height);}else if(layer.renderToCanvas){imageLayer.ctx.save();layer.renderToCanvas(imageLayer.ctx);imageLayer.ctx.restore();}});}else{// PENDING, echarts-gl and incremental rendering.\nvar scope={};var displayList=this.storage.getDisplayList(true);for(var i=0;i<displayList.length;i++){var el=displayList[i];this._doPaintEl(el,imageLayer,true,scope);}}return imageLayer.dom;},/**\n     * 获取绘图区域宽度\n     */getWidth:function getWidth(){return this._width;},/**\n     * 获取绘图区域高度\n     */getHeight:function getHeight(){return this._height;},_getSize:function _getSize(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;// IE8 does not support getComputedStyle, but it use VML.\nvar stl=document.defaultView.getComputedStyle(root);return(root[cwh]||parseInt10(stl[wh])||parseInt10(root.style[wh]))-(parseInt10(stl[plt])||0)-(parseInt10(stl[prb])||0)|0;},pathToImage:function pathToImage(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=style.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={position:path.position,rotation:path.rotation,scale:path.scale};path.position=[leftMargin-rect.x,topMargin-rect.y];path.rotation=0;path.scale=[1,1];path.updateTransform();if(path){path.brush(ctx);}var ImageShape=ZImage;var imgShape=new ImageShape({style:{x:0,y:0,image:canvas}});if(pathTransform.position!=null){imgShape.position=path.position=pathTransform.position;}if(pathTransform.rotation!=null){imgShape.rotation=path.rotation=pathTransform.rotation;}if(pathTransform.scale!=null){imgShape.scale=path.scale=pathTransform.scale;}return imgShape;}};/**\n * Animation main class, dispatch and manage all animation controllers\n *\n * @module zrender/animation/Animation\n * @author pissang(https://github.com/pissang)\n */ // TODO Additive animation\n// http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/\n// https://developer.apple.com/videos/wwdc2014/#236\n/**\n * @typedef {Object} IZRenderStage\n * @property {Function} update\n */ /**\n * @alias module:zrender/animation/Animation\n * @constructor\n * @param {Object} [options]\n * @param {Function} [options.onframe]\n * @param {IZRenderStage} [options.stage]\n * @example\n *     var animation = new Animation();\n *     var obj = {\n *         x: 100,\n *         y: 100\n *     };\n *     animation.animate(node.position)\n *         .when(1000, {\n *             x: 500,\n *             y: 500\n *         })\n *         .when(2000, {\n *             x: 100,\n *             y: 100\n *         })\n *         .start('spline');\n */var Animation=function Animation(options){options=options||{};this.stage=options.stage||{};this.onframe=options.onframe||function(){};// private properties\nthis._clips=[];this._running=false;this._time;this._pausedTime;this._pauseStart;this._paused=false;Eventful.call(this);};Animation.prototype={constructor:Animation,/**\n     * Add clip\n     * @param {module:zrender/animation/Clip} clip\n     */addClip:function addClip(clip){this._clips.push(clip);},/**\n     * Add animator\n     * @param {module:zrender/animation/Animator} animator\n     */addAnimator:function addAnimator(animator){animator.animation=this;var clips=animator.getClips();for(var i=0;i<clips.length;i++){this.addClip(clips[i]);}},/**\n     * Delete animation clip\n     * @param {module:zrender/animation/Clip} clip\n     */removeClip:function removeClip(clip){var idx=indexOf(this._clips,clip);if(idx>=0){this._clips.splice(idx,1);}},/**\n     * Delete animation clip\n     * @param {module:zrender/animation/Animator} animator\n     */removeAnimator:function removeAnimator(animator){var clips=animator.getClips();for(var i=0;i<clips.length;i++){this.removeClip(clips[i]);}animator.animation=null;},_update:function _update(){var time=new Date().getTime()-this._pausedTime;var delta=time-this._time;var clips=this._clips;var len=clips.length;var deferredEvents=[];var deferredClips=[];for(var i=0;i<len;i++){var clip=clips[i];var e=clip.step(time,delta);// Throw out the events need to be called after\n// stage.update, like destroy\nif(e){deferredEvents.push(e);deferredClips.push(clip);}}// Remove the finished clip\nfor(var i=0;i<len;){if(clips[i]._needsRemove){clips[i]=clips[len-1];clips.pop();len--;}else{i++;}}len=deferredEvents.length;for(var i=0;i<len;i++){deferredClips[i].fire(deferredEvents[i]);}this._time=time;this.onframe(delta);// 'frame' should be triggered before stage, because upper application\n// depends on the sequence (e.g., echarts-stream and finish\n// event judge)\nthis.trigger('frame',delta);if(this.stage.update){this.stage.update();}},_startLoop:function _startLoop(){var self=this;this._running=true;function step(){if(self._running){requestAnimationFrame(step);!self._paused&&self._update();}}requestAnimationFrame(step);},/**\n     * Start animation.\n     */start:function start(){this._time=new Date().getTime();this._pausedTime=0;this._startLoop();},/**\n     * Stop animation.\n     */stop:function stop(){this._running=false;},/**\n     * Pause animation.\n     */pause:function pause(){if(!this._paused){this._pauseStart=new Date().getTime();this._paused=true;}},/**\n     * Resume animation.\n     */resume:function resume(){if(this._paused){this._pausedTime+=new Date().getTime()-this._pauseStart;this._paused=false;}},/**\n     * Clear animation.\n     */clear:function clear(){this._clips=[];},/**\n     * Whether animation finished.\n     */isFinished:function isFinished(){return!this._clips.length;},/**\n     * Creat animator for a target, whose props can be animated.\n     *\n     * @param  {Object} target\n     * @param  {Object} options\n     * @param  {boolean} [options.loop=false] Whether loop animation.\n     * @param  {Function} [options.getter=null] Get value from target.\n     * @param  {Function} [options.setter=null] Set value to target.\n     * @return {module:zrender/animation/Animation~Animator}\n     */ // TODO Gap\nanimate:function animate(target,options){options=options||{};var animator=new Animator(target,options.loop,options.getter,options.setter);this.addAnimator(animator);return animator;}};mixin(Animation,Eventful);/* global document */var TOUCH_CLICK_DELAY=300;var globalEventSupported=env$1.domSupported;var localNativeListenerNames=function(){var mouseHandlerNames=['click','dblclick','mousewheel','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']};function eventNameFix(name){return name==='mousewheel'&&env$1.browser.firefox?'DOMMouseScroll':name;}function isPointerFromTouch(event){var pointerType=event.pointerType;return pointerType==='pen'||pointerType==='touch';}// function useMSGuesture(handlerProxy, event) {\n//     return isPointerFromTouch(event) && !!handlerProxy._msGesture;\n// }\n// function onMSGestureChange(proxy, event) {\n//     if (event.translationX || event.translationY) {\n//         // mousemove is carried by MSGesture to reduce the sensitivity.\n//         proxy.handler.dispatchToElement(event.target, 'mousemove', event);\n//     }\n//     if (event.scale !== 1) {\n//         event.pinchX = event.offsetX;\n//         event.pinchY = event.offsetY;\n//         event.pinchScale = event.scale;\n//         proxy.handler.dispatchToElement(event.target, 'pinch', event);\n//     }\n// }\n/**\n * Prevent mouse event from being dispatched after Touch Events action\n * @see <https://github.com/deltakosh/handjs/blob/master/src/hand.base.js>\n * 1. Mobile browsers dispatch mouse events 300ms after touchend.\n * 2. Chrome for Android dispatch mousedown for long-touch about 650ms\n * Result: Blocking Mouse Events for 700ms.\n *\n * @param {DOMHandlerScope} scope\n */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);}// Mark touch, which is useful in distinguish touch and\n// mouse event in upper applicatoin.\nfunction markTouch(event){event&&(event.zrByTouch=true);}// function markTriggeredFromLocal(event) {\n//     event && (event.__zrIsFromLocal = true);\n// }\n// function isTriggeredFromLocal(instance, event) {\n//     return !!(event && event.__zrIsFromLocal);\n// }\nfunction normalizeGlobalEvent(instance,event){// offsetX, offsetY still need to be calculated. They are necessary in the event\n// handlers of the upper applications. Set `true` to force calculate them.\nreturn normalizeEvent(instance.dom,new FakeGlobalEvent(instance,event),true);}/**\n * Detect whether the given el is in `painterRoot`.\n */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;}/**\n * Make a fake event but not change the original event,\n * becuase the global event probably be used by other\n * listeners not belonging to zrender.\n * @class\n */function FakeGlobalEvent(instance,event){this.type=event.type;this.target=this.currentTarget=instance.dom;this.pointerType=event.pointerType;// Necessray for the force calculation of zrX, zrY\nthis.clientX=event.clientX;this.clientY=event.clientY;// Because we do not mount global listeners to touch events,\n// we do not copy `targetTouches` and `changedTouches` here.\n}var fakeGlobalEventProto=FakeGlobalEvent.prototype;// we make the default methods on the event do nothing,\n// otherwise it is dangerous. See more details in\n// [Drag outside] in `Handler.js`.\nfakeGlobalEventProto.stopPropagation=fakeGlobalEventProto.stopImmediatePropagation=fakeGlobalEventProto.preventDefault=noop;/**\n * Local DOM Handlers\n * @this {HandlerProxy}\n */var localDOMHandlers={mousedown:function mousedown(event){event=normalizeEvent(this.dom,event);this._mayPointerCapture=[event.zrX,event.zrY];this.trigger('mousedown',event);},mousemove:function mousemove(event){event=normalizeEvent(this.dom,event);var downPoint=this._mayPointerCapture;if(downPoint&&(event.zrX!==downPoint[0]||event.zrY!==downPoint[1])){togglePointerCapture(this,true);}this.trigger('mousemove',event);},mouseup:function mouseup(event){event=normalizeEvent(this.dom,event);togglePointerCapture(this,false);this.trigger('mouseup',event);},mouseout:function mouseout(event){event=normalizeEvent(this.dom,event);// Similarly to the browser did on `document` and touch event,\n// `globalout` will be delayed to final pointer cature release.\nif(this._pointerCapturing){event.zrEventControl='no_globalout';}// There might be some doms created by upper layer application\n// at the same level of painter.getViewportRoot() (e.g., tooltip\n// dom created by echarts), where 'globalout' event should not\n// be triggered when mouse enters these doms. (But 'mouseout'\n// should be triggered at the original hovered element as usual).\nvar element=event.toElement||event.relatedTarget;event.zrIsToLocalDOM=isLocalEl(this,element);this.trigger('mouseout',event);},touchstart:function touchstart(event){// Default mouse behaviour should not be disabled here.\n// For example, page may needs to be slided.\nevent=normalizeEvent(this.dom,event);markTouch(event);this._lastTouchMoment=new Date();this.handler.processGesture(event,'start');// For consistent event listener for both touch device and mouse device,\n// we simulate \"mouseover-->mousedown\" in touch device. So we trigger\n// `mousemove` here (to trigger `mouseover` inside), and then trigger\n// `mousedown`.\nlocalDOMHandlers.mousemove.call(this,event);localDOMHandlers.mousedown.call(this,event);},touchmove:function touchmove(event){event=normalizeEvent(this.dom,event);markTouch(event);this.handler.processGesture(event,'change');// Mouse move should always be triggered no matter whether\n// there is gestrue event, because mouse move and pinch may\n// be used at the same time.\nlocalDOMHandlers.mousemove.call(this,event);},touchend:function touchend(event){event=normalizeEvent(this.dom,event);markTouch(event);this.handler.processGesture(event,'end');localDOMHandlers.mouseup.call(this,event);// Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is\n// triggered in `touchstart`. This seems to be illogical, but by this mechanism,\n// we can conveniently implement \"hover style\" in both PC and touch device just\n// by listening to `mouseover` to add \"hover style\" and listening to `mouseout`\n// to remove \"hover style\" on an element, without any additional code for\n// compatibility. (`mouseout` will not be triggered in `touchend`, so \"hover\n// style\" will remain for user view)\n// click event should always be triggered no matter whether\n// there is gestrue event. System click can not be prevented.\nif(+new Date()-this._lastTouchMoment<TOUCH_CLICK_DELAY){localDOMHandlers.click.call(this,event);}},pointerdown:function pointerdown(event){localDOMHandlers.mousedown.call(this,event);// if (useMSGuesture(this, event)) {\n//     this._msGesture.addPointer(event.pointerId);\n// }\n},pointermove:function pointermove(event){// FIXME\n// pointermove is so sensitive that it always triggered when\n// tap(click) on touch screen, which affect some judgement in\n// upper application. So, we dont support mousemove on MS touch\n// device yet.\nif(!isPointerFromTouch(event)){localDOMHandlers.mousemove.call(this,event);}},pointerup:function pointerup(event){localDOMHandlers.mouseup.call(this,event);},pointerout:function pointerout(event){// pointerout will be triggered when tap on touch screen\n// (IE11+/Edge on MS Surface) after click event triggered,\n// which is inconsistent with the mousout behavior we defined\n// in touchend. So we unify them.\n// (check localDOMHandlers.touchend for detailed explanation)\nif(!isPointerFromTouch(event)){localDOMHandlers.mouseout.call(this,event);}}};/**\n * Othere DOM UI Event handlers for zr dom.\n * @this {HandlerProxy}\n */each$1(['click','mousewheel','dblclick','contextmenu'],function(name){localDOMHandlers[name]=function(event){event=normalizeEvent(this.dom,event);this.trigger(name,event);};});/**\n * DOM UI Event handlers for global page.\n *\n * [Caution]:\n * those handlers should both support in capture phase and bubble phase!\n *\n * @this {HandlerProxy}\n */var globalDOMHandlers={pointermove:function pointermove(event){// FIXME\n// pointermove is so sensitive that it always triggered when\n// tap(click) on touch screen, which affect some judgement in\n// upper application. So, we dont support mousemove on MS touch\n// device yet.\nif(!isPointerFromTouch(event)){globalDOMHandlers.mousemove.call(this,event);}},pointerup:function pointerup(event){globalDOMHandlers.mouseup.call(this,event);},mousemove:function mousemove(event){this.trigger('mousemove',event);},mouseup:function mouseup(event){var pointerCaptureReleasing=this._pointerCapturing;togglePointerCapture(this,false);this.trigger('mouseup',event);if(pointerCaptureReleasing){event.zrEventControl='only_globalout';this.trigger('mouseout',event);}}};/**\n * @param {HandlerProxy} instance\n * @param {DOMHandlerScope} scope\n */function mountLocalDOMEventListeners(instance,scope){var domHandlers=scope.domHandlers;if(env$1.pointerEventsSupported){// Only IE11+/Edge\n// 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240),\n// IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event\n// at the same time.\n// 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on\n// screen, which do not occurs in pointer event.\n// So we use pointer event to both detect touch gesture and mouse behavior.\neach$1(localNativeListenerNames.pointer,function(nativeEventName){mountSingleDOMEventListener(scope,nativeEventName,function(event){// markTriggeredFromLocal(event);\ndomHandlers[nativeEventName].call(instance,event);});});// FIXME\n// Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,\n// which does not prevent defuault behavior occasionally (which may cause view port\n// zoomed in but use can not zoom it back). And event.preventDefault() does not work.\n// So we have to not to use MSGesture and not to support touchmove and pinch on MS\n// touch screen. And we only support click behavior on MS touch screen now.\n// MS Gesture Event is only supported on IE11+/Edge and on Windows 8+.\n// We dont support touch on IE on win7.\n// See <https://msdn.microsoft.com/en-us/library/dn433243(v=vs.85).aspx>\n// if (typeof MSGesture === 'function') {\n//     (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line\n//     dom.addEventListener('MSGestureChange', onMSGestureChange);\n// }\n}else{if(env$1.touchEventsSupported){each$1(localNativeListenerNames.touch,function(nativeEventName){mountSingleDOMEventListener(scope,nativeEventName,function(event){// markTriggeredFromLocal(event);\ndomHandlers[nativeEventName].call(instance,event);setTouchTimer(scope);});});// Handler of 'mouseout' event is needed in touch mode, which will be mounted below.\n// addEventListener(root, 'mouseout', this._mouseoutHandler);\n}// 1. Considering some devices that both enable touch and mouse event (like on MS Surface\n// and lenovo X240, @see #2350), we make mouse event be always listened, otherwise\n// mouse event can not be handle in those devices.\n// 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent\n// mouseevent after touch event triggered, see `setTouchTimer`.\neach$1(localNativeListenerNames.mouse,function(nativeEventName){mountSingleDOMEventListener(scope,nativeEventName,function(event){event=getNativeEvent(event);if(!scope.touching){// markTriggeredFromLocal(event);\ndomHandlers[nativeEventName].call(instance,event);}});});}}/**\n * @param {HandlerProxy} instance\n * @param {DOMHandlerScope} scope\n */function mountGlobalDOMEventListeners(instance,scope){// Only IE11+/Edge. See the comment in `mountLocalDOMEventListeners`.\nif(env$1.pointerEventsSupported){each$1(globalNativeListenerNames.pointer,mount);}// Touch event has implemented \"drag outside\" so we do not mount global listener for touch event.\n// (see https://www.w3.org/TR/touch-events/#the-touchmove-event)\n// We do not consider \"both-support-touch-and-mouse device\" for this feature (see the comment of\n// `mountLocalDOMEventListeners`) to avoid bugs util some requirements come.\nelse if(!env$1.touchEventsSupported){each$1(globalNativeListenerNames.mouse,mount);}function mount(nativeEventName){function nativeEventListener(event){event=getNativeEvent(event);// See the reason in [Drag outside] in `Handler.js`\n// This checking supports both `useCapture` or not.\n// PENDING: if there is performance issue in some devices,\n// we probably can not use `useCapture` and change a easier\n// to judes whether local (mark).\nif(!isLocalEl(instance,event.target)){event=normalizeGlobalEvent(instance,event);scope.domHandlers[nativeEventName].call(instance,event);}}mountSingleDOMEventListener(scope,nativeEventName,nativeEventListener,{capture:true}// See [Drag Outside] in `Handler.js`\n);}}function mountSingleDOMEventListener(scope,nativeEventName,listener,opt){scope.mounted[nativeEventName]=listener;scope.listenerOpts[nativeEventName]=opt;addEventListener(scope.domTarget,eventNameFix(nativeEventName),listener,opt);}function unmountDOMEventListeners(scope){var mounted=scope.mounted;for(var nativeEventName in mounted){if(mounted.hasOwnProperty(nativeEventName)){removeEventListener(scope.domTarget,eventNameFix(nativeEventName),mounted[nativeEventName],scope.listenerOpts[nativeEventName]);}}scope.mounted={};}/**\n * See [Drag Outside] in `Handler.js`.\n * @implement\n * @param {boolean} isPointerCapturing Should never be `null`/`undefined`.\n *        `true`: start to capture pointer if it is not capturing.\n *        `false`: end the capture if it is capturing.\n */function togglePointerCapture(instance,isPointerCapturing){instance._mayPointerCapture=null;if(globalEventSupported&&instance._pointerCapturing^isPointerCapturing){instance._pointerCapturing=isPointerCapturing;var globalHandlerScope=instance._globalHandlerScope;isPointerCapturing?mountGlobalDOMEventListeners(instance,globalHandlerScope):unmountDOMEventListeners(globalHandlerScope);}}/**\n * @inner\n * @class\n */function DOMHandlerScope(domTarget,domHandlers){this.domTarget=domTarget;this.domHandlers=domHandlers;// Key: eventName, value: mounted handler funcitons.\n// Used for unmount.\nthis.mounted={};this.listenerOpts={};this.touchTimer=null;this.touching=false;}/**\n * @public\n * @class\n */function HandlerDomProxy(dom,painterRoot){Eventful.call(this);this.dom=dom;this.painterRoot=painterRoot;this._localHandlerScope=new DOMHandlerScope(dom,localDOMHandlers);if(globalEventSupported){this._globalHandlerScope=new DOMHandlerScope(document,globalDOMHandlers);}/**\n     * @type {boolean}\n     */this._pointerCapturing=false;/**\n     * @type {Array.<number>} [x, y] or null.\n     */this._mayPointerCapture=null;mountLocalDOMEventListeners(this,this._localHandlerScope);}var handlerDomProxyProto=HandlerDomProxy.prototype;handlerDomProxyProto.dispose=function(){unmountDOMEventListeners(this._localHandlerScope);if(globalEventSupported){unmountDOMEventListeners(this._globalHandlerScope);}};handlerDomProxyProto.setCursor=function(cursorStyle){this.dom.style&&(this.dom.style.cursor=cursorStyle||'default');};mixin(HandlerDomProxy,Eventful);/*!\n* ZRender, a high performance 2d drawing library.\n*\n* Copyright (c) 2013, Baidu Inc.\n* All rights reserved.\n*\n* LICENSE\n* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt\n*/var useVML=!env$1.canvasSupported;var painterCtors={canvas:Painter};var instances$1={};// ZRender实例map索引\n/**\n * @type {string}\n */var version$1='4.3.2';/**\n * Initializing a zrender instance\n * @param {HTMLElement} dom\n * @param {Object} [opts]\n * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'\n * @param {number} [opts.devicePixelRatio]\n * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)\n * @return {module:zrender/ZRender}\n */function init$1(dom,opts){var zr=new ZRender(guid(),dom,opts);instances$1[zr.id]=zr;return zr;}/**\n * Dispose zrender instance\n * @param {module:zrender/ZRender} zr\n */function dispose$1(zr){if(zr){zr.dispose();}else{for(var key in instances$1){if(instances$1.hasOwnProperty(key)){instances$1[key].dispose();}}instances$1={};}return this;}/**\n * Get zrender instance by id\n * @param {string} id zrender instance id\n * @return {module:zrender/ZRender}\n */function getInstance(id){return instances$1[id];}function registerPainter(name,Ctor){painterCtors[name]=Ctor;}function delInstance(id){delete instances$1[id];}/**\n * @module zrender/ZRender\n */ /**\n * @constructor\n * @alias module:zrender/ZRender\n * @param {string} id\n * @param {HTMLElement} dom\n * @param {Object} opts\n * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'\n * @param {number} [opts.devicePixelRatio]\n * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)\n */var ZRender=function ZRender(id,dom,opts){opts=opts||{};/**\n     * @type {HTMLDomElement}\n     */this.dom=dom;/**\n     * @type {string}\n     */this.id=id;var self=this;var storage=new Storage();var rendererType=opts.renderer;// TODO WebGL\nif(useVML){if(!painterCtors.vml){throw new Error('You need to require \\'zrender/vml/vml\\' to support IE8');}rendererType='vml';}else if(!rendererType||!painterCtors[rendererType]){rendererType='canvas';}var painter=new painterCtors[rendererType](dom,storage,opts,id);this.storage=storage;this.painter=painter;var handerProxy=!env$1.node&&!env$1.worker?new HandlerDomProxy(painter.getViewportRoot(),painter.root):null;this.handler=new Handler(storage,painter,handerProxy,painter.root);/**\n     * @type {module:zrender/animation/Animation}\n     */this.animation=new Animation({stage:{update:bind(this.flush,this)}});this.animation.start();/**\n     * @type {boolean}\n     * @private\n     */this._needsRefresh;// 修改 storage.delFromStorage, 每次删除元素之前删除动画\n// FIXME 有点ugly\nvar oldDelFromStorage=storage.delFromStorage;var oldAddToStorage=storage.addToStorage;storage.delFromStorage=function(el){oldDelFromStorage.call(storage,el);el&&el.removeSelfFromZr(self);};storage.addToStorage=function(el){oldAddToStorage.call(storage,el);el.addSelfToZr(self);};};ZRender.prototype={constructor:ZRender,/**\n     * 获取实例唯一标识\n     * @return {string}\n     */getId:function getId(){return this.id;},/**\n     * 添加元素\n     * @param  {module:zrender/Element} el\n     */add:function add(el){this.storage.addRoot(el);this._needsRefresh=true;},/**\n     * 删除元素\n     * @param  {module:zrender/Element} el\n     */remove:function remove(el){this.storage.delRoot(el);this._needsRefresh=true;},/**\n     * Change configuration of layer\n     * @param {string} zLevel\n     * @param {Object} config\n     * @param {string} [config.clearColor=0] Clear color\n     * @param {string} [config.motionBlur=false] If enable motion blur\n     * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer\n    */configLayer:function configLayer(zLevel,config){if(this.painter.configLayer){this.painter.configLayer(zLevel,config);}this._needsRefresh=true;},/**\n     * Set background color\n     * @param {string} backgroundColor\n     */setBackgroundColor:function setBackgroundColor(backgroundColor){if(this.painter.setBackgroundColor){this.painter.setBackgroundColor(backgroundColor);}this._needsRefresh=true;},/**\n     * Repaint the canvas immediately\n     */refreshImmediately:function refreshImmediately(){// var start = new Date();\n// Clear needsRefresh ahead to avoid something wrong happens in refresh\n// Or it will cause zrender refreshes again and again.\nthis._needsRefresh=this._needsRefreshHover=false;this.painter.refresh();// Avoid trigger zr.refresh in Element#beforeUpdate hook\nthis._needsRefresh=this._needsRefreshHover=false;// var end = new Date();\n// var log = document.getElementById('log');\n// if (log) {\n//     log.innerHTML = log.innerHTML + '<br>' + (end - start);\n// }\n},/**\n     * Mark and repaint the canvas in the next frame of browser\n     */refresh:function refresh(){this._needsRefresh=true;},/**\n     * Perform all refresh\n     */flush:function flush(){var triggerRendered;if(this._needsRefresh){triggerRendered=true;this.refreshImmediately();}if(this._needsRefreshHover){triggerRendered=true;this.refreshHoverImmediately();}triggerRendered&&this.trigger('rendered');},/**\n     * Add element to hover layer\n     * @param  {module:zrender/Element} el\n     * @param {Object} style\n     */addHover:function addHover(el,style){if(this.painter.addHover){var elMirror=this.painter.addHover(el,style);this.refreshHover();return elMirror;}},/**\n     * Add element from hover layer\n     * @param  {module:zrender/Element} el\n     */removeHover:function removeHover(el){if(this.painter.removeHover){this.painter.removeHover(el);this.refreshHover();}},/**\n     * Clear all hover elements in hover layer\n     * @param  {module:zrender/Element} el\n     */clearHover:function clearHover(){if(this.painter.clearHover){this.painter.clearHover();this.refreshHover();}},/**\n     * Refresh hover in next frame\n     */refreshHover:function refreshHover(){this._needsRefreshHover=true;},/**\n     * Refresh hover immediately\n     */refreshHoverImmediately:function refreshHoverImmediately(){this._needsRefreshHover=false;this.painter.refreshHover&&this.painter.refreshHover();},/**\n     * Resize the canvas.\n     * Should be invoked when container size is changed\n     * @param {Object} [opts]\n     * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)\n     * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)\n     */resize:function resize(opts){opts=opts||{};this.painter.resize(opts.width,opts.height);this.handler.resize();},/**\n     * Stop and clear all animation immediately\n     */clearAnimation:function clearAnimation(){this.animation.clear();},/**\n     * Get container width\n     */getWidth:function getWidth(){return this.painter.getWidth();},/**\n     * Get container height\n     */getHeight:function getHeight(){return this.painter.getHeight();},/**\n     * Export the canvas as Base64 URL\n     * @param {string} type\n     * @param {string} [backgroundColor='#fff']\n     * @return {string} Base64 URL\n     */ // toDataURL: function(type, backgroundColor) {\n//     return this.painter.getRenderedCanvas({\n//         backgroundColor: backgroundColor\n//     }).toDataURL(type);\n// },\n/**\n     * Converting a path to image.\n     * It has much better performance of drawing image rather than drawing a vector path.\n     * @param {module:zrender/graphic/Path} e\n     * @param {number} width\n     * @param {number} height\n     */pathToImage:function pathToImage(e,dpr){return this.painter.pathToImage(e,dpr);},/**\n     * Set default cursor\n     * @param {string} [cursorStyle='default'] 例如 crosshair\n     */setCursorStyle:function setCursorStyle(cursorStyle){this.handler.setCursorStyle(cursorStyle);},/**\n     * Find hovered element\n     * @param {number} x\n     * @param {number} y\n     * @return {Object} {target, topTarget}\n     */findHover:function findHover(x,y){return this.handler.findHover(x,y);},/**\n     * Bind event\n     *\n     * @param {string} eventName Event name\n     * @param {Function} eventHandler Handler function\n     * @param {Object} [context] Context object\n     */on:function on(eventName,eventHandler,context){this.handler.on(eventName,eventHandler,context);},/**\n     * Unbind event\n     * @param {string} eventName Event name\n     * @param {Function} [eventHandler] Handler function\n     */off:function off(eventName,eventHandler){this.handler.off(eventName,eventHandler);},/**\n     * Trigger event manually\n     *\n     * @param {string} eventName Event name\n     * @param {event=} event Event object\n     */trigger:function trigger(eventName,event){this.handler.trigger(eventName,event);},/**\n     * Clear all objects and the canvas.\n     */clear:function clear(){this.storage.delRoot();this.painter.clear();},/**\n     * Dispose self.\n     */dispose:function dispose(){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);}};var zrender=(Object.freeze||Object)({version:version$1,init:init$1,dispose:dispose$1,getInstance:getInstance,registerPainter:registerPainter});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$2=each$1;var isObject$2=isObject$1;var isArray$1=isArray;/**\n * Make the name displayable. But we should\n * make sure it is not duplicated with user\n * specified name, so use '\\0';\n */var DUMMY_COMPONENT_NAME_PREFIX='series\\0';/**\n * If value is not array, then translate it to array.\n * @param  {*} value\n * @return {Array} [value] or value\n */function normalizeToArray(value){return value instanceof Array?value:value==null?[]:[value];}/**\n * Sync default option between normal and emphasis like `position` and `show`\n * In case some one will write code like\n *     label: {\n *          show: false,\n *          position: 'outside',\n *          fontSize: 18\n *     },\n *     emphasis: {\n *          label: { show: true }\n *     }\n * @param {Object} opt\n * @param {string} key\n * @param {Array.<string>} subOpts\n */function defaultEmphasis(opt,key,subOpts){// Caution: performance sensitive.\nif(opt){opt[key]=opt[key]||{};opt.emphasis=opt.emphasis||{};opt.emphasis[key]=opt.emphasis[key]||{};// Default emphasis option from normal\nfor(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'];// modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([\n//     'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter',\n//     'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',\n//     // FIXME: deprecated, check and remove it.\n//     'textStyle'\n// ]);\n/**\n * The method do not ensure performance.\n * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]\n * This helper method retieves value from data.\n * @param {string|number|Date|Array|Object} dataItem\n * @return {number|string|Date|Array.<number|string|Date>}\n */function getDataItemValue(dataItem){return isObject$2(dataItem)&&!isArray$1(dataItem)&&!(dataItem instanceof Date)?dataItem.value:dataItem;}/**\n * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]\n * This helper method determine if dataItem has extra option besides value\n * @param {string|number|Date|Array|Object} dataItem\n */function isDataItemOption(dataItem){return isObject$2(dataItem)&&!(dataItem instanceof Array);// // markLine data can be array\n// && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));\n}/**\n * Mapping to exists for merge.\n *\n * @public\n * @param {Array.<Object>|Array.<module:echarts/model/Component>} exists\n * @param {Object|Array.<Object>} newCptOptions\n * @return {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],\n *                          index of which is the same as exists.\n */function mappingToExists(exists,newCptOptions){// Mapping by the order by original option (but not order of\n// new option) in merge mode. Because we should ensure\n// some specified index (like xAxisIndex) is consistent with\n// original option, which is easy to understand, espatially in\n// media query. And in most case, merge option is used to\n// update partial option but not be expected to change order.\nnewCptOptions=(newCptOptions||[]).slice();var result=map(exists||[],function(obj,index){return{exist:obj};});// Mapping by id or name if specified.\neach$2(newCptOptions,function(cptOption,index){if(!isObject$2(cptOption)){return;}// id has highest priority.\nfor(var i=0;i<result.length;i++){if(!result[i].option// Consider name: two map to one.\n&&cptOption.id!=null&&result[i].exist.id===cptOption.id+''){result[i].option=cptOption;newCptOptions[index]=null;return;}}for(var i=0;i<result.length;i++){var exist=result[i].exist;if(!result[i].option// Consider name: two map to one.\n// Can not match when both ids exist but different.\n&&(exist.id==null||cptOption.id==null)&&cptOption.name!=null&&!isIdInner(cptOption)&&!isIdInner(exist)&&exist.name===cptOption.name+''){result[i].option=cptOption;newCptOptions[index]=null;return;}}});// Otherwise mapping by index.\neach$2(newCptOptions,function(cptOption,index){if(!isObject$2(cptOption)){return;}var i=0;for(;i<result.length;i++){var exist=result[i].exist;if(!result[i].option// Existing model that already has id should be able to\n// mapped to (because after mapping performed model may\n// be assigned with a id, whish should not affect next\n// mapping), except those has inner id.\n&&!isIdInner(exist)// Caution:\n// Do not overwrite id. But name can be overwritten,\n// because axis use name as 'show label text'.\n// 'exist' always has id and name and we dont\n// need to check it.\n&&cptOption.id==null){result[i].option=cptOption;break;}}if(i>=result.length){result.push({option:cptOption});}});return result;}/**\n * Make id and name for mapping result (result of mappingToExists)\n * into `keyInfo` field.\n *\n * @public\n * @param {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],\n *                          which order is the same as exists.\n * @return {Array.<Object>} The input.\n */function makeIdAndName(mapResult){// We use this id to hash component models and view instances\n// in echarts. id can be specified by user, or auto generated.\n// The id generation rule ensures new view instance are able\n// to mapped to old instance when setOption are called in\n// no-merge mode. So we generate model id by name and plus\n// type in view id.\n// name can be duplicated among components, which is convenient\n// to specify multi components (like series) by one name.\n// Ensure that each id is distinct.\nvar idMap=createHashMap();each$2(mapResult,function(item,index){var existCpt=item.exist;existCpt&&idMap.set(existCpt.id,item);});each$2(mapResult,function(item,index){var opt=item.option;assert$1(!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={});});// Make name and id.\neach$2(mapResult,function(item,index){var existCpt=item.exist;var opt=item.option;var keyInfo=item.keyInfo;if(!isObject$2(opt)){return;}// name can be overwitten. Consider case: axis.name = '20km'.\n// But id generated by name will not be changed, which affect\n// only in that case: setOption with 'not merge mode' and view\n// instance will be recreated, which can be accepted.\nkeyInfo.name=opt.name!=null?opt.name+'':existCpt?existCpt.name// Avoid diffferent series has the same name,\n// because name may be used like in color pallet.\n:DUMMY_COMPONENT_NAME_PREFIX+index;if(existCpt){keyInfo.id=existCpt.id;}else if(opt.id!=null){keyInfo.id=opt.id+'';}else{// Consider this situatoin:\n//  optionA: [{name: 'a'}, {name: 'a'}, {..}]\n//  optionB [{..}, {name: 'a'}, {name: 'a'}]\n// Series with the same name between optionA and optionB\n// should be mapped.\nvar idNum=0;do{keyInfo.id='\\0'+keyInfo.name+'\\0'+idNum++;}while(idMap.get(keyInfo.id));}idMap.set(keyInfo.id,item);});}function isNameSpecified(componentModel){var name=componentModel.name;// Is specified when `indexOf` get -1 or > 0.\nreturn!!(name&&name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));}/**\n * @public\n * @param {Object} cptOption\n * @return {boolean}\n */function isIdInner(cptOption){return isObject$2(cptOption)&&cptOption.id&&(cptOption.id+'').indexOf('\\0_ec_\\0')===0;}/**\n * A helper for removing duplicate items between batchA and batchB,\n * and in themselves, and categorize by series.\n *\n * @param {Array.<Object>} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]\n * @param {Array.<Object>} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]\n * @return {Array.<Array.<Object>, Array.<Object>>} result: [resultBatchA, resultBatchB]\n */ /**\n * @param {module:echarts/data/List} data\n * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name\n *                         each of which can be Array or primary type.\n * @return {number|Array.<number>} dataIndex If not found, return undefined/null.\n */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);}}/**\n * Enable property storage to any host object.\n * Notice: Serialization is not supported.\n *\n * For example:\n * var inner = zrUitl.makeInner();\n *\n * function some1(hostObj) {\n *      inner(hostObj).someProperty = 1212;\n *      ...\n * }\n * function some2() {\n *      var fields = inner(this);\n *      fields.someProperty1 = 1212;\n *      fields.someProperty2 = 'xx';\n *      ...\n * }\n *\n * @return {Function}\n */function makeInner(){// Consider different scope by es module import.\nvar key='__\\0ec_inner_'+innerUniqueIndex++ +'_'+Math.random().toFixed(5);return function(hostObj){return hostObj[key]||(hostObj[key]={});};}var innerUniqueIndex=0;/**\n * @param {module:echarts/model/Global} ecModel\n * @param {string|Object} finder\n *        If string, e.g., 'geo', means {geoIndex: 0}.\n *        If Object, could contain some of these properties below:\n *        {\n *            seriesIndex, seriesId, seriesName,\n *            geoIndex, geoId, geoName,\n *            bmapIndex, bmapId, bmapName,\n *            xAxisIndex, xAxisId, xAxisName,\n *            yAxisIndex, yAxisId, yAxisName,\n *            gridIndex, gridId, gridName,\n *            ... (can be extended)\n *        }\n *        Each properties can be number|string|Array.<number>|Array.<string>\n *        For example, a finder could be\n *        {\n *            seriesIndex: 3,\n *            geoId: ['aa', 'cc'],\n *            gridName: ['xx', 'rr']\n *        }\n *        xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify)\n *        If nothing or null/undefined specified, return nothing.\n * @param {Object} [opt]\n * @param {string} [opt.defaultMainType]\n * @param {Array.<string>} [opt.includeMainTypes]\n * @return {Object} result like:\n *        {\n *            seriesModels: [seriesModel1, seriesModel2],\n *            seriesModel: seriesModel1, // The first model\n *            geoModels: [geoModel1, geoModel2],\n *            geoModel: geoModel1, // The first model\n *            ...\n *        }\n */function parseFinder(ecModel,finder,opt){if(isString(finder)){var obj={};obj[finder+'Index']=0;finder=obj;}var defaultMainType=opt&&opt.defaultMainType;if(defaultMainType&&!has(finder,defaultMainType+'Index')&&!has(finder,defaultMainType+'Id')&&!has(finder,defaultMainType+'Name')){finder[defaultMainType+'Index']=0;}var result={};each$2(finder,function(value,key){var value=finder[key];// Exclude 'dataIndex' and other illgal keys.\nif(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||value==null||queryType==='index'&&value==='none'||opt&&opt.includeMainTypes&&indexOf(opt.includeMainTypes,mainType)<0){return;}var queryParam={mainType:mainType};if(queryType!=='index'||value!=='all'){queryParam[queryType]=value;}var models=ecModel.queryComponents(queryParam);result[mainType+'Models']=models;result[mainType+'Model']=models[0];});return result;}function has(obj,prop){return obj&&obj.hasOwnProperty(prop);}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'){// Using html when `document` exists, use richText otherwise\nreturn env$1.domSupported?'html':'richText';}else{return renderModeOption||'html';}}/**\n * Group a list by key.\n *\n * @param {Array} array\n * @param {Function} getKey\n *        param {*} Array item\n *        return {string} key\n * @return {Object} Result\n *        {Array}: keys,\n *        {module:zrender/core/util/HashMap} buckets: {key -> Array}\n */ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var TYPE_DELIMITER='.';var IS_CONTAINER='___EC__COMPONENT__CONTAINER___';/**\n * Notice, parseClassType('') should returns {main: '', sub: ''}\n * @public\n */function parseClassType$1(componentType){var ret={main:'',sub:''};if(componentType){componentType=componentType.split(TYPE_DELIMITER);ret.main=componentType[0]||'';ret.sub=componentType[1]||'';}return ret;}/**\n * @public\n */function checkClassType(componentType){assert$1(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType),'componentType \"'+componentType+'\" illegal');}/**\n * @public\n */function enableClassExtend(RootClass,mandatoryMethods){RootClass.$constructor=RootClass;RootClass.extend=function(proto){if(__DEV__){each$1(mandatoryMethods,function(method){if(!proto[method]){console.warn('Method `'+method+'` should be implemented'+(proto.type?' in '+proto.type:'')+'.');}});}var superClass=this;var ExtendedClass=function ExtendedClass(){if(!proto.$constructor){superClass.apply(this,arguments);}else{proto.$constructor.apply(this,arguments);}};extend(ExtendedClass.prototype,proto);ExtendedClass.extend=this.extend;ExtendedClass.superCall=superCall;ExtendedClass.superApply=superApply;inherits(ExtendedClass,this);ExtendedClass.superClass=superClass;return ExtendedClass;};}var classBase=0;/**\n * Can not use instanceof, consider different scope by\n * cross domain or es module import in ec extensions.\n * Mount a method \"isInstance()\" to Clz.\n */function enableClassCheck(Clz){var classAttr=['__\\0is_clz',classBase++,Math.random().toFixed(3)].join('_');Clz.prototype[classAttr]=true;if(__DEV__){assert$1(!Clz.isInstance,'The method \"is\" can not be defined.');}Clz.isInstance=function(obj){return!!(obj&&obj[classAttr]);};}// superCall should have class info, which can not be fetch from 'this'.\n// Consider this case:\n// class A has method f,\n// class B inherits class A, overrides method f, f call superApply('f'),\n// class C inherits class B, do not overrides method f,\n// then when method of class C is called, dead loop occured.\nfunction superCall(context,methodName){var args=slice(arguments,2);return this.superClass.prototype[methodName].apply(context,args);}function superApply(context,methodName,args){return this.superClass.prototype[methodName].apply(context,args);}/**\n * @param {Object} entity\n * @param {Object} options\n * @param {boolean} [options.registerWhenExtend]\n * @public\n */function enableClassManagement(entity,options){options=options||{};/**\n     * Component model classes\n     * key: componentType,\n     * value:\n     *     componentClass, when componentType is 'xxx'\n     *     or Object.<subKey, componentClass>, when componentType is 'xxx.yy'\n     * @type {Object}\n     */var storage={};entity.registerClass=function(Clazz,componentType){if(componentType){checkClassType(componentType);componentType=parseClassType$1(componentType);if(!componentType.sub){if(__DEV__){if(storage[componentType.main]){console.warn(componentType.main+' exists.');}}storage[componentType.main]=Clazz;}else if(componentType.sub!==IS_CONTAINER){var container=makeContainer(componentType);container[componentType.sub]=Clazz;}}return Clazz;};entity.getClass=function(componentMainType,subType,throwWhenNotFound){var Clazz=storage[componentMainType];if(Clazz&&Clazz[IS_CONTAINER]){Clazz=subType?Clazz[subType]:null;}if(throwWhenNotFound&&!Clazz){throw new Error(!subType?componentMainType+'.'+'type should be specified.':'Component '+componentMainType+'.'+(subType||'')+' not exists. Load it first.');}return Clazz;};entity.getClassesByMainType=function(componentType){componentType=parseClassType$1(componentType);var result=[];var obj=storage[componentType.main];if(obj&&obj[IS_CONTAINER]){each$1(obj,function(o,type){type!==IS_CONTAINER&&result.push(o);});}else{result.push(obj);}return result;};entity.hasClass=function(componentType){// Just consider componentType.main.\ncomponentType=parseClassType$1(componentType);return!!storage[componentType.main];};/**\n     * @return {Array.<string>} Like ['aa', 'bb'], but can not be ['aa.xx']\n     */entity.getAllClassMainTypes=function(){var types=[];each$1(storage,function(obj,type){types.push(type);});return types;};/**\n     * If a main type is container and has sub types\n     * @param  {string}  mainType\n     * @return {boolean}\n     */entity.hasSubTypes=function(componentType){componentType=parseClassType$1(componentType);var obj=storage[componentType.main];return obj&&obj[IS_CONTAINER];};entity.parseClassType=parseClassType$1;function makeContainer(componentType){var container=storage[componentType.main];if(!container||!container[IS_CONTAINER]){container=storage[componentType.main]={};container[IS_CONTAINER]=true;}return container;}if(options.registerWhenExtend){var originalExtend=entity.extend;if(originalExtend){entity.extend=function(proto){var ExtendedClass=originalExtend.call(this,proto);return entity.registerClass(ExtendedClass,proto.type);};}}return entity;}/**\n * @param {string|Array.<string>} properties\n */ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // TODO Parse shadow style\n// TODO Only shallow path support\nvar makeStyleMapper=function makeStyleMapper(properties){// Normalize\nfor(var i=0;i<properties.length;i++){if(!properties[i][1]){properties[i][1]=properties[i][0];}}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);if(val!=null){style[properties[i][0]]=val;}}return style;};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var _getLineStyle=makeStyleMapper([['lineWidth','width'],['stroke','color'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor']]);var lineStyleMixin={getLineStyle:function getLineStyle(excludes){var style=_getLineStyle(this,excludes);// Always set lineDash whether dashed, otherwise we can not\n// erase the previous style when assigning to el.style.\nstyle.lineDash=this.getLineDash(style.lineWidth);return style;},getLineDash:function getLineDash(lineWidth){if(lineWidth==null){lineWidth=1;}var lineType=this.get('type');var dotSize=Math.max(lineWidth,2);var dashSize=lineWidth*4;return lineType==='solid'||lineType==null?// Use `false` but not `null` for the solid line here, because `null` might be\n// ignored when assigning to `el.style`. e.g., when setting `lineStyle.type` as\n// `'dashed'` and `emphasis.lineStyle.type` as `'solid'` in graph series, the\n// `lineDash` gotten form the latter one is not able to erase that from the former\n// one if using `null` here according to the emhpsis strategy in `util/graphic.js`.\nfalse:lineType==='dashed'?[dashSize,dashSize]:[dotSize,dotSize];}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var _getAreaStyle=makeStyleMapper([['fill','color'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['opacity'],['shadowColor']]);var areaStyleMixin={getAreaStyle:function getAreaStyle(excludes,includes){return _getAreaStyle(this,excludes,includes);}};/**\n * 曲线辅助模块\n * @module zrender/core/curve\n * @author pissang(https://www.github.com/pissang)\n */var mathPow=Math.pow;var mathSqrt$2=Math.sqrt;var EPSILON$1=1e-8;var EPSILON_NUMERIC=1e-4;var THREE_SQRT=mathSqrt$2(3);var ONE_THIRD=1/3;// 临时变量\nvar _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;}/**\n * 计算三次贝塞尔值\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {number} t\n * @return {number}\n */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);}/**\n * 计算三次贝塞尔导数值\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {number} t\n * @return {number}\n */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);}/**\n * 计算三次贝塞尔方程根，使用盛金公式\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {number} val\n * @param  {Array.<number>} roots\n * @return {number} 有效根数目\n */function cubicRootAt(p0,p1,p2,p3,val,roots){// Evaluate roots of cubic functions\nvar 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;//t1, t2, t3, b is not zero\nif(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;// t1, a is not zero\nvar t2=-K/2;// t2, t3\nif(t1>=0&&t1<=1){roots[n++]=t1;}if(t2>=0&&t2<=1){roots[n++]=t2;}}else if(disc>0){var discSqrt=mathSqrt$2(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$2(A*A*A));var theta=Math.acos(T)/3;var ASqrt=mathSqrt$2(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;}/**\n * 计算三次贝塞尔方程极限值的位置\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {Array.<number>} extrema\n * @return {number} 有效数目\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$2(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;}/**\n * 细分三次贝塞尔曲线\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} p3\n * @param  {number} t\n * @param  {Array.<number>} out\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;// Seg0\nout[0]=p0;out[1]=p01;out[2]=p012;out[3]=p0123;// Seg1\nout[4]=p0123;out[5]=p123;out[6]=p23;out[7]=p3;}/**\n * 投射点到三次贝塞尔曲线上，返回投射距离。\n * 投射点有可能会有一个或者多个，这里只返回其中距离最短的一个。\n * @param {number} x0\n * @param {number} y0\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {number} x3\n * @param {number} y3\n * @param {number} x\n * @param {number} y\n * @param {Array.<number>} [out] 投射点\n * @return {number}\n */function cubicProjectPoint(x0,y0,x1,y1,x2,y2,x3,y3,x,y,out){// http://pomax.github.io/bezierinfo/#projections\nvar t;var interval=0.005;var d=Infinity;var prev;var next;var d1;var d2;_v0[0]=x;_v0[1]=y;// 先粗略估计一下可能的最小距离的 t 值\n// PENDING\nfor(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;// At most 32 iteration\nfor(var i=0;i<32;i++){if(interval<EPSILON_NUMERIC){break;}prev=t-interval;next=t+interval;// t - interval\n_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{// t + interval\n_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;}}}// t\nif(out){out[0]=cubicAt(x0,x1,x2,x3,t);out[1]=cubicAt(y0,y1,y2,y3,t);}// console.log(interval, i);\nreturn mathSqrt$2(d);}/**\n * 计算二次方贝塞尔值\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} t\n * @return {number}\n */function quadraticAt(p0,p1,p2,t){var onet=1-t;return onet*(onet*p0+2*t*p1)+t*t*p2;}/**\n * 计算二次方贝塞尔导数值\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} t\n * @return {number}\n */function quadraticDerivativeAt(p0,p1,p2,t){return 2*((1-t)*(p1-p0)+t*(p2-p1));}/**\n * 计算二次方贝塞尔方程根\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} t\n * @param  {Array.<number>} roots\n * @return {number} 有效根数目\n */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$2(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;}/**\n * 计算二次贝塞尔方程极限值\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @return {number}\n */function quadraticExtremum(p0,p1,p2){var divider=p0+p2-2*p1;if(divider===0){// p1 is center of p0 and p2\nreturn 0.5;}else{return(p0-p1)/divider;}}/**\n * 细分二次贝塞尔曲线\n * @memberOf module:zrender/core/curve\n * @param  {number} p0\n * @param  {number} p1\n * @param  {number} p2\n * @param  {number} t\n * @param  {Array.<number>} out\n */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;// Seg0\nout[0]=p0;out[1]=p01;out[2]=p012;// Seg1\nout[3]=p012;out[4]=p12;out[5]=p2;}/**\n * 投射点到二次贝塞尔曲线上，返回投射距离。\n * 投射点有可能会有一个或者多个，这里只返回其中距离最短的一个。\n * @param {number} x0\n * @param {number} y0\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {number} x\n * @param {number} y\n * @param {Array.<number>} out 投射点\n * @return {number}\n */function quadraticProjectPoint(x0,y0,x1,y1,x2,y2,x,y,out){// http://pomax.github.io/bezierinfo/#projections\nvar t;var interval=0.005;var d=Infinity;_v0[0]=x;_v0[1]=y;// 先粗略估计一下可能的最小距离的 t 值\n// PENDING\nfor(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;// At most 32 iteration\nfor(var i=0;i<32;i++){if(interval<EPSILON_NUMERIC){break;}var prev=t-interval;var next=t+interval;// t - interval\n_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{// t + interval\n_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;}}}// t\nif(out){out[0]=quadraticAt(x0,x1,x2,t);out[1]=quadraticAt(y0,y1,y2,t);}// console.log(interval, i);\nreturn mathSqrt$2(d);}/**\n * @author Yi Shen(https://github.com/pissang)\n */var mathMin$3=Math.min;var mathMax$3=Math.max;var mathSin$2=Math.sin;var mathCos$2=Math.cos;var PI2=Math.PI*2;var start=create();var end=create();var extremity=create();/**\n * 从顶点数组中计算出最小包围盒，写入`min`和`max`中\n * @module zrender/core/bbox\n * @param {Array<Object>} points 顶点数组\n * @param {number} min\n * @param {number} max\n */function fromPoints(points,min$$1,max$$1){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];var i;for(i=1;i<points.length;i++){p=points[i];left=mathMin$3(left,p[0]);right=mathMax$3(right,p[0]);top=mathMin$3(top,p[1]);bottom=mathMax$3(bottom,p[1]);}min$$1[0]=left;min$$1[1]=top;max$$1[0]=right;max$$1[1]=bottom;}/**\n * @memberOf module:zrender/core/bbox\n * @param {number} x0\n * @param {number} y0\n * @param {number} x1\n * @param {number} y1\n * @param {Array.<number>} min\n * @param {Array.<number>} max\n */function fromLine(x0,y0,x1,y1,min$$1,max$$1){min$$1[0]=mathMin$3(x0,x1);min$$1[1]=mathMin$3(y0,y1);max$$1[0]=mathMax$3(x0,x1);max$$1[1]=mathMax$3(y0,y1);}var xDim=[];var yDim=[];/**\n * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒，写入`min`和`max`中\n * @memberOf module:zrender/core/bbox\n * @param {number} x0\n * @param {number} y0\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {number} x3\n * @param {number} y3\n * @param {Array.<number>} min\n * @param {Array.<number>} max\n */function fromCubic(x0,y0,x1,y1,x2,y2,x3,y3,min$$1,max$$1){var cubicExtrema$$1=cubicExtrema;var cubicAt$$1=cubicAt;var i;var n=cubicExtrema$$1(x0,x1,x2,x3,xDim);min$$1[0]=Infinity;min$$1[1]=Infinity;max$$1[0]=-Infinity;max$$1[1]=-Infinity;for(i=0;i<n;i++){var x=cubicAt$$1(x0,x1,x2,x3,xDim[i]);min$$1[0]=mathMin$3(x,min$$1[0]);max$$1[0]=mathMax$3(x,max$$1[0]);}n=cubicExtrema$$1(y0,y1,y2,y3,yDim);for(i=0;i<n;i++){var y=cubicAt$$1(y0,y1,y2,y3,yDim[i]);min$$1[1]=mathMin$3(y,min$$1[1]);max$$1[1]=mathMax$3(y,max$$1[1]);}min$$1[0]=mathMin$3(x0,min$$1[0]);max$$1[0]=mathMax$3(x0,max$$1[0]);min$$1[0]=mathMin$3(x3,min$$1[0]);max$$1[0]=mathMax$3(x3,max$$1[0]);min$$1[1]=mathMin$3(y0,min$$1[1]);max$$1[1]=mathMax$3(y0,max$$1[1]);min$$1[1]=mathMin$3(y3,min$$1[1]);max$$1[1]=mathMax$3(y3,max$$1[1]);}/**\n * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒，写入`min`和`max`中\n * @memberOf module:zrender/core/bbox\n * @param {number} x0\n * @param {number} y0\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {Array.<number>} min\n * @param {Array.<number>} max\n */function fromQuadratic(x0,y0,x1,y1,x2,y2,min$$1,max$$1){var quadraticExtremum$$1=quadraticExtremum;var quadraticAt$$1=quadraticAt;// Find extremities, where derivative in x dim or y dim is zero\nvar tx=mathMax$3(mathMin$3(quadraticExtremum$$1(x0,x1,x2),1),0);var ty=mathMax$3(mathMin$3(quadraticExtremum$$1(y0,y1,y2),1),0);var x=quadraticAt$$1(x0,x1,x2,tx);var y=quadraticAt$$1(y0,y1,y2,ty);min$$1[0]=mathMin$3(x0,x2,x);min$$1[1]=mathMin$3(y0,y2,y);max$$1[0]=mathMax$3(x0,x2,x);max$$1[1]=mathMax$3(y0,y2,y);}/**\n * 从圆弧中计算出最小包围盒，写入`min`和`max`中\n * @method\n * @memberOf module:zrender/core/bbox\n * @param {number} x\n * @param {number} y\n * @param {number} rx\n * @param {number} ry\n * @param {number} startAngle\n * @param {number} endAngle\n * @param {number} anticlockwise\n * @param {Array.<number>} min\n * @param {Array.<number>} max\n */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){// Is a circle\nmin$$1[0]=x-rx;min$$1[1]=y-ry;max$$1[0]=x+rx;max$$1[1]=y+ry;return;}start[0]=mathCos$2(startAngle)*rx+x;start[1]=mathSin$2(startAngle)*ry+y;end[0]=mathCos$2(endAngle)*rx+x;end[1]=mathSin$2(endAngle)*ry+y;vec2Min(min$$1,start,end);vec2Max(max$$1,start,end);// Thresh to [0, Math.PI * 2]\nstartAngle=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;}// var number = 0;\n// var step = (anticlockwise ? -Math.PI : Math.PI) / 2;\nfor(var angle=0;angle<endAngle;angle+=Math.PI/2){if(angle>startAngle){extremity[0]=mathCos$2(angle)*rx+x;extremity[1]=mathSin$2(angle)*ry+y;vec2Min(min$$1,extremity,min$$1);vec2Max(max$$1,extremity,max$$1);}}}/**\n * Path 代理，可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中\n * 可以用于 isInsidePath 判断以及获取boundingRect\n *\n * @module zrender/core/PathProxy\n * @author Yi Shen (http://www.github.com/pissang)\n */ // TODO getTotalLength, getPointAtLength\n/* global Float32Array */var CMD={M:1,L:2,C:3,Q:4,A:5,Z:6,// Rect\nR:7};// var CMD_MEM_SIZE = {\n//     M: 3,\n//     L: 3,\n//     C: 7,\n//     Q: 5,\n//     A: 9,\n//     R: 5,\n//     Z: 1\n// };\nvar 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 hasTypedArray=typeof Float32Array!=='undefined';/**\n * @alias module:zrender/core/PathProxy\n * @constructor\n */var PathProxy=function PathProxy(notSaveData){this._saveData=!(notSaveData||false);if(this._saveData){/**\n         * Path data. Stored as flat array\n         * @type {Array.<Object>}\n         */this.data=[];}this._ctx=null;};/**\n * 快速计算Path包围盒（并不是最小包围盒）\n * @return {Object}\n */PathProxy.prototype={constructor:PathProxy,_xi:0,_yi:0,_x0:0,_y0:0,// Unit x, Unit y. Provide for avoiding drawing that too short line segment\n_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,/**\n     * @readOnly\n     */setScale:function setScale(sx,sy,segmentIgnoreThreshold){// Compat. Previously there is no segmentIgnoreThreshold.\nsegmentIgnoreThreshold=segmentIgnoreThreshold||0;this._ux=mathAbs(segmentIgnoreThreshold/devicePixelRatio/sx)||0;this._uy=mathAbs(segmentIgnoreThreshold/devicePixelRatio/sy)||0;},getContext:function getContext(){return this._ctx;},/**\n     * @param  {CanvasRenderingContext2D} ctx\n     * @return {module:zrender/core/PathProxy}\n     */beginPath:function beginPath(ctx){this._ctx=ctx;ctx&&ctx.beginPath();ctx&&(this.dpr=ctx.dpr);// Reset\nif(this._saveData){this._len=0;}if(this._lineDash){this._lineDash=null;this._dashOffset=0;}return this;},/**\n     * @param  {number} x\n     * @param  {number} y\n     * @return {module:zrender/core/PathProxy}\n     */moveTo:function moveTo(x,y){this.addData(CMD.M,x,y);this._ctx&&this._ctx.moveTo(x,y);// x0, y0, xi, yi 是记录在 _dashedXXXXTo 方法中使用\n// xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。\n// 有可能在 beginPath 之后直接调用 lineTo，这时候 x0, y0 需要\n// 在 lineTo 方法中记录，这里先不考虑这种情况，dashed line 也只在 IE10- 中不支持\nthis._x0=x;this._y0=y;this._xi=x;this._yi=y;return this;},/**\n     * @param  {number} x\n     * @param  {number} y\n     * @return {module:zrender/core/PathProxy}\n     */lineTo:function lineTo(x,y){var exceedUnit=mathAbs(x-this._xi)>this._ux||mathAbs(y-this._yi)>this._uy// Force draw the first segment\n||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;},/**\n     * @param  {number} x1\n     * @param  {number} y1\n     * @param  {number} x2\n     * @param  {number} y2\n     * @param  {number} x3\n     * @param  {number} y3\n     * @return {module:zrender/core/PathProxy}\n     */bezierCurveTo:function bezierCurveTo(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;},/**\n     * @param  {number} x1\n     * @param  {number} y1\n     * @param  {number} x2\n     * @param  {number} y2\n     * @return {module:zrender/core/PathProxy}\n     */quadraticCurveTo:function quadraticCurveTo(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;},/**\n     * @param  {number} cx\n     * @param  {number} cy\n     * @param  {number} r\n     * @param  {number} startAngle\n     * @param  {number} endAngle\n     * @param  {boolean} anticlockwise\n     * @return {module:zrender/core/PathProxy}\n     */arc:function arc(cx,cy,r,startAngle,endAngle,anticlockwise){this.addData(CMD.A,cx,cy,r,r,startAngle,endAngle-startAngle,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;},// TODO\narcTo:function arcTo(x1,y1,x2,y2,radius){if(this._ctx){this._ctx.arcTo(x1,y1,x2,y2,radius);}return this;},// TODO\nrect:function rect(x,y,w,h){this._ctx&&this._ctx.rect(x,y,w,h);this.addData(CMD.R,x,y,w,h);return this;},/**\n     * @return {module:zrender/core/PathProxy}\n     */closePath:function closePath(){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;},/**\n     * Context 从外部传入，因为有可能是 rebuildPath 完之后再 fill。\n     * stroke 同样\n     * @param {CanvasRenderingContext2D} ctx\n     * @return {module:zrender/core/PathProxy}\n     */fill:function fill(ctx){ctx&&ctx.fill();this.toStatic();},/**\n     * @param {CanvasRenderingContext2D} ctx\n     * @return {module:zrender/core/PathProxy}\n     */stroke:function stroke(ctx){ctx&&ctx.stroke();this.toStatic();},/**\n     * 必须在其它绘制命令前调用\n     * Must be invoked before all other path drawing methods\n     * @return {module:zrender/core/PathProxy}\n     */setLineDash:function setLineDash(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;}return this;},/**\n     * 必须在其它绘制命令前调用\n     * Must be invoked before all other path drawing methods\n     * @return {module:zrender/core/PathProxy}\n     */setLineDashOffset:function setLineDashOffset(offset){this._dashOffset=offset;return this;},/**\n     *\n     * @return {boolean}\n     */len:function len(){return this._len;},/**\n     * 直接设置 Path 数据\n     */setData:function setData(data){var len$$1=data.length;if(!(this.data&&this.data.length===len$$1)&&hasTypedArray){this.data=new Float32Array(len$$1);}for(var i=0;i<len$$1;i++){this.data[i]=data[i];}this._len=len$$1;},/**\n     * 添加子路径\n     * @param {module:zrender/core/PathProxy|Array.<module:zrender/core/PathProxy>} path\n     */appendPath:function appendPath(path){if(!(path instanceof Array)){path=[path];}var len$$1=path.length;var appendSize=0;var offset=this._len;for(var i=0;i<len$$1;i++){appendSize+=path[i].len();}if(hasTypedArray&&this.data instanceof Float32Array){this.data=new Float32Array(offset+appendSize);}for(var i=0;i<len$$1;i++){var appendPathData=path[i].data;for(var k=0;k<appendPathData.length;k++){this.data[offset++]=appendPathData[k];}}this._len=offset;},/**\n     * 填充 Path 数据。\n     * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。\n     */addData:function addData(cmd){if(!this._saveData){return;}var data=this.data;if(this._len+arguments.length>data.length){// 因为之前的数组已经转换成静态的 Float32Array\n// 所以不够用时需要扩展一个新的动态数组\nthis._expandData();data=this.data;}for(var i=0;i<arguments.length;i++){data[this._len++]=arguments[i];}this._prevCmd=cmd;},_expandData:function _expandData(){// Only if data is Float32Array\nif(!(this.data instanceof Array)){var newData=[];for(var i=0;i<this._len;i++){newData[i]=this.data[i];}this.data=newData;}},/**\n     * If needs js implemented dashed line\n     * @return {boolean}\n     * @private\n     */_needsDash:function _needsDash(){return this._lineDash;},_dashedLineTo:function _dashedLineTo(x1,y1){var dashSum=this._dashSum;var offset=this._dashOffset;var lineDash=this._lineDash;var ctx=this._ctx;var x0=this._xi;var y0=this._yi;var dx=x1-x0;var dy=y1-y0;var dist$$1=mathSqrt$1(dx*dx+dy*dy);var x=x0;var y=y0;var dash;var nDash=lineDash.length;var idx;dx/=dist$$1;dy/=dist$$1;if(offset<0){// Convert to positive offset\noffset=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;// Skip positive offset\nif(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));}// Offset for next lineTo\ndx=x-x1;dy=y-y1;this._dashOffset=-mathSqrt$1(dx*dx+dy*dy);},// Not accurate dashed line to\n_dashedBezierTo:function _dashedBezierTo(x1,y1,x2,y2,x3,y3){var dashSum=this._dashSum;var offset=this._dashOffset;var lineDash=this._lineDash;var ctx=this._ctx;var x0=this._xi;var y0=this._yi;var t;var dx;var dy;var cubicAt$$1=cubicAt;var bezierLen=0;var idx=this._dashIdx;var nDash=lineDash.length;var x;var y;var tmpLen=0;if(offset<0){// Convert to positive offset\noffset=dashSum+offset;}offset%=dashSum;// Bezier approx length\nfor(t=0;t<1;t+=0.1){dx=cubicAt$$1(x0,x1,x2,x3,t+0.1)-cubicAt$$1(x0,x1,x2,x3,t);dy=cubicAt$$1(y0,y1,y2,y3,t+0.1)-cubicAt$$1(y0,y1,y2,y3,t);bezierLen+=mathSqrt$1(dx*dx+dy*dy);}// Find idx after add offset\nfor(;idx<nDash;idx++){tmpLen+=lineDash[idx];if(tmpLen>offset){break;}}t=(tmpLen-offset)/bezierLen;while(t<=1){x=cubicAt$$1(x0,x1,x2,x3,t);y=cubicAt$$1(y0,y1,y2,y3,t);// Use line to approximate dashed bezier\n// Bad result if dash is long\nidx%2?ctx.moveTo(x,y):ctx.lineTo(x,y);t+=lineDash[idx]/bezierLen;idx=(idx+1)%nDash;}// Finish the last segment and calculate the new offset\nidx%2!==0&&ctx.lineTo(x3,y3);dx=x3-x;dy=y3-y;this._dashOffset=-mathSqrt$1(dx*dx+dy*dy);},_dashedQuadraticTo:function _dashedQuadraticTo(x1,y1,x2,y2){// Convert quadratic to cubic using degree elevation\nvar 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);},/**\n     * 转成静态的 Float32Array 减少堆内存占用\n     * Convert dynamic array to static Float32Array\n     */toStatic:function toStatic(){var data=this.data;if(data instanceof Array){data.length=this._len;if(hasTypedArray){this.data=new Float32Array(data);}}},/**\n     * @return {module:zrender/core/BoundingRect}\n     */getBoundingRect:function getBoundingRect(){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;for(var i=0;i<data.length;){var cmd=data[i++];if(i===1){// 如果第一个命令是 L, C, Q\n// 则 previous point 同绘制命令的第一个 point\n//\n// 第一个命令为 Arc 的情况下会在后面特殊处理\nxi=data[i];yi=data[i+1];x0=xi;y0=yi;}switch(cmd){case CMD.M:// moveTo 命令重新创建一个新的 subpath, 并且更新新的起点\n// 在 closePath 的时候使用\nx0=data[i++];y0=data[i++];xi=x0;yi=y0;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:// TODO Arc 判断的开销比较大\nvar cx=data[i++];var cy=data[i++];var rx=data[i++];var ry=data[i++];var startAngle=data[i++];var endAngle=data[i++]+startAngle;// TODO Arc 旋转\ni+=1;var anticlockwise=1-data[i++];if(i===1){// 直接使用 arc 命令\n// 第一个命令起点还未定义\nx0=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++];// Use fromLine\nfromLine(x0,y0,x0+width,y0+height,min2,max2);break;case CMD.Z:xi=x0;yi=y0;break;}// Union\nmin(min$1,min$1,min2);max(max$1,max$1,max2);}// No data\nif(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]);},/**\n     * Rebuild path from current data\n     * Rebuild path will not consider javascript implemented line dash.\n     * @param {CanvasRenderingContext2D} ctx\n     */rebuildPath:function rebuildPath(ctx){var d=this.data;var x0;var y0;var xi;var yi;var x;var y;var ux=this._ux;var uy=this._uy;var len$$1=this._len;for(var i=0;i<len$$1;){var cmd=d[i++];if(i===1){// 如果第一个命令是 L, C, Q\n// 则 previous point 同绘制命令的第一个 point\n//\n// 第一个命令为 Arc 的情况下会在后面特殊处理\nxi=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++];// Not draw too small seg between\nif(mathAbs(x-xi)>ux||mathAbs(y-yi)>uy||i===len$$1-1){ctx.lineTo(x,y);xi=x;yi=y;}break;case CMD.C:ctx.bezierCurveTo(d[i++],d[i++],d[i++],d[i++],d[i++],d[i++]);xi=d[i-2];yi=d[i-1];break;case CMD.Q:ctx.quadraticCurveTo(d[i++],d[i++],d[i++],d[i++]);xi=d[i-2];yi=d[i-1];break;case CMD.A:var cx=d[i++];var cy=d[i++];var rx=d[i++];var ry=d[i++];var theta=d[i++];var dTheta=d[i++];var psi=d[i++];var fs=d[i++];var r=rx>ry?rx:ry;var scaleX=rx>ry?1:rx/ry;var scaleY=rx>ry?ry/rx:1;var isEllipse=Math.abs(rx-ry)>1e-3;var endAngle=theta+dTheta;if(isEllipse){ctx.translate(cx,cy);ctx.rotate(psi);ctx.scale(scaleX,scaleY);ctx.arc(0,0,r,theta,endAngle,1-fs);ctx.scale(1/scaleX,1/scaleY);ctx.rotate(-psi);ctx.translate(-cx,-cy);}else{ctx.arc(cx,cy,r,theta,endAngle,1-fs);}if(i===1){// 直接使用 arc 命令\n// 第一个命令起点还未定义\nx0=mathCos$1(theta)*rx+cx;y0=mathSin$1(theta)*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];ctx.rect(d[i++],d[i++],d[i++],d[i++]);break;case CMD.Z:ctx.closePath();xi=x0;yi=y0;}}}};PathProxy.CMD=CMD;/**\n * 线段包含判断\n * @param  {number}  x0\n * @param  {number}  y0\n * @param  {number}  x1\n * @param  {number}  y1\n * @param  {number}  lineWidth\n * @param  {number}  x\n * @param  {number}  y\n * @return {boolean}\n */function containStroke$1(x0,y0,x1,y1,lineWidth,x,y){if(lineWidth===0){return false;}var _l=lineWidth;var _a=0;var _b=x0;// Quick reject\nif(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;}/**\n * 三次贝塞尔曲线描边包含判断\n * @param  {number}  x0\n * @param  {number}  y0\n * @param  {number}  x1\n * @param  {number}  y1\n * @param  {number}  x2\n * @param  {number}  y2\n * @param  {number}  x3\n * @param  {number}  y3\n * @param  {number}  lineWidth\n * @param  {number}  x\n * @param  {number}  y\n * @return {boolean}\n */function containStroke$2(x0,y0,x1,y1,x2,y2,x3,y3,lineWidth,x,y){if(lineWidth===0){return false;}var _l=lineWidth;// Quick reject\nif(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;}/**\n * 二次贝塞尔曲线描边包含判断\n * @param  {number}  x0\n * @param  {number}  y0\n * @param  {number}  x1\n * @param  {number}  y1\n * @param  {number}  x2\n * @param  {number}  y2\n * @param  {number}  lineWidth\n * @param  {number}  x\n * @param  {number}  y\n * @return {boolean}\n */function containStroke$3(x0,y0,x1,y1,x2,y2,lineWidth,x,y){if(lineWidth===0){return false;}var _l=lineWidth;// Quick reject\nif(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$3=Math.PI*2;function normalizeRadian(angle){angle%=PI2$3;if(angle<0){angle+=PI2$3;}return angle;}var PI2$2=Math.PI*2;/**\n * 圆弧描边包含判断\n * @param  {number}  cx\n * @param  {number}  cy\n * @param  {number}  r\n * @param  {number}  startAngle\n * @param  {number}  endAngle\n * @param  {boolean}  anticlockwise\n * @param  {number} lineWidth\n * @param  {number}  x\n * @param  {number}  y\n * @return {Boolean}\n */function containStroke$4(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$2<1e-4){// Is a circle\nreturn true;}if(anticlockwise){var tmp=startAngle;startAngle=normalizeRadian(endAngle);endAngle=normalizeRadian(tmp);}else{startAngle=normalizeRadian(startAngle);endAngle=normalizeRadian(endAngle);}if(startAngle>endAngle){endAngle+=PI2$2;}var angle=Math.atan2(y,x);if(angle<0){angle+=PI2$2;}return angle>=startAngle&&angle<=endAngle||angle+PI2$2>=startAngle&&angle+PI2$2<=endAngle;}function windingLine(x0,y0,x1,y1,x,y){if(y>y0&&y>y1||y<y0&&y<y1){return 0;}// Ignore horizontal line\nif(y1===y0){return 0;}var dir=y1<y0?1:-1;var t=(y-y0)/(y1-y0);// Avoid winding error when intersection point is the connect point of two line of polygon\nif(t===1||t===0){dir=y1<y0?0.5:-0.5;}var x_=t*(x1-x0)+x0;// If (x, y) on the line, considered as \"contain\".\nreturn x_===x?Infinity:x_>x?dir:0;}var CMD$1=PathProxy.CMD;var PI2$1=Math.PI*2;var EPSILON$2=1e-4;function isAroundEqual(a,b){return Math.abs(a-b)<EPSILON$2;}// 临时数组\nvar 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){// Quick reject\nif(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_;var y1_;for(var i=0;i<nRoots;i++){var t=roots[i];// Avoid winding error when intersection point is the connect point of two line of polygon\nvar unit=t===0||t===1?0.5:1;var x_=cubicAt(x0,x1,x2,x3,t);if(x_<x){// Quick reject\ncontinue;}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){// 分成三段单调函数\nif(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{// 分成两段单调函数\nif(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){// Quick reject\nif(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++){// Remove one endpoint.\nvar unit=roots[i]===0||roots[i]===1?0.5:1;var x_=quadraticAt(x0,x1,x2,roots[i]);if(x_<x){// Quick reject\ncontinue;}if(roots[i]<t){w+=y_<y0?unit:-unit;}else{w+=y2<y_?unit:-unit;}}return w;}else{// Remove one endpoint.\nvar unit=roots[0]===0||roots[0]===1?0.5:1;var x_=quadraticAt(x0,x1,x2,roots[0]);if(x_<x){// Quick reject\nreturn 0;}return y2<y0?unit:-unit;}}}// TODO\n// Arc 旋转\nfunction 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 diff=Math.abs(startAngle-endAngle);if(diff<1e-4){return 0;}if(diff%PI2$1<1e-4){// Is a circle\nstartAngle=0;endAngle=PI2$1;var dir=anticlockwise?1:-1;if(x>=roots[0]+cx&&x<=roots[1]+cx){return dir;}else{return 0;}}if(anticlockwise){var tmp=startAngle;startAngle=normalizeRadian(endAngle);endAngle=normalizeRadian(tmp);}else{startAngle=normalizeRadian(startAngle);endAngle=normalizeRadian(endAngle);}if(startAngle>endAngle){endAngle+=PI2$1;}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$1+angle;}if(angle>=startAngle&&angle<=endAngle||angle+PI2$1>=startAngle&&angle+PI2$1<=endAngle){if(angle>Math.PI/2&&angle<Math.PI*1.5){dir=-dir;}w+=dir;}}}return w;}function containPath(data,lineWidth,isStroke,x,y){var w=0;var xi=0;var yi=0;var x0=0;var y0=0;for(var i=0;i<data.length;){var cmd=data[i++];// Begin a new subpath\nif(cmd===CMD$1.M&&i>1){// Close previous subpath\nif(!isStroke){w+=windingLine(xi,yi,x0,y0,x,y);}// 如果被任何一个 subpath 包含\n// if (w !== 0) {\n//     return true;\n// }\n}if(i===1){// 如果第一个命令是 L, C, Q\n// 则 previous point 同绘制命令的第一个 point\n//\n// 第一个命令为 Arc 的情况下会在后面特殊处理\nxi=data[i];yi=data[i+1];x0=xi;y0=yi;}switch(cmd){case CMD$1.M:// moveTo 命令重新创建一个新的 subpath, 并且更新新的起点\n// 在 closePath 的时候使用\nx0=data[i++];y0=data[i++];xi=x0;yi=y0;break;case CMD$1.L:if(isStroke){if(containStroke$1(xi,yi,data[i],data[i+1],lineWidth,x,y)){return true;}}else{// NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN\nw+=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$2(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$3(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:// TODO Arc 判断的开销比较大\nvar cx=data[i++];var cy=data[i++];var rx=data[i++];var ry=data[i++];var theta=data[i++];var dTheta=data[i++];// TODO Arc 旋转\ni+=1;var anticlockwise=1-data[i++];var x1=Math.cos(theta)*rx+cx;var y1=Math.sin(theta)*ry+cy;// 不是直接使用 arc 命令\nif(i>1){w+=windingLine(xi,yi,x1,y1,x,y);}else{// 第一个命令起点还未定义\nx0=x1;y0=y1;}// zr 使用scale来模拟椭圆, 这里也对x做一定的缩放\nvar _x=(x-cx)*ry/rx+cx;if(isStroke){if(containStroke$4(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++];var x1=x0+width;var y1=y0+height;if(isStroke){if(containStroke$1(x0,y0,x1,y0,lineWidth,x,y)||containStroke$1(x1,y0,x1,y1,lineWidth,x,y)||containStroke$1(x1,y1,x0,y1,lineWidth,x,y)||containStroke$1(x0,y1,x0,y0,lineWidth,x,y)){return true;}}else{// FIXME Clockwise ?\nw+=windingLine(x1,y0,x1,y1,x,y);w+=windingLine(x0,y1,x0,y0,x,y);}break;case CMD$1.Z:if(isStroke){if(containStroke$1(xi,yi,x0,y0,lineWidth,x,y)){return true;}}else{// Close a subpath\nw+=windingLine(xi,yi,x0,y0,x,y);// 如果被任何一个 subpath 包含\n// FIXME subpaths may overlap\n// if (w !== 0) {\n//     return true;\n// }\n}xi=x0;yi=y0;break;}}if(!isStroke&&!isAroundEqual(yi,y0)){w+=windingLine(xi,yi,x0,y0,x,y)||0;}return w!==0;}function _contain(pathData,x,y){return containPath(pathData,0,false,x,y);}function containStroke(pathData,lineWidth,x,y){return containPath(pathData,lineWidth,true,x,y);}var getCanvasPattern=Pattern.prototype.getCanvasPattern;var abs=Math.abs;var pathProxyForDraw=new PathProxy(true);/**\n * @alias module:zrender/graphic/Path\n * @extends module:zrender/graphic/Displayable\n * @constructor\n * @param {Object} opts\n */function Path(opts){Displayable.call(this,opts);/**\n     * @type {module:zrender/core/PathProxy}\n     * @readOnly\n     */this.path=null;}Path.prototype={constructor:Path,type:'path',__dirtyPath:true,strokeContainThreshold:5,// This item default to be false. But in map series in echarts,\n// in order to improve performance, it should be set to true,\n// so the shorty segment won't draw.\nsegmentIgnoreThreshold:0,/**\n     * See `module:zrender/src/graphic/helper/subPixelOptimize`.\n     * @type {boolean}\n     */subPixelOptimize:false,brush:function brush(ctx,prevEl){var style=this.style;var path=this.path||pathProxyForDraw;var hasStroke=style.hasStroke();var hasFill=style.hasFill();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;style.bind(ctx,this,prevEl);this.setTransform(ctx);if(this.__dirty){var rect;// Update gradient because bounding rect may changed\nif(hasFillGradient){rect=rect||this.getBoundingRect();this._fillGradient=style.getGradient(ctx,fill,rect);}if(hasStrokeGradient){rect=rect||this.getBoundingRect();this._strokeGradient=style.getGradient(ctx,stroke,rect);}}// Use the gradient or pattern\nif(hasFillGradient){// PENDING If may have affect the state\nctx.fillStyle=this._fillGradient;}else if(hasFillPattern){ctx.fillStyle=getCanvasPattern.call(fill,ctx);}if(hasStrokeGradient){ctx.strokeStyle=this._strokeGradient;}else if(hasStrokePattern){ctx.strokeStyle=getCanvasPattern.call(stroke,ctx);}var lineDash=style.lineDash;var lineDashOffset=style.lineDashOffset;var ctxLineDash=!!ctx.setLineDash;// Update path sx, sy\nvar scale=this.getGlobalScale();path.setScale(scale[0],scale[1],this.segmentIgnoreThreshold);// Proxy context\n// Rebuild path in following 2 cases\n// 1. Path is dirty\n// 2. Path needs javascript implemented lineDash stroking.\n//    In this case, lineDash information will not be saved in PathProxy\nif(this.__dirtyPath||lineDash&&!ctxLineDash&&hasStroke){path.beginPath(ctx);// Setting line dash before build path\nif(lineDash&&!ctxLineDash){path.setLineDash(lineDash);path.setLineDashOffset(lineDashOffset);}this.buildPath(path,this.shape,false);// Clear path dirty flag\nif(this.path){this.__dirtyPath=false;}}else{// Replay path building\nctx.beginPath();this.path.rebuildPath(ctx);}if(hasFill){if(style.fillOpacity!=null){var originalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.fillOpacity*style.opacity;path.fill(ctx);ctx.globalAlpha=originalGlobalAlpha;}else{path.fill(ctx);}}if(lineDash&&ctxLineDash){ctx.setLineDash(lineDash);ctx.lineDashOffset=lineDashOffset;}if(hasStroke){if(style.strokeOpacity!=null){var originalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.strokeOpacity*style.opacity;path.stroke(ctx);ctx.globalAlpha=originalGlobalAlpha;}else{path.stroke(ctx);}}if(lineDash&&ctxLineDash){// PENDING\n// Remove lineDash\nctx.setLineDash([]);}// Draw rect text\nif(style.text!=null){// Only restore transform when needs draw text.\nthis.restoreTransform(ctx);this.drawRectText(ctx,this.getBoundingRect());}},// When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath\n// Like in circle\nbuildPath:function buildPath(ctx,shapeCfg,inBundle){},createPathProxy:function createPathProxy(){this.path=new PathProxy();},getBoundingRect:function getBoundingRect(){var rect=this._rect;var style=this.style;var needsUpdateRect=!rect;if(needsUpdateRect){var path=this.path;if(!path){// Create path on demand.\npath=this.path=new PathProxy();}if(this.__dirtyPath){path.beginPath();this.buildPath(path,this.shape,false);}rect=path.getBoundingRect();}this._rect=rect;if(style.hasStroke()){// Needs update rect with stroke lineWidth when\n// 1. Element changes scale or lineWidth\n// 2. Shape is changed\nvar rectWithStroke=this._rectWithStroke||(this._rectWithStroke=rect.clone());if(this.__dirty||needsUpdateRect){rectWithStroke.copy(rect);// FIXME Must after updateTransform\nvar w=style.lineWidth;// PENDING, Min line width is needed when line is horizontal or vertical\nvar lineScale=style.strokeNoScale?this.getLineScale():1;// Only add extra hover lineWidth when there are no fill\nif(!style.hasFill()){w=Math.max(w,this.strokeContainThreshold||4);}// Consider line width\n// Line scale can't be 0;\nif(lineScale>1e-10){rectWithStroke.width+=w/lineScale;rectWithStroke.height+=w/lineScale;rectWithStroke.x-=w/lineScale/2;rectWithStroke.y-=w/lineScale/2;}}// Return rect with stroke\nreturn rectWithStroke;}return rect;},contain:function contain(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 pathData=this.path.data;if(style.hasStroke()){var lineWidth=style.lineWidth;var lineScale=style.strokeNoScale?this.getLineScale():1;// Line scale can't be 0;\nif(lineScale>1e-10){// Only add extra hover lineWidth when there are no fill\nif(!style.hasFill()){lineWidth=Math.max(lineWidth,this.strokeContainThreshold);}if(containStroke(pathData,lineWidth/lineScale,x,y)){return true;}}}if(style.hasFill()){return _contain(pathData,x,y);}}return false;},/**\n     * @param  {boolean} dirtyPath\n     */dirty:function dirty(dirtyPath){if(dirtyPath==null){dirtyPath=true;}// Only mark dirty, not mark clean\nif(dirtyPath){this.__dirtyPath=dirtyPath;this._rect=null;}this.__dirty=this.__dirtyText=true;this.__zr&&this.__zr.refresh();// Used as a clipping path\nif(this.__clipTarget){this.__clipTarget.dirty();}},/**\n     * Alias for animate('shape')\n     * @param {boolean} loop\n     */animateShape:function animateShape(loop){return this.animate('shape',loop);},// Overwrite attrKV\nattrKV:function attrKV(key,value){// FIXME\nif(key==='shape'){this.setShape(value);this.__dirtyPath=true;this._rect=null;}else{Displayable.prototype.attrKV.call(this,key,value);}},/**\n     * @param {Object|string} key\n     * @param {*} value\n     */setShape:function setShape(key,value){var shape=this.shape;// Path from string may not have shape\nif(shape){if(isObject$1(key)){for(var name in key){if(key.hasOwnProperty(name)){shape[name]=key[name];}}}else{shape[key]=value;}this.dirty(true);}return this;},getLineScale:function getLineScale(){var m=this.transform;// Get the line scale.\n// Determinant of `m` means how much the area is enlarged by the\n// transformation. So its square root can be used as a scale factor\n// for width.\nreturn 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;}};/**\n * 扩展一个 Path element, 比如星形，圆等。\n * Extend a path element\n * @param {Object} props\n * @param {string} props.type Path type\n * @param {Function} props.init Initialize\n * @param {Function} props.buildPath Overwrite buildPath method\n * @param {Object} [props.style] Extended default style config\n * @param {Object} [props.shape] Extended default shape config\n */Path.extend=function(defaults$$1){var Sub=function Sub(opts){Path.call(this,opts);if(defaults$$1.style){// Extend default style\nthis.style.extendFrom(defaults$$1.style,false);}// Extend default shape\nvar defaultShape=defaults$$1.shape;if(defaultShape){this.shape=this.shape||{};var thisShape=this.shape;for(var name in defaultShape){if(!thisShape.hasOwnProperty(name)&&defaultShape.hasOwnProperty(name)){thisShape[name]=defaultShape[name];}}}defaults$$1.init&&defaults$$1.init.call(this,opts);};inherits(Sub,Path);// FIXME 不能 extend position, rotation 等引用对象\nfor(var name in defaults$$1){// Extending prototype values and methods\nif(name!=='style'&&name!=='shape'){Sub.prototype[name]=defaults$$1[name];}}return Sub;};inherits(Path,Displayable);var CMD$2=PathProxy.CMD;var points=[[],[],[]];var mathSqrt$3=Math.sqrt;var mathAtan2=Math.atan2;var transformPath=function transformPath(path,m){var data=path.data;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<data.length;){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$3(m[0]*m[0]+m[1]*m[1]);var sy=mathSqrt$3(m[2]*m[2]+m[3]*m[3]);var angle=mathAtan2(-m[1]/sy,m[0]/sx);// cx\ndata[i]*=sx;data[i++]+=x;// cy\ndata[i]*=sy;data[i++]+=y;// Scale rx and ry\n// FIXME Assume psi is 0 here\ndata[i++]*=sx;data[i++]*=sy;// Start angle\ndata[i++]+=angle;// end angle\ndata[i++]+=angle;// FIXME psi\ni+=2;j=i;break;case R:// x0, y0\np[0]=data[i++];p[1]=data[i++];applyTransform(p,p,m);data[j++]=p[0];data[j++]=p[1];// x1, y1\np[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=points[k];p[0]=data[i++];p[1]=data[i++];applyTransform(p,p,m);// Write back\ndata[j++]=p[0];data[j++]=p[1];}}};// command chars\n// var cc = [\n//     'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',\n//     'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'\n// ];\nvar mathSqrt=Math.sqrt;var mathSin=Math.sin;var mathCos=Math.cos;var PI=Math.PI;var vMag=function vMag(v){return Math.sqrt(v[0]*v[0]+v[1]*v[1]);};var vRatio=function vRatio(u,v){return(u[0]*v[0]+u[1]*v[1])/(vMag(u)*vMag(v));};var vAngle=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/180.0);var xp=mathCos(psi)*(x1-x2)/2.0+mathSin(psi)*(y1-y2)/2.0;var yp=-1*mathSin(psi)*(x1-x2)/2.0+mathCos(psi)*(y1-y2)/2.0;var lambda=xp*xp/(rx*rx)+yp*yp/(ry*ry);if(lambda>1){rx*=mathSqrt(lambda);ry*=mathSqrt(lambda);}var f=(fa===fs?-1:1)*mathSqrt((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(psi)*cxp-mathSin(psi)*cyp;var cy=(y1+y2)/2.0+mathSin(psi)*cxp+mathCos(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;}if(vRatio(u,v)>=1){dTheta=0;}if(fs===0&&dTheta>0){dTheta=dTheta-2*PI;}if(fs===1&&dTheta<0){dTheta=dTheta+2*PI;}path.addData(cmd,cx,cy,rx,ry,theta,dTheta,psi,fs);}var commandReg=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;// Consider case:\n// (1) delimiter can be comma or space, where continuous commas\n// or spaces should be seen as one comma.\n// (2) value can be like:\n// '2e-4', 'l.5.9' (ignore 0), 'M-10-10', 'l-2.43e-1,34.9983',\n// 'l-.5E1,54', '121-23-44-11' (no delimiter)\nvar numberReg=/-?([0-9]*\\.)?[0-9]+([eE]-?[0-9]+)?/g;// var valueSplitReg = /[\\s,]+/;\nfunction createPathProxyFromString(data){if(!data){return new PathProxy();}// var data = data.replace(/-/g, ' -')\n//     .replace(/  /g, ' ')\n//     .replace(/ /g, ',')\n//     .replace(/,,/g, ',');\n// var n;\n// create pipes so that we can split the data\n// for (n = 0; n < cc.length; n++) {\n//     cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);\n// }\n// data = data.replace(/-/g, ',-');\n// create array\n// var arr = cs.split('|');\n// init context point\nvar cpx=0;var cpy=0;var subpathX=cpx;var subpathY=cpy;var prevCmd;var path=new PathProxy();var CMD=PathProxy.CMD;// commandReg.lastIndex = 0;\n// var cmdResult;\n// while ((cmdResult = commandReg.exec(data)) != null) {\n//     var cmdStr = cmdResult[1];\n//     var cmdContent = cmdResult[2];\nvar cmdList=data.match(commandReg);for(var l=0;l<cmdList.length;l++){var cmdText=cmdList[l];var cmdStr=cmdText.charAt(0);var cmd;// String#split is faster a little bit than String#replace or RegExp#exec.\n// var p = cmdContent.split(valueSplitReg);\n// var pLen = 0;\n// for (var i = 0; i < p.length; i++) {\n//     // '' and other invalid str => NaN\n//     var val = parseFloat(p[i]);\n//     !isNaN(val) && (p[pLen++] = val);\n// }\nvar 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;var ctlPty;var rx;var ry;var psi;var fa;var fs;var x1=cpx;var y1=cpy;// convert l, H, h, V, and v to L\nswitch(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;var len=path.len();var 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;var len=path.len();var 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;var len=path.len();var 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;var len=path.len();var 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);// z may be in the middle of the path.\ncpx=subpathX;cpy=subpathY;}prevCmd=cmd;}path.toStatic();return path;}// TODO Optimize double memory cost problem\nfunction createPathOptions(str,opts){var pathProxy=createPathProxyFromString(str);opts=opts||{};opts.buildPath=function(path){if(path.setData){path.setData(pathProxy.data);// Svg and vml renderer don't have context\nvar ctx=path.getContext();if(ctx){path.rebuildPath(ctx);}}else{var ctx=path;pathProxy.rebuildPath(ctx);}};opts.applyTransform=function(m){transformPath(pathProxy,m);this.dirty(true);};return opts;}/**\n * Create a Path object from path string data\n * http://www.w3.org/TR/SVG/paths.html#PathData\n * @param  {Object} opts Other options\n */function createFromString(str,opts){return new Path(createPathOptions(str,opts));}/**\n * Create a Path class from path string data\n * @param  {string} str\n * @param  {Object} opts Other options\n */function extendFromString(str,opts){return Path.extend(createPathOptions(str,opts));}/**\n * Merge multiple paths\n */ // TODO Apply transform\n// TODO stroke dash\n// TODO Optimize double memory cost problem\nfunction mergePath$1(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.__dirtyPath){pathEl.buildPath(pathEl.path,pathEl.shape,true);}pathList.push(pathEl.path);}var pathBundle=new Path(opts);// Need path proxy.\npathBundle.createPathProxy();pathBundle.buildPath=function(path){path.appendPath(pathList);// Svg and vml renderer don't have context\nvar ctx=path.getContext();if(ctx){path.rebuildPath(ctx);}};return pathBundle;}/**\n * @alias zrender/graphic/Text\n * @extends module:zrender/graphic/Displayable\n * @constructor\n * @param {Object} opts\n */var Text=function Text(opts){// jshint ignore:line\nDisplayable.call(this,opts);};Text.prototype={constructor:Text,type:'text',brush:function brush(ctx,prevEl){var style=this.style;// Optimize, avoid normalize every time.\nthis.__dirty&&normalizeTextStyle(style,true);// Use props with prefix 'text'.\nstyle.fill=style.stroke=style.shadowBlur=style.shadowColor=style.shadowOffsetX=style.shadowOffsetY=null;var text=style.text;// Convert to string\ntext!=null&&(text+='');// Do not apply style.bind in Text node. Because the real bind job\n// is in textHelper.renderText, and performance of text render should\n// be considered.\n// style.bind(ctx, this, prevEl);\nif(!needDrawText(text,style)){// The current el.style is not applied\n// and should not be used as cache.\nctx.__attrCachedBy=ContextCachedBy.NONE;return;}this.setTransform(ctx);renderText(this,ctx,text,style,null,prevEl);this.restoreTransform(ctx);},getBoundingRect:function getBoundingRect(){var style=this.style;// Optimize, avoid normalize every time.\nthis.__dirty&&normalizeTextStyle(style,true);if(!this._rect){var text=style.text;text!=null?text+='':text='';var rect=_getBoundingRect(style.text+'',style.font,style.textAlign,style.textVerticalAlign,style.textPadding,style.textLineHeight,style.rich);rect.x+=style.x||0;rect.y+=style.y||0;if(getStroke(style.textStroke,style.textStrokeWidth)){var w=style.textStrokeWidth;rect.x-=w/2;rect.y-=w/2;rect.width+=w;rect.height+=w;}this._rect=rect;}return this._rect;}};inherits(Text,Displayable);/**\n * 圆形\n * @module zrender/shape/Circle\n */var Circle=Path.extend({type:'circle',shape:{cx:0,cy:0,r:0},buildPath:function buildPath(ctx,shape,inBundle){// Better stroking in ShapeBundle\n// Always do it may have performence issue ( fill may be 2x more cost)\nif(inBundle){ctx.moveTo(shape.cx+shape.r,shape.cy);}// else {\n//     if (ctx.allocate && !ctx.data.length) {\n//         ctx.allocate(ctx.CMD_MEM_SIZE.A);\n//     }\n// }\n// Better stroking in ShapeBundle\n// ctx.moveTo(shape.cx + shape.r, shape.cy);\nctx.arc(shape.cx,shape.cy,shape.r,0,Math.PI*2,true);}});// Fix weird bug in some version of IE11 (like 11.0.9600.178**),\n// where exception \"unexpected call to method or property access\"\n// might be thrown when calling ctx.fill or ctx.stroke after a path\n// whose area size is zero is drawn and ctx.clip() is called and\n// shadowBlur is set. See #4572, #3112, #5777.\n// (e.g.,\n//  ctx.moveTo(10, 10);\n//  ctx.lineTo(20, 10);\n//  ctx.closePath();\n//  ctx.clip();\n//  ctx.shadowBlur = 10;\n//  ...\n//  ctx.fill();\n// )\nvar shadowTemp=[['shadowBlur',0],['shadowColor','#000'],['shadowOffsetX',0],['shadowOffsetY',0]];var fixClipWithShadow=function fixClipWithShadow(orignalBrush){// version string can be: '11.0'\nreturn env$1.browser.ie&&env$1.browser.version>=11?function(){var clipPaths=this.__clipPaths;var style=this.style;var modified;if(clipPaths){for(var i=0;i<clipPaths.length;i++){var clipPath=clipPaths[i];var shape=clipPath&&clipPath.shape;var type=clipPath&&clipPath.type;if(shape&&(type==='sector'&&shape.startAngle===shape.endAngle||type==='rect'&&(!shape.width||!shape.height))){for(var j=0;j<shadowTemp.length;j++){// It is save to put shadowTemp static, because shadowTemp\n// will be all modified each item brush called.\nshadowTemp[j][2]=style[shadowTemp[j][0]];style[shadowTemp[j][0]]=shadowTemp[j][1];}modified=true;break;}}}orignalBrush.apply(this,arguments);if(modified){for(var j=0;j<shadowTemp.length;j++){style[shadowTemp[j][0]]=shadowTemp[j][2];}}}:orignalBrush;};/**\n * 扇形\n * @module zrender/graphic/shape/Sector\n */var Sector=Path.extend({type:'sector',shape:{cx:0,cy:0,r0:0,r:0,startAngle:0,endAngle:Math.PI*2,clockwise:true},brush:fixClipWithShadow(Path.prototype.brush),buildPath:function buildPath(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 startAngle=shape.startAngle;var endAngle=shape.endAngle;var clockwise=shape.clockwise;var unitX=Math.cos(startAngle);var unitY=Math.sin(startAngle);ctx.moveTo(unitX*r0+x,unitY*r0+y);ctx.lineTo(unitX*r+x,unitY*r+y);ctx.arc(x,y,r,startAngle,endAngle,!clockwise);ctx.lineTo(Math.cos(endAngle)*r0+x,Math.sin(endAngle)*r0+y);if(r0!==0){ctx.arc(x,y,r0,endAngle,startAngle,clockwise);}ctx.closePath();}});/**\n * 圆环\n * @module zrender/graphic/shape/Ring\n */var Ring=Path.extend({type:'ring',shape:{cx:0,cy:0,r:0,r0:0},buildPath:function buildPath(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);}});/**\n * Catmull-Rom spline 插值折线\n * @module zrender/shape/util/smoothSpline\n * @author pissang (https://www.github.com/pissang)\n *         Kener (@Kener-林峰, kener.linfeng@gmail.com)\n *         errorrik (errorrik@gmail.com)\n */ /**\n * @inner\n */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;}/**\n * @alias module:zrender/shape/util/smoothSpline\n * @param {Array} points 线段顶点数组\n * @param {boolean} isLoop\n * @return {Array}\n */var smoothSpline=function smoothSpline(points,isLoop){var len$$1=points.length;var ret=[];var distance$$1=0;for(var i=1;i<len$$1;i++){distance$$1+=distance(points[i-1],points[i]);}var segs=distance$$1/2;segs=segs<len$$1?len$$1:segs;for(var i=0;i<segs;i++){var pos=i/(segs-1)*(isLoop?len$$1:len$$1-1);var idx=Math.floor(pos);var w=pos-idx;var p0;var p1=points[idx%len$$1];var p2;var p3;if(!isLoop){p0=points[idx===0?idx:idx-1];p2=points[idx>len$$1-2?len$$1-1:idx+1];p3=points[idx>len$$1-3?len$$1-1:idx+2];}else{p0=points[(idx-1+len$$1)%len$$1];p2=points[(idx+1)%len$$1];p3=points[(idx+2)%len$$1];}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;};/**\n * 贝塞尔平滑曲线\n * @module zrender/shape/util/smoothBezier\n * @author pissang (https://www.github.com/pissang)\n *         Kener (@Kener-林峰, kener.linfeng@gmail.com)\n *         errorrik (errorrik@gmail.com)\n */ /**\n * 贝塞尔平滑曲线\n * @alias module:zrender/shape/util/smoothBezier\n * @param {Array} points 线段顶点数组\n * @param {number} smooth 平滑等级, 0-1\n * @param {boolean} isLoop\n * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内\n *                           比如 [[0, 0], [100, 100]], 这个包围盒会与\n *                           整个折线的包围盒做一个并集用来约束控制点。\n * @param {Array} 计算出来的控制点数组\n */var smoothBezier=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$$1=points.length;i<len$$1;i++){min(min$$1,min$$1,points[i]);max(max$$1,max$$1,points[i]);}// 与指定的包围盒做并集\nmin(min$$1,min$$1,constraint[0]);max(max$$1,max$$1,constraint[1]);}for(var i=0,len$$1=points.length;i<len$$1;i++){var point=points[i];if(isLoop){prevPoint=points[i?i-1:len$$1-1];nextPoint=points[(i+1)%len$$1];}else{if(i===0||i===len$$1-1){cps.push(clone$1(points[i]));continue;}else{prevPoint=points[i-1];nextPoint=points[i+1];}}sub(v,nextPoint,prevPoint);// use degree to scale the handle length\nscale(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 points=shape.points;var smooth=shape.smooth;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();}}/**\n * 多边形\n * @module zrender/shape/Polygon\n */var Polygon=Path.extend({type:'polygon',shape:{points:null,smooth:false,smoothConstraint:null},buildPath:function buildPath(ctx,shape){buildPath$1(ctx,shape,true);}});/**\n * @module zrender/graphic/shape/Polyline\n */var Polyline=Path.extend({type:'polyline',shape:{points:null,smooth:false,smoothConstraint:null},style:{stroke:'#000',fill:null},buildPath:function buildPath(ctx,shape){buildPath$1(ctx,shape,false);}});/**\n * Sub-pixel optimize for canvas rendering, prevent from blur\n * when rendering a thin vertical/horizontal line.\n */var round=Math.round;/**\n * Sub pixel optimize line for canvas\n *\n * @param {Object} outputShape The modification will be performed on `outputShape`.\n *                 `outputShape` and `inputShape` can be the same object.\n *                 `outputShape` object can be used repeatly, because all of\n *                 the `x1`, `x2`, `y1`, `y2` will be assigned in this method.\n * @param {Object} [inputShape]\n * @param {number} [inputShape.x1]\n * @param {number} [inputShape.y1]\n * @param {number} [inputShape.x2]\n * @param {number} [inputShape.y2]\n * @param {Object} [style]\n * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.\n */function subPixelOptimizeLine$1(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;}if(round(x1*2)===round(x2*2)){outputShape.x1=outputShape.x2=subPixelOptimize$1(x1,lineWidth,true);}if(round(y1*2)===round(y2*2)){outputShape.y1=outputShape.y2=subPixelOptimize$1(y1,lineWidth,true);}}/**\n * Sub pixel optimize rect for canvas\n *\n * @param {Object} outputShape The modification will be performed on `outputShape`.\n *                 `outputShape` and `inputShape` can be the same object.\n *                 `outputShape` object can be used repeatly, because all of\n *                 the `x`, `y`, `width`, `height` will be assigned in this method.\n * @param {Object} [inputShape]\n * @param {number} [inputShape.x]\n * @param {number} [inputShape.y]\n * @param {number} [inputShape.width]\n * @param {number} [inputShape.height]\n * @param {Object} [style]\n * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.\n */function subPixelOptimizeRect$1(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.x=subPixelOptimize$1(originX,lineWidth,true);outputShape.y=subPixelOptimize$1(originY,lineWidth,true);outputShape.width=Math.max(subPixelOptimize$1(originX+originWidth,lineWidth,false)-outputShape.x,originWidth===0?0:1);outputShape.height=Math.max(subPixelOptimize$1(originY+originHeight,lineWidth,false)-outputShape.y,originHeight===0?0:1);}/**\n * Sub pixel optimize for canvas\n *\n * @param {number} position Coordinate, such as x, y\n * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.\n * @param {boolean=} positiveOrNegative Default false (negative).\n * @return {number} Optimized position.\n */function subPixelOptimize$1(position,lineWidth,positiveOrNegative){if(!lineWidth){return position;}// Assure that (position + lineWidth / 2) is near integer edge,\n// otherwise line will be fuzzy in canvas.\nvar doubledPosition=round(position*2);return(doubledPosition+round(lineWidth))%2===0?doubledPosition/2:(doubledPosition+(positiveOrNegative?1:-1))/2;}/**\n * 矩形\n * @module zrender/graphic/shape/Rect\n */ // Avoid create repeatly.\nvar subPixelOptimizeOutputShape={};var Rect=Path.extend({type:'rect',shape:{// 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4\n// r缩写为1         相当于 [1, 1, 1, 1]\n// r缩写为[1]       相当于 [1, 1, 1, 1]\n// r缩写为[1, 2]    相当于 [1, 2, 1, 2]\n// r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2]\nr:0,x:0,y:0,width:0,height:0},buildPath:function buildPath(ctx,shape){var x;var y;var width;var height;if(this.subPixelOptimize){subPixelOptimizeRect$1(subPixelOptimizeOutputShape,shape,this.style);x=subPixelOptimizeOutputShape.x;y=subPixelOptimizeOutputShape.y;width=subPixelOptimizeOutputShape.width;height=subPixelOptimizeOutputShape.height;subPixelOptimizeOutputShape.r=shape.r;shape=subPixelOptimizeOutputShape;}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);}ctx.closePath();return;}});/**\n * 直线\n * @module zrender/graphic/shape/Line\n */ // Avoid create repeatly.\nvar subPixelOptimizeOutputShape$1={};var Line=Path.extend({type:'line',shape:{// Start point\nx1:0,y1:0,// End point\nx2:0,y2:0,percent:1},style:{stroke:'#000',fill:null},buildPath:function buildPath(ctx,shape){var x1;var y1;var x2;var y2;if(this.subPixelOptimize){subPixelOptimizeLine$1(subPixelOptimizeOutputShape$1,shape,this.style);x1=subPixelOptimizeOutputShape$1.x1;y1=subPixelOptimizeOutputShape$1.y1;x2=subPixelOptimizeOutputShape$1.x2;y2=subPixelOptimizeOutputShape$1.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);},/**\n     * Get point at percent\n     * @param  {number} percent\n     * @return {Array.<number>}\n     */pointAt:function pointAt(p){var shape=this.shape;return[shape.x1*(1-p)+shape.x2*p,shape.y1*(1-p)+shape.y2*p];}});/**\n * 贝塞尔曲线\n * @module zrender/shape/BezierCurve\n */var out=[];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=Path.extend({type:'bezier-curve',shape:{x1:0,y1:0,x2:0,y2:0,cpx1:0,cpy1:0,// cpx2: 0,\n// cpy2: 0\n// Curve show percent, for animating\npercent:1},style:{stroke:'#000',fill:null},buildPath:function buildPath(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);}},/**\n     * Get point at percent\n     * @param  {number} t\n     * @return {Array.<number>}\n     */pointAt:function pointAt(t){return someVectorAt(this.shape,t,false);},/**\n     * Get tangent at percent\n     * @param  {number} t\n     * @return {Array.<number>}\n     */tangentAt:function tangentAt(t){var p=someVectorAt(this.shape,t,true);return normalize(p,p);}});/**\n * 圆弧\n * @module zrender/graphic/shape/Arc\n */var Arc=Path.extend({type:'arc',shape:{cx:0,cy:0,r:0,startAngle:0,endAngle:Math.PI*2,clockwise:true},style:{stroke:'#000',fill:null},buildPath:function buildPath(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);}});// CompoundPath to improve performance\nvar CompoundPath=Path.extend({type:'compound',shape:{paths:null},_updatePathDirty:function _updatePathDirty(){var dirtyPath=this.__dirtyPath;var paths=this.shape.paths;for(var i=0;i<paths.length;i++){// Mark as dirty if any subpath is dirty\ndirtyPath=dirtyPath||paths[i].__dirtyPath;}this.__dirtyPath=dirtyPath;this.__dirty=this.__dirty||dirtyPath;},beforeBrush:function beforeBrush(){this._updatePathDirty();var paths=this.shape.paths||[];var scale=this.getGlobalScale();// Update path scale\nfor(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);}},buildPath:function buildPath(ctx,shape){var paths=shape.paths||[];for(var i=0;i<paths.length;i++){paths[i].buildPath(ctx,paths[i].shape,true);}},afterBrush:function afterBrush(){var paths=this.shape.paths||[];for(var i=0;i<paths.length;i++){paths[i].__dirtyPath=false;}},getBoundingRect:function getBoundingRect(){this._updatePathDirty();return Path.prototype.getBoundingRect.call(this);}});/**\n * @param {Array.<Object>} colorStops\n */var Gradient=function Gradient(colorStops){this.colorStops=colorStops||[];};Gradient.prototype={constructor:Gradient,addColorStop:function addColorStop(offset,color){this.colorStops.push({offset:offset,color:color});}};/**\n * x, y, x2, y2 are all percent from 0 to 1\n * @param {number} [x=0]\n * @param {number} [y=0]\n * @param {number} [x2=1]\n * @param {number} [y2=0]\n * @param {Array.<Object>} colorStops\n * @param {boolean} [globalCoord=false]\n */var LinearGradient=function LinearGradient(x,y,x2,y2,colorStops,globalCoord){// Should do nothing more in this constructor. Because gradient can be\n// declard by `color: {type: 'linear', colorStops: ...}`, where\n// this constructor will not be called.\nthis.x=x==null?0:x;this.y=y==null?0:y;this.x2=x2==null?1:x2;this.y2=y2==null?0:y2;// Can be cloned\nthis.type='linear';// If use global coord\nthis.global=globalCoord||false;Gradient.call(this,colorStops);};LinearGradient.prototype={constructor:LinearGradient};inherits(LinearGradient,Gradient);/**\n * x, y, r are all percent from 0 to 1\n * @param {number} [x=0.5]\n * @param {number} [y=0.5]\n * @param {number} [r=0.5]\n * @param {Array.<Object>} [colorStops]\n * @param {boolean} [globalCoord=false]\n */var RadialGradient=function RadialGradient(x,y,r,colorStops,globalCoord){// Should do nothing more in this constructor. Because gradient can be\n// declard by `color: {type: 'radial', colorStops: ...}`, where\n// this constructor will not be called.\nthis.x=x==null?0.5:x;this.y=y==null?0.5:y;this.r=r==null?0.5:r;// Can be cloned\nthis.type='radial';// If use global coord\nthis.global=globalCoord||false;Gradient.call(this,colorStops);};RadialGradient.prototype={constructor:RadialGradient};inherits(RadialGradient,Gradient);/**\n * Displayable for incremental rendering. It will be rendered in a separate layer\n * IncrementalDisplay have two main methods. `clearDisplayables` and `addDisplayables`\n * addDisplayables will render the added displayables incremetally.\n *\n * It use a not clearFlag to tell the painter don't clear the layer if it's the first element.\n */ // TODO Style override ?\nfunction IncrementalDisplayble(opts){Displayable.call(this,opts);this._displayables=[];this._temporaryDisplayables=[];this._cursor=0;this.notClear=true;}IncrementalDisplayble.prototype.incremental=true;IncrementalDisplayble.prototype.clearDisplaybles=function(){this._displayables=[];this._temporaryDisplayables=[];this._cursor=0;this.dirty();this.notClear=false;};IncrementalDisplayble.prototype.addDisplayable=function(displayable,notPersistent){if(notPersistent){this._temporaryDisplayables.push(displayable);}else{this._displayables.push(displayable);}this.dirty();};IncrementalDisplayble.prototype.addDisplayables=function(displayables,notPersistent){notPersistent=notPersistent||false;for(var i=0;i<displayables.length;i++){this.addDisplayable(displayables[i],notPersistent);}};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];// PENDING\ndisplayable.parent=this;displayable.update();displayable.parent=null;}for(var i=0;i<this._temporaryDisplayables.length;i++){var displayable=this._temporaryDisplayables[i];// PENDING\ndisplayable.parent=this;displayable.update();displayable.parent=null;}};IncrementalDisplayble.prototype.brush=function(ctx,prevEl){// Render persistant displayables.\nfor(var i=this._cursor;i<this._displayables.length;i++){var displayable=this._displayables[i];displayable.beforeBrush&&displayable.beforeBrush(ctx);displayable.brush(ctx,i===this._cursor?null:this._displayables[i-1]);displayable.afterBrush&&displayable.afterBrush(ctx);}this._cursor=i;// Render temporary displayables.\nfor(var i=0;i<this._temporaryDisplayables.length;i++){var displayable=this._temporaryDisplayables[i];displayable.beforeBrush&&displayable.beforeBrush(ctx);displayable.brush(ctx,i===0?null:this._temporaryDisplayables[i-1]);displayable.afterBrush&&displayable.afterBrush(ctx);}this._temporaryDisplayables=[];this.notClear=true;};var m=[];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;};inherits(IncrementalDisplayble,Displayable);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var mathMax$1=Math.max;var mathMin$1=Math.min;var EMPTY_OBJ={};var Z2_EMPHASIS_LIFT=1;// key: label model property nane, value: style property name.\nvar CACHED_LABEL_STYLE_PROPERTIES={color:'textFill',textBorderColor:'textStroke',textBorderWidth:'textStrokeWidth'};var EMPHASIS='emphasis';var NORMAL='normal';// Reserve 0 as default.\nvar _highlightNextDigit=1;var _highlightKeyMap={};var _customShapeMap={};/**\n * Extend shape with parameters\n */function extendShape(opts){return Path.extend(opts);}/**\n * Extend path\n */function extendPath(pathData,opts){return extendFromString(pathData,opts);}/**\n * Register a user defined shape.\n * The shape class can be fetched by `getShapeClass`\n * This method will overwrite the registered shapes, including\n * the registered built-in shapes, if using the same `name`.\n * The shape can be used in `custom series` and\n * `graphic component` by declaring `{type: name}`.\n *\n * @param {string} name\n * @param {Object} ShapeClass Can be generated by `extendShape`.\n */function registerShape(name,ShapeClass){_customShapeMap[name]=ShapeClass;}/**\n * Find shape class registered by `registerShape`. Usually used in\n * fetching user defined shape.\n *\n * [Caution]:\n * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared\n * to use user registered shapes.\n * Because the built-in shape (see `getBuiltInShape`) will be registered by\n * `registerShape` by default. That enables users to get both built-in\n * shapes as well as the shapes belonging to themsleves. But users can overwrite\n * the built-in shapes by using names like 'circle', 'rect' via calling\n * `registerShape`. So the echarts inner featrues should not fetch shapes from here\n * in case that it is overwritten by users, except that some features, like\n * `custom series`, `graphic component`, do it deliberately.\n *\n * (2) In the features like `custom series`, `graphic component`, the user input\n * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic\n * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names\n * are reserved names, that is, if some user register a shape named `'image'`,\n * the shape will not be used. If we intending to add some more reserved names\n * in feature, that might bring break changes (disable some existing user shape\n * names). But that case probably rearly happen. So we dont make more mechanism\n * to resolve this issue here.\n *\n * @param {string} name\n * @return {Object} The shape class. If not found, return nothing.\n */function getShapeClass(name){if(_customShapeMap.hasOwnProperty(name)){return _customShapeMap[name];}}/**\n * Create a path element from path data string\n * @param {string} pathData\n * @param {Object} opts\n * @param {module:zrender/core/BoundingRect} rect\n * @param {string} [layout=cover] 'center' or 'cover'\n */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;}/**\n * Create a image element from image url\n * @param {string} imageUrl image url\n * @param {Object} opts options\n * @param {module:zrender/core/BoundingRect} rect constrain rect\n * @param {string} [layout=cover] 'center' or 'cover'\n */function makeImage(imageUrl,rect,layout){var path=new ZImage({style:{image:imageUrl,x:rect.x,y:rect.y,width:rect.width,height:rect.height},onload:function onload(img){if(layout==='center'){var boundingRect={width:img.width,height:img.height};path.setStyle(centerGraphic(rect,boundingRect));}}});return path;}/**\n * Get position of centered element in bounding box.\n *\n * @param  {Object} rect         element local bounding box\n * @param  {Object} boundingRect constraint bounding box\n * @return {Object} element position containing x, y, width, and height\n */function centerGraphic(rect,boundingRect){// Set rect to center, keep width / height ratio.\nvar 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=mergePath$1;/**\n * Resize a path to fit the rect\n * @param {module:zrender/graphic/Path} path\n * @param {Object} rect\n */function resizePath(path,rect){if(!path.applyTransform){return;}var pathRect=path.getBoundingRect();var m=pathRect.calculateTransform(rect);path.applyTransform(m);}/**\n * Sub pixel optimize line for canvas\n *\n * @param {Object} param\n * @param {Object} [param.shape]\n * @param {number} [param.shape.x1]\n * @param {number} [param.shape.y1]\n * @param {number} [param.shape.x2]\n * @param {number} [param.shape.y2]\n * @param {Object} [param.style]\n * @param {number} [param.style.lineWidth]\n * @return {Object} Modified param\n */function subPixelOptimizeLine(param){subPixelOptimizeLine$1(param.shape,param.shape,param.style);return param;}/**\n * Sub pixel optimize rect for canvas\n *\n * @param {Object} param\n * @param {Object} [param.shape]\n * @param {number} [param.shape.x]\n * @param {number} [param.shape.y]\n * @param {number} [param.shape.width]\n * @param {number} [param.shape.height]\n * @param {Object} [param.style]\n * @param {number} [param.style.lineWidth]\n * @return {Object} Modified param\n */function subPixelOptimizeRect(param){subPixelOptimizeRect$1(param.shape,param.shape,param.style);return param;}/**\n * Sub pixel optimize for canvas\n *\n * @param {number} position Coordinate, such as x, y\n * @param {number} lineWidth Should be nonnegative integer.\n * @param {boolean=} positiveOrNegative Default false (negative).\n * @return {number} Optimized position.\n */var subPixelOptimize=subPixelOptimize$1;function hasFillOrStroke(fillOrStroke){return fillOrStroke!=null&&fillOrStroke!=='none';}// Most lifted color are duplicated.\nvar liftedColorMap=createHashMap();var liftedColorCount=0;function liftColor(color){if(typeof color!=='string'){return color;}var liftedColor=liftedColorMap.get(color);if(!liftedColor){liftedColor=lift(color,-0.1);if(liftedColorCount<10000){liftedColorMap.set(color,liftedColor);liftedColorCount++;}}return liftedColor;}function cacheElementStl(el){if(!el.__hoverStlDirty){return;}el.__hoverStlDirty=false;var hoverStyle=el.__hoverStl;if(!hoverStyle){el.__cachedNormalStl=el.__cachedNormalZ2=null;return;}var normalStyle=el.__cachedNormalStl={};el.__cachedNormalZ2=el.z2;var elStyle=el.style;for(var name in hoverStyle){// See comment in `singleEnterEmphasis`.\nif(hoverStyle[name]!=null){normalStyle[name]=elStyle[name];}}// Always cache fill and stroke to normalStyle for lifting color.\nnormalStyle.fill=elStyle.fill;normalStyle.stroke=elStyle.stroke;}function singleEnterEmphasis(el){var hoverStl=el.__hoverStl;if(!hoverStl||el.__highlighted){return;}var zr=el.__zr;var useHoverLayer=el.useHoverLayer&&zr&&zr.painter.type==='canvas';el.__highlighted=useHoverLayer?'layer':'plain';if(el.isGroup||!zr&&el.useHoverLayer){return;}var elTarget=el;var targetStyle=el.style;if(useHoverLayer){elTarget=zr.addHover(el);targetStyle=elTarget.style;}rollbackDefaultTextStyle(targetStyle);if(!useHoverLayer){cacheElementStl(elTarget);}// styles can be:\n// {\n//    label: {\n//        show: false,\n//        position: 'outside',\n//        fontSize: 18\n//    },\n//    emphasis: {\n//        label: {\n//            show: true\n//        }\n//    }\n// },\n// where properties of `emphasis` may not appear in `normal`. We previously use\n// module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`.\n// But consider rich text and setOption in merge mode, it is impossible to cover\n// all properties in merge. So we use merge mode when setting style here.\n// But we choose the merge strategy that only properties that is not `null/undefined`.\n// Because when making a textStyle (espacially rich text), it is not easy to distinguish\n// `hasOwnProperty` and `null/undefined` in code, so we trade them as the same for simplicity.\n// But this strategy brings a trouble that `null/undefined` can not be used to remove\n// style any more in `emphasis`. Users can both set properties directly on normal and\n// emphasis to avoid this issue, or we might support `'none'` for this case if required.\ntargetStyle.extendFrom(hoverStl);setDefaultHoverFillStroke(targetStyle,hoverStl,'fill');setDefaultHoverFillStroke(targetStyle,hoverStl,'stroke');applyDefaultTextStyle(targetStyle);if(!useHoverLayer){el.dirty(false);el.z2+=Z2_EMPHASIS_LIFT;}}function setDefaultHoverFillStroke(targetStyle,hoverStyle,prop){if(!hasFillOrStroke(hoverStyle[prop])&&hasFillOrStroke(targetStyle[prop])){targetStyle[prop]=liftColor(targetStyle[prop]);}}function singleEnterNormal(el){var highlighted=el.__highlighted;if(!highlighted){return;}el.__highlighted=false;if(el.isGroup){return;}if(highlighted==='layer'){el.__zr&&el.__zr.removeHover(el);}else{var style=el.style;var normalStl=el.__cachedNormalStl;if(normalStl){rollbackDefaultTextStyle(style);el.setStyle(normalStl);applyDefaultTextStyle(style);}// `__cachedNormalZ2` will not be reset if calling `setElementHoverStyle`\n// when `el` is on emphasis state. So here by comparing with 1, we try\n// hard to make the bug case rare.\nvar normalZ2=el.__cachedNormalZ2;if(normalZ2!=null&&el.z2-normalZ2===Z2_EMPHASIS_LIFT){el.z2=normalZ2;}}}function traverseUpdate(el,updater,commonParam){// If root is group, also enter updater for `highDownOnUpdate`.\nvar fromState=NORMAL;var toState=NORMAL;var trigger;// See the rule of `highDownOnUpdate` on `graphic.setAsHighDownDispatcher`.\nel.__highlighted&&(fromState=EMPHASIS,trigger=true);updater(el,commonParam);el.__highlighted&&(toState=EMPHASIS,trigger=true);el.isGroup&&el.traverse(function(child){!child.isGroup&&updater(child,commonParam);});trigger&&el.__highDownOnUpdate&&el.__highDownOnUpdate(fromState,toState);}/**\n * Set hover style (namely \"emphasis style\") of element, based on the current\n * style of the given `el`.\n * This method should be called after all of the normal styles have been adopted\n * to the `el`. See the reason on `setHoverStyle`.\n *\n * @param {module:zrender/Element} el Should not be `zrender/container/Group`.\n * @param {Object} [el.hoverStyle] Can be set on el or its descendants,\n *        e.g., `el.hoverStyle = ...; graphic.setHoverStyle(el); `.\n *        Often used when item group has a label element and it's hoverStyle is different.\n * @param {Object|boolean} [hoverStl] The specified hover style.\n *        If set as `false`, disable the hover style.\n *        Similarly, The `el.hoverStyle` can alse be set\n *        as `false` to disable the hover style.\n *        Otherwise, use the default hover style if not provided.\n */function setElementHoverStyle(el,hoverStl){// For performance consideration, it might be better to make the \"hover style\" only the\n// difference properties from the \"normal style\", but not a entire copy of all styles.\nhoverStl=el.__hoverStl=hoverStl!==false&&(el.hoverStyle||hoverStl||{});el.__hoverStlDirty=true;// FIXME\n// It is not completely right to save \"normal\"/\"emphasis\" flag on elements.\n// It probably should be saved on `data` of series. Consider the cases:\n// (1) A highlighted elements are moved out of the view port and re-enter\n// again by dataZoom.\n// (2) call `setOption` and replace elements totally when they are highlighted.\nif(el.__highlighted){// Consider the case:\n// The styles of a highlighted `el` is being updated. The new \"emphasis style\"\n// should be adapted to the `el`. Notice here new \"normal styles\" should have\n// been set outside and the cached \"normal style\" is out of date.\nel.__cachedNormalStl=null;// Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint\n// of this method. In most cases, `z2` is not set and hover style should be able\n// to rollback. Of course, that would bring bug, but only in a rare case, see\n// `doSingleLeaveHover` for details.\nsingleEnterNormal(el);singleEnterEmphasis(el);}}function onElementMouseOver(e){!shouldSilent(this,e)// \"emphasis\" event highlight has higher priority than mouse highlight.\n&&!this.__highByOuter&&traverseUpdate(this,singleEnterEmphasis);}function onElementMouseOut(e){!shouldSilent(this,e)// \"emphasis\" event highlight has higher priority than mouse highlight.\n&&!this.__highByOuter&&traverseUpdate(this,singleEnterNormal);}function onElementEmphasisEvent(highlightDigit){this.__highByOuter|=1<<(highlightDigit||0);traverseUpdate(this,singleEnterEmphasis);}function onElementNormalEvent(highlightDigit){!(this.__highByOuter&=~(1<<(highlightDigit||0)))&&traverseUpdate(this,singleEnterNormal);}function shouldSilent(el,e){return el.__highDownSilentOnTouch&&e.zrByTouch;}/**\n * Set hover style (namely \"emphasis style\") of element,\n * based on the current style of the given `el`.\n *\n * (1)\n * **CONSTRAINTS** for this method:\n * <A> This method MUST be called after all of the normal styles having been adopted\n * to the `el`.\n * <B> The input `hoverStyle` (that is, \"emphasis style\") MUST be the subset of the\n * \"normal style\" having been set to the el.\n * <C> `color` MUST be one of the \"normal styles\" (because color might be lifted as\n * a default hover style).\n *\n * The reason: this method treat the current style of the `el` as the \"normal style\"\n * and cache them when enter/update the \"emphasis style\". Consider the case: the `el`\n * is in \"emphasis\" state and `setOption`/`dispatchAction` trigger the style updating\n * logic, where the el should shift from the original emphasis style to the new\n * \"emphasis style\" and should be able to \"downplay\" back to the new \"normal style\".\n *\n * Indeed, it is error-prone to make a interface has so many constraints, but I have\n * not found a better solution yet to fit the backward compatibility, performance and\n * the current programming style.\n *\n * (2)\n * Call the method for a \"root\" element once. Do not call it for each descendants.\n * If the descendants elemenets of a group has itself hover style different from the\n * root group, we can simply mount the style on `el.hoverStyle` for them, but should\n * not call this method for them.\n *\n * (3) These input parameters can be set directly on `el`:\n *\n * @param {module:zrender/Element} el\n * @param {Object} [el.hoverStyle] See `graphic.setElementHoverStyle`.\n * @param {boolean} [el.highDownSilentOnTouch=false] See `graphic.setAsHighDownDispatcher`.\n * @param {Function} [el.highDownOnUpdate] See `graphic.setAsHighDownDispatcher`.\n * @param {Object|boolean} [hoverStyle] See `graphic.setElementHoverStyle`.\n */function setHoverStyle(el,hoverStyle){setAsHighDownDispatcher(el,true);traverseUpdate(el,setElementHoverStyle,hoverStyle);}/**\n * @param {module:zrender/Element} el\n * @param {Function} [el.highDownOnUpdate] Called when state updated.\n *        Since `setHoverStyle` has the constraint that it must be called after\n *        all of the normal style updated, `highDownOnUpdate` is not needed to\n *        trigger if both `fromState` and `toState` is 'normal', and needed to\n *        trigger if both `fromState` and `toState` is 'emphasis', which enables\n *        to sync outside style settings to \"emphasis\" state.\n *        @this {string} This dispatcher `el`.\n *        @param {string} fromState Can be \"normal\" or \"emphasis\".\n *               `fromState` might equal to `toState`,\n *               for example, when this method is called when `el` is\n *               on \"emphasis\" state.\n *        @param {string} toState Can be \"normal\" or \"emphasis\".\n *\n *        FIXME\n *        CAUTION: Do not expose `highDownOnUpdate` outside echarts.\n *        Because it is not a complete solution. The update\n *        listener should not have been mount in element,\n *        and the normal/emphasis state should not have\n *        mantained on elements.\n *\n * @param {boolean} [el.highDownSilentOnTouch=false]\n *        In touch device, mouseover event will be trigger on touchstart event\n *        (see module:zrender/dom/HandlerProxy). By this mechanism, we can\n *        conveniently use hoverStyle when tap on touch screen without additional\n *        code for compatibility.\n *        But if the chart/component has select feature, which usually also use\n *        hoverStyle, there might be conflict between 'select-highlight' and\n *        'hover-highlight' especially when roam is enabled (see geo for example).\n *        In this case, `highDownSilentOnTouch` should be used to disable\n *        hover-highlight on touch device.\n * @param {boolean} [asDispatcher=true] If `false`, do not set as \"highDownDispatcher\".\n */function setAsHighDownDispatcher(el,asDispatcher){var disable=asDispatcher===false;// Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after\n// `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.\nel.__highDownSilentOnTouch=el.highDownSilentOnTouch;el.__highDownOnUpdate=el.highDownOnUpdate;// Simple optimize, since this method might be\n// called for each elements of a group in some cases.\nif(!disable||el.__highDownDispatcher){var method=disable?'off':'on';// Duplicated function will be auto-ignored, see Eventful.js.\nel[method]('mouseover',onElementMouseOver)[method]('mouseout',onElementMouseOut);// Emphasis, normal can be triggered manually by API or other components like hover link.\nel[method]('emphasis',onElementEmphasisEvent)[method]('normal',onElementNormalEvent);// Also keep previous record.\nel.__highByOuter=el.__highByOuter||0;el.__highDownDispatcher=!disable;}}/**\n * @param {module:zrender/src/Element} el\n * @return {boolean}\n */function isHighDownDispatcher(el){return!!(el&&el.__highDownDispatcher);}/**\n * Support hightlight/downplay record on each elements.\n * For the case: hover highlight/downplay (legend, visualMap, ...) and\n * user triggerred hightlight/downplay should not conflict.\n * Only all of the highlightDigit cleared, return to normal.\n * @param {string} highlightKey\n * @return {number} highlightDigit\n */function getHighlightDigit(highlightKey){var highlightDigit=_highlightKeyMap[highlightKey];if(highlightDigit==null&&_highlightNextDigit<=32){highlightDigit=_highlightKeyMap[highlightKey]=_highlightNextDigit++;}return highlightDigit;}/**\n * See more info in `setTextStyleCommon`.\n * @param {Object|module:zrender/graphic/Style} normalStyle\n * @param {Object} emphasisStyle\n * @param {module:echarts/model/Model} normalModel\n * @param {module:echarts/model/Model} emphasisModel\n * @param {Object} opt Check `opt` of `setTextStyleCommon` to find other props.\n * @param {string|Function} [opt.defaultText]\n * @param {module:echarts/model/Model} [opt.labelFetcher] Fetch text by\n *      `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)`\n * @param {number} [opt.labelDataIndex] Fetch text by\n *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)`\n * @param {number} [opt.labelDimIndex] Fetch text by\n *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)`\n * @param {string} [opt.labelProp] Fetch text by\n *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)`\n * @param {Object} [normalSpecified]\n * @param {Object} [emphasisSpecified]\n */function setLabelStyle(normalStyle,emphasisStyle,normalModel,emphasisModel,opt,normalSpecified,emphasisSpecified){opt=opt||EMPTY_OBJ;var labelFetcher=opt.labelFetcher;var labelDataIndex=opt.labelDataIndex;var labelDimIndex=opt.labelDimIndex;var labelProp=opt.labelProp;// This scenario, `label.normal.show = true; label.emphasis.show = false`,\n// is not supported util someone requests.\nvar showNormal=normalModel.getShallow('show');var showEmphasis=emphasisModel.getShallow('show');// Consider performance, only fetch label when necessary.\n// If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set,\n// label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.\nvar baseText;if(showNormal||showEmphasis){if(labelFetcher){baseText=labelFetcher.getFormattedLabel(labelDataIndex,'normal',null,labelDimIndex,labelProp);}if(baseText==null){baseText=isFunction$1(opt.defaultText)?opt.defaultText(labelDataIndex,opt):opt.defaultText;}}var normalStyleText=showNormal?baseText:null;var emphasisStyleText=showEmphasis?retrieve2(labelFetcher?labelFetcher.getFormattedLabel(labelDataIndex,'emphasis',null,labelDimIndex,labelProp):null,baseText):null;// Optimize: If style.text is null, text will not be drawn.\nif(normalStyleText!=null||emphasisStyleText!=null){// Always set `textStyle` even if `normalStyle.text` is null, because default\n// values have to be set on `normalStyle`.\n// If we set default values on `emphasisStyle`, consider case:\n// Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);`\n// Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);`\n// Then the 'red' will not work on emphasis.\nsetTextStyle(normalStyle,normalModel,normalSpecified,opt);setTextStyle(emphasisStyle,emphasisModel,emphasisSpecified,opt,true);}normalStyle.text=normalStyleText;emphasisStyle.text=emphasisStyleText;}/**\n * Modify label style manually.\n * Only works after `setLabelStyle` and `setElementHoverStyle` called.\n *\n * @param {module:zrender/src/Element} el\n * @param {Object} [normalStyleProps] optional\n * @param {Object} [emphasisStyleProps] optional\n */function modifyLabelStyle(el,normalStyleProps,emphasisStyleProps){var elStyle=el.style;if(normalStyleProps){rollbackDefaultTextStyle(elStyle);el.setStyle(normalStyleProps);applyDefaultTextStyle(elStyle);}elStyle=el.__hoverStl;if(emphasisStyleProps&&elStyle){rollbackDefaultTextStyle(elStyle);extend(elStyle,emphasisStyleProps);applyDefaultTextStyle(elStyle);}}/**\n * Set basic textStyle properties.\n * See more info in `setTextStyleCommon`.\n * @param {Object|module:zrender/graphic/Style} textStyle\n * @param {module:echarts/model/Model} model\n * @param {Object} [specifiedTextStyle] Can be overrided by settings in model.\n * @param {Object} [opt] See `opt` of `setTextStyleCommon`.\n * @param {boolean} [isEmphasis]\n */function setTextStyle(textStyle,textStyleModel,specifiedTextStyle,opt,isEmphasis){setTextStyleCommon(textStyle,textStyleModel,opt,isEmphasis);specifiedTextStyle&&extend(textStyle,specifiedTextStyle);// textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);\nreturn textStyle;}/**\n * Set text option in the style.\n * See more info in `setTextStyleCommon`.\n * @deprecated\n * @param {Object} textStyle\n * @param {module:echarts/model/Model} labelModel\n * @param {string|boolean} defaultColor Default text color.\n *        If set as false, it will be processed as a emphasis style.\n */function setText(textStyle,labelModel,defaultColor){var opt={isRectText:true};var isEmphasis;if(defaultColor===false){isEmphasis=true;}else{// Support setting color as 'auto' to get visual color.\nopt.autoColor=defaultColor;}setTextStyleCommon(textStyle,labelModel,opt,isEmphasis);// textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);\n}/**\n * The uniform entry of set text style, that is, retrieve style definitions\n * from `model` and set to `textStyle` object.\n *\n * Never in merge mode, but in overwrite mode, that is, all of the text style\n * properties will be set. (Consider the states of normal and emphasis and\n * default value can be adopted, merge would make the logic too complicated\n * to manage.)\n *\n * The `textStyle` object can either be a plain object or an instance of\n * `zrender/src/graphic/Style`, and either be the style of normal or emphasis.\n * After this mothod called, the `textStyle` object can then be used in\n * `el.setStyle(textStyle)` or `el.hoverStyle = textStyle`.\n *\n * Default value will be adopted and `insideRollbackOpt` will be created.\n * See `applyDefaultTextStyle` `rollbackDefaultTextStyle` for more details.\n *\n * opt: {\n *      disableBox: boolean, Whether diable drawing box of block (outer most).\n *      isRectText: boolean,\n *      autoColor: string, specify a color when color is 'auto',\n *              for textFill, textStroke, textBackgroundColor, and textBorderColor.\n *              If autoColor specified, it is used as default textFill.\n *      useInsideStyle:\n *              `true`: Use inside style (textFill, textStroke, textStrokeWidth)\n *                  if `textFill` is not specified.\n *              `false`: Do not use inside style.\n *              `null/undefined`: use inside style if `isRectText` is true and\n *                  `textFill` is not specified and textPosition contains `'inside'`.\n *      forceRich: boolean\n * }\n */function setTextStyleCommon(textStyle,textStyleModel,opt,isEmphasis){// Consider there will be abnormal when merge hover style to normal style if given default value.\nopt=opt||EMPTY_OBJ;if(opt.isRectText){var textPosition;if(opt.getTextPosition){textPosition=opt.getTextPosition(textStyleModel,isEmphasis);}else{textPosition=textStyleModel.getShallow('position')||(isEmphasis?null:'inside');// 'outside' is not a valid zr textPostion value, but used\n// in bar series, and magric type should be considered.\ntextPosition==='outside'&&(textPosition='top');}textStyle.textPosition=textPosition;textStyle.textOffset=textStyleModel.getShallow('offset');var labelRotate=textStyleModel.getShallow('rotate');labelRotate!=null&&(labelRotate*=Math.PI/180);textStyle.textRotation=labelRotate;textStyle.textDistance=retrieve2(textStyleModel.getShallow('distance'),isEmphasis?null:5);}var ecModel=textStyleModel.ecModel;var globalTextStyle=ecModel&&ecModel.option.textStyle;// Consider case:\n// {\n//     data: [{\n//         value: 12,\n//         label: {\n//             rich: {\n//                 // no 'a' here but using parent 'a'.\n//             }\n//         }\n//     }],\n//     rich: {\n//         a: { ... }\n//     }\n// }\nvar richItemNames=getRichItemNames(textStyleModel);var richResult;if(richItemNames){richResult={};for(var name in richItemNames){if(richItemNames.hasOwnProperty(name)){// Cascade is supported in rich.\nvar richTextStyle=textStyleModel.getModel(['rich',name]);// In rich, never `disableBox`.\n// FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`,\n// the default color `'blue'` will not be adopted if no color declared in `rich`.\n// That might confuses users. So probably we should put `textStyleModel` as the\n// root ancestor of the `richTextStyle`. But that would be a break change.\nsetTokenTextStyle(richResult[name]={},richTextStyle,globalTextStyle,opt,isEmphasis);}}}textStyle.rich=richResult;setTokenTextStyle(textStyle,textStyleModel,globalTextStyle,opt,isEmphasis,true);if(opt.forceRich&&!opt.textStyle){opt.textStyle={};}return textStyle;}// Consider case:\n// {\n//     data: [{\n//         value: 12,\n//         label: {\n//             rich: {\n//                 // no 'a' here but using parent 'a'.\n//             }\n//         }\n//     }],\n//     rich: {\n//         a: { ... }\n//     }\n// }\nfunction getRichItemNames(textStyleModel){// Use object to remove duplicated names.\nvar richItemNameMap;while(textStyleModel&&textStyleModel!==textStyleModel.ecModel){var rich=(textStyleModel.option||EMPTY_OBJ).rich;if(rich){richItemNameMap=richItemNameMap||{};for(var name in rich){if(rich.hasOwnProperty(name)){richItemNameMap[name]=1;}}}textStyleModel=textStyleModel.parentModel;}return richItemNameMap;}function setTokenTextStyle(textStyle,textStyleModel,globalTextStyle,opt,isEmphasis,isBlock){// In merge mode, default value should not be given.\nglobalTextStyle=!isEmphasis&&globalTextStyle||EMPTY_OBJ;textStyle.textFill=getAutoColor(textStyleModel.getShallow('color'),opt)||globalTextStyle.color;textStyle.textStroke=getAutoColor(textStyleModel.getShallow('textBorderColor'),opt)||globalTextStyle.textBorderColor;textStyle.textStrokeWidth=retrieve2(textStyleModel.getShallow('textBorderWidth'),globalTextStyle.textBorderWidth);if(!isEmphasis){if(isBlock){textStyle.insideRollbackOpt=opt;applyDefaultTextStyle(textStyle);}// Set default finally.\nif(textStyle.textFill==null){textStyle.textFill=opt.autoColor;}}// Do not use `getFont` here, because merge should be supported, where\n// part of these properties may be changed in emphasis style, and the\n// others should remain their original value got from normal style.\ntextStyle.fontStyle=textStyleModel.getShallow('fontStyle')||globalTextStyle.fontStyle;textStyle.fontWeight=textStyleModel.getShallow('fontWeight')||globalTextStyle.fontWeight;textStyle.fontSize=textStyleModel.getShallow('fontSize')||globalTextStyle.fontSize;textStyle.fontFamily=textStyleModel.getShallow('fontFamily')||globalTextStyle.fontFamily;textStyle.textAlign=textStyleModel.getShallow('align');textStyle.textVerticalAlign=textStyleModel.getShallow('verticalAlign')||textStyleModel.getShallow('baseline');textStyle.textLineHeight=textStyleModel.getShallow('lineHeight');textStyle.textWidth=textStyleModel.getShallow('width');textStyle.textHeight=textStyleModel.getShallow('height');textStyle.textTag=textStyleModel.getShallow('tag');if(!isBlock||!opt.disableBox){textStyle.textBackgroundColor=getAutoColor(textStyleModel.getShallow('backgroundColor'),opt);textStyle.textPadding=textStyleModel.getShallow('padding');textStyle.textBorderColor=getAutoColor(textStyleModel.getShallow('borderColor'),opt);textStyle.textBorderWidth=textStyleModel.getShallow('borderWidth');textStyle.textBorderRadius=textStyleModel.getShallow('borderRadius');textStyle.textBoxShadowColor=textStyleModel.getShallow('shadowColor');textStyle.textBoxShadowBlur=textStyleModel.getShallow('shadowBlur');textStyle.textBoxShadowOffsetX=textStyleModel.getShallow('shadowOffsetX');textStyle.textBoxShadowOffsetY=textStyleModel.getShallow('shadowOffsetY');}textStyle.textShadowColor=textStyleModel.getShallow('textShadowColor')||globalTextStyle.textShadowColor;textStyle.textShadowBlur=textStyleModel.getShallow('textShadowBlur')||globalTextStyle.textShadowBlur;textStyle.textShadowOffsetX=textStyleModel.getShallow('textShadowOffsetX')||globalTextStyle.textShadowOffsetX;textStyle.textShadowOffsetY=textStyleModel.getShallow('textShadowOffsetY')||globalTextStyle.textShadowOffsetY;}function getAutoColor(color,opt){return color!=='auto'?color:opt&&opt.autoColor?opt.autoColor:null;}/**\n * Give some default value to the input `textStyle` object, based on the current settings\n * in this `textStyle` object.\n *\n * The Scenario:\n * when text position is `inside` and `textFill` is not specified, we show\n * text border by default for better view. But it should be considered that text position\n * might be changed when hovering or being emphasis, where the `insideRollback` is used to\n * restore the style.\n *\n * Usage (& NOTICE):\n * When a style object (eithor plain object or instance of `zrender/src/graphic/Style`) is\n * about to be modified on its text related properties, `rollbackDefaultTextStyle` should\n * be called before the modification and `applyDefaultTextStyle` should be called after that.\n * (For the case that all of the text related properties is reset, like `setTextStyleCommon`\n * does, `rollbackDefaultTextStyle` is not needed to be called).\n */function applyDefaultTextStyle(textStyle){var textPosition=textStyle.textPosition;var opt=textStyle.insideRollbackOpt;var insideRollback;if(opt&&textStyle.textFill==null){var autoColor=opt.autoColor;var isRectText=opt.isRectText;var useInsideStyle=opt.useInsideStyle;var useInsideStyleCache=useInsideStyle!==false&&(useInsideStyle===true||isRectText&&textPosition// textPosition can be [10, 30]\n&&typeof textPosition==='string'&&textPosition.indexOf('inside')>=0);var useAutoColorCache=!useInsideStyleCache&&autoColor!=null;// All of the props declared in `CACHED_LABEL_STYLE_PROPERTIES` are to be cached.\nif(useInsideStyleCache||useAutoColorCache){insideRollback={textFill:textStyle.textFill,textStroke:textStyle.textStroke,textStrokeWidth:textStyle.textStrokeWidth};}if(useInsideStyleCache){textStyle.textFill='#fff';// Consider text with #fff overflow its container.\nif(textStyle.textStroke==null){textStyle.textStroke=autoColor;textStyle.textStrokeWidth==null&&(textStyle.textStrokeWidth=2);}}if(useAutoColorCache){textStyle.textFill=autoColor;}}// Always set `insideRollback`, so that the previous one can be cleared.\ntextStyle.insideRollback=insideRollback;}/**\n * Consider the case: in a scatter,\n * label: {\n *     normal: {position: 'inside'},\n *     emphasis: {position: 'top'}\n * }\n * In the normal state, the `textFill` will be set as '#fff' for pretty view (see\n * `applyDefaultTextStyle`), but when switching to emphasis state, the `textFill`\n * should be retured to 'autoColor', but not keep '#fff'.\n */function rollbackDefaultTextStyle(style){var insideRollback=style.insideRollback;if(insideRollback){// Reset all of the props in `CACHED_LABEL_STYLE_PROPERTIES`.\nstyle.textFill=insideRollback.textFill;style.textStroke=insideRollback.textStroke;style.textStrokeWidth=insideRollback.textStrokeWidth;style.insideRollback=null;}}function _getFont(opt,ecModel){var gTextStyleModel=ecModel&&ecModel.getModel('textStyle');return trim([// FIXME in node-canvas fontWeight is before fontStyle\nopt.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(' '));}function animateOrSetProps(isUpdate,el,props,animatableModel,dataIndex,cb){if(typeof dataIndex==='function'){cb=dataIndex;dataIndex=null;}// Do not check 'animation' property directly here. Consider this case:\n// animation model is an `itemModel`, whose does not have `isAnimationEnabled`\n// but its parent model (`seriesModel`) does.\nvar animationEnabled=animatableModel&&animatableModel.isAnimationEnabled();if(animationEnabled){var postfix=isUpdate?'Update':'';var duration=animatableModel.getShallow('animationDuration'+postfix);var animationEasing=animatableModel.getShallow('animationEasing'+postfix);var animationDelay=animatableModel.getShallow('animationDelay'+postfix);if(typeof animationDelay==='function'){animationDelay=animationDelay(dataIndex,animatableModel.getAnimationDelayParams?animatableModel.getAnimationDelayParams(el,dataIndex):null);}if(typeof duration==='function'){duration=duration(dataIndex);}duration>0?el.animateTo(props,duration,animationDelay||0,animationEasing,cb,!!cb):(el.stopAnimation(),el.attr(props),cb&&cb());}else{el.stopAnimation();el.attr(props);cb&&cb();}}/**\n * Update graphic element properties with or without animation according to the\n * configuration in series.\n *\n * Caution: this method will stop previous animation.\n * So do not use this method to one element twice before\n * animation starts, unless you know what you are doing.\n *\n * @param {module:zrender/Element} el\n * @param {Object} props\n * @param {module:echarts/model/Model} [animatableModel]\n * @param {number} [dataIndex]\n * @param {Function} [cb]\n * @example\n *     graphic.updateProps(el, {\n *         position: [100, 100]\n *     }, seriesModel, dataIndex, function () { console.log('Animation done!'); });\n *     // Or\n *     graphic.updateProps(el, {\n *         position: [100, 100]\n *     }, seriesModel, function () { console.log('Animation done!'); });\n */function updateProps(el,props,animatableModel,dataIndex,cb){animateOrSetProps(true,el,props,animatableModel,dataIndex,cb);}/**\n * Init graphic element properties with or without animation according to the\n * configuration in series.\n *\n * Caution: this method will stop previous animation.\n * So do not use this method to one element twice before\n * animation starts, unless you know what you are doing.\n *\n * @param {module:zrender/Element} el\n * @param {Object} props\n * @param {module:echarts/model/Model} [animatableModel]\n * @param {number} [dataIndex]\n * @param {Function} cb\n */function initProps(el,props,animatableModel,dataIndex,cb){animateOrSetProps(false,el,props,animatableModel,dataIndex,cb);}/**\n * Get transform matrix of target (param target),\n * in coordinate of its ancestor (param ancestor)\n *\n * @param {module:zrender/mixin/Transformable} target\n * @param {module:zrender/mixin/Transformable} [ancestor]\n */function getTransform(target,ancestor){var mat=identity([]);while(target&&target!==ancestor){mul$1(mat,target.getLocalTransform(),mat);target=target.parent;}return mat;}/**\n * Apply transform to an vertex.\n * @param {Array.<number>} target [x, y]\n * @param {Array.<number>|TypedArray.<number>|Object} transform Can be:\n *      + Transform matrix: like [1, 0, 0, 1, 0, 0]\n *      + {position, rotation, scale}, the same as `zrender/Transformable`.\n * @param {boolean=} invert Whether use invert matrix.\n * @return {Array.<number>} [x, y]\n */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);}/**\n * @param {string} direction 'left' 'right' 'top' 'bottom'\n * @param {Array.<number>} transform Transform matrix: like [1, 0, 0, 1, 0, 0]\n * @param {boolean=} invert Whether use invert matrix.\n * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom'\n */function transformDirection(direction,transform,invert$$1){// Pick a base, ensure that transform result will not be (0, 0).\nvar 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$$1);return Math.abs(vertex[0])>Math.abs(vertex[1])?vertex[0]>0?'right':'left':vertex[1]>0?'bottom':'top';}/**\n * Apply group transition animation from g1 to g2.\n * If no animatableModel, no animation.\n */function groupTransition(g1,g2,animatableModel,cb){if(!g1||!g2){return;}function getElMap(g){var elMap={};g.traverse(function(el){if(!el.isGroup&&el.anid){elMap[el.anid]=el;}});return elMap;}function getAnimatableProps(el){var obj={position:clone$1(el.position),rotation:el.rotation};if(el.shape){obj.shape=extend({},el.shape);}return obj;}var elMap1=getElMap(g1);g2.traverse(function(el){if(!el.isGroup&&el.anid){var oldEl=elMap1[el.anid];if(oldEl){var newProp=getAnimatableProps(el);el.attr(getAnimatableProps(oldEl));updateProps(el,newProp,animatableModel,el.dataIndex);}// else {\n//     if (el.previousProps) {\n//         graphic.updateProps\n//     }\n// }\n}});}/**\n * @param {Array.<Array.<number>>} points Like: [[23, 44], [53, 66], ...]\n * @param {Object} rect {x, y, width, height}\n * @return {Array.<Array.<number>>} A new clipped points.\n */function clipPointsByRect(points,rect){// FIXME: this way migth be incorrect when grpahic clipped by a corner.\n// and when element have border.\nreturn map(points,function(point){var x=point[0];x=mathMax$1(x,rect.x);x=mathMin$1(x,rect.x+rect.width);var y=point[1];y=mathMax$1(y,rect.y);y=mathMin$1(y,rect.y+rect.height);return[x,y];});}/**\n * @param {Object} targetRect {x, y, width, height}\n * @param {Object} rect {x, y, width, height}\n * @return {Object} A new clipped rect. If rect size are negative, return undefined.\n */function clipRectByRect(targetRect,rect){var x=mathMax$1(targetRect.x,rect.x);var x2=mathMin$1(targetRect.x+targetRect.width,rect.x+rect.width);var y=mathMax$1(targetRect.y,rect.y);var y2=mathMin$1(targetRect.y+targetRect.height,rect.y+rect.height);// If the total rect is cliped, nothing, including the border,\n// should be painted. So return undefined.\nif(x2>=x&&y2>=y){return{x:x,y:y,width:x2-x,height:y2-y};}}/**\n * @param {string} iconStr Support 'image://' or 'path://' or direct svg path.\n * @param {Object} [opt] Properties of `module:zrender/Element`, except `style`.\n * @param {Object} [rect] {x, y, width, height}\n * @return {module:zrender/Element} Icon path or image element.\n */function createIcon(iconStr,opt,rect){opt=extend({rectHover:true},opt);var style=opt.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 ZImage(opt)):makePath(iconStr.replace('path://',''),opt,rect,'center');}}/**\n * Return `true` if the given line (line `a`) and the given polygon\n * are intersect.\n * Note that we do not count colinear as intersect here because no\n * requirement for that. We could do that if required in future.\n *\n * @param {number} a1x\n * @param {number} a1y\n * @param {number} a2x\n * @param {number} a2y\n * @param {Array.<Array.<number>>} points Points of the polygon.\n * @return {boolean}\n */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;}}/**\n * Return `true` if the given two lines (line `a` and line `b`)\n * are intersect.\n * Note that we do not count colinear as intersect here because no\n * requirement for that. We could do that if required in future.\n *\n * @param {number} a1x\n * @param {number} a1y\n * @param {number} a2x\n * @param {number} a2y\n * @param {number} b1x\n * @param {number} b1y\n * @param {number} b2x\n * @param {number} b2y\n * @return {boolean}\n */function lineLineIntersect(a1x,a1y,a2x,a2y,b1x,b1y,b2x,b2y){// let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`.\nvar mx=a2x-a1x;var my=a2y-a1y;var nx=b2x-b1x;var ny=b2y-b1y;// `vec_m` and `vec_n` are parallel iff\n//     exising `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`.\nvar nmCrossProduct=crossProduct2d(nx,ny,mx,my);if(nearZero(nmCrossProduct)){return false;}// `vec_m` and `vec_n` are intersect iff\n//     existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`,\n//     such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)`\n//           and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`.\nvar 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;}/**\n * Cross product of 2-dimension vector.\n */function crossProduct2d(x1,y1,x2,y2){return x1*y2-x2*y1;}function nearZero(val){return val<=1e-6&&val>=-1e-6;}// Register built-in shapes. These shapes might be overwirtten\n// by users, although we do not recommend that.\nregisterShape('circle',Circle);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=(Object.freeze||Object)({Z2_EMPHASIS_LIFT:Z2_EMPHASIS_LIFT,CACHED_LABEL_STYLE_PROPERTIES:CACHED_LABEL_STYLE_PROPERTIES,extendShape:extendShape,extendPath:extendPath,registerShape:registerShape,getShapeClass:getShapeClass,makePath:makePath,makeImage:makeImage,mergePath:mergePath,resizePath:resizePath,subPixelOptimizeLine:subPixelOptimizeLine,subPixelOptimizeRect:subPixelOptimizeRect,subPixelOptimize:subPixelOptimize,setElementHoverStyle:setElementHoverStyle,setHoverStyle:setHoverStyle,setAsHighDownDispatcher:setAsHighDownDispatcher,isHighDownDispatcher:isHighDownDispatcher,getHighlightDigit:getHighlightDigit,setLabelStyle:setLabelStyle,modifyLabelStyle:modifyLabelStyle,setTextStyle:setTextStyle,setText:setText,getFont:_getFont,updateProps:updateProps,initProps:initProps,getTransform:getTransform,applyTransform:applyTransform$1,transformDirection:transformDirection,groupTransition:groupTransition,clipPointsByRect:clipPointsByRect,clipRectByRect:clipRectByRect,createIcon:createIcon,linePolygonIntersect:linePolygonIntersect,lineLineIntersect:lineLineIntersect,Group:Group,Image:ZImage,Text:Text,Circle:Circle,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});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var PATH_COLOR=['textStyle','color'];var textStyleMixin={/**\n     * Get color property or get color from option.textStyle.color\n     * @param {boolean} [isEmphasis]\n     * @return {string}\n     */getTextColor:function getTextColor(isEmphasis){var ecModel=this.ecModel;return this.getShallow('color')||(!isEmphasis&&ecModel?ecModel.get(PATH_COLOR):null);},/**\n     * Create font string from fontStyle, fontWeight, fontSize, fontFamily\n     * @return {string}\n     */getFont:function getFont(){return _getFont({fontStyle:this.getShallow('fontStyle'),fontWeight:this.getShallow('fontWeight'),fontSize:this.getShallow('fontSize'),fontFamily:this.getShallow('fontFamily')},this.ecModel);},getTextRect:function getTextRect(text){return _getBoundingRect(text,this.getFont(),this.getShallow('align'),this.getShallow('verticalAlign')||this.getShallow('baseline'),this.getShallow('padding'),this.getShallow('lineHeight'),this.getShallow('rich'),this.getShallow('truncateText'));}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var _getItemStyle=makeStyleMapper([['fill','color'],['stroke','borderColor'],['lineWidth','borderWidth'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor'],['textPosition'],['textAlign']]);var itemStyleMixin={getItemStyle:function getItemStyle(excludes,includes){var style=_getItemStyle(this,excludes,includes);var lineDash=this.getBorderLineDash();lineDash&&(style.lineDash=lineDash);return style;},getBorderLineDash:function getBorderLineDash(){var lineType=this.get('borderType');return lineType==='solid'||lineType==null?null:lineType==='dashed'?[5,5]:[1,1];}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/model/Model\n */var mixin$1=mixin;var inner=makeInner();/**\n * @alias module:echarts/model/Model\n * @constructor\n * @param {Object} [option]\n * @param {module:echarts/model/Model} [parentModel]\n * @param {module:echarts/model/Global} [ecModel]\n */function Model(option,parentModel,ecModel){/**\n     * @type {module:echarts/model/Model}\n     * @readOnly\n     */this.parentModel=parentModel;/**\n     * @type {module:echarts/model/Global}\n     * @readOnly\n     */this.ecModel=ecModel;/**\n     * @type {Object}\n     * @protected\n     */this.option=option;// Simple optimization\n// if (this.init) {\n//     if (arguments.length <= 4) {\n//         this.init(option, parentModel, ecModel, extraOpt);\n//     }\n//     else {\n//         this.init.apply(this, arguments);\n//     }\n// }\n}Model.prototype={constructor:Model,/**\n     * Model 的初始化函数\n     * @param {Object} option\n     */init:null,/**\n     * 从新的 Option merge\n     */mergeOption:function mergeOption(option){merge(this.option,option,true);},/**\n     * @param {string|Array.<string>} path\n     * @param {boolean} [ignoreParent=false]\n     * @return {*}\n     */get:function get(path,ignoreParent){if(path==null){return this.option;}return doGet(this.option,this.parsePath(path),!ignoreParent&&getParent(this,path));},/**\n     * @param {string} key\n     * @param {boolean} [ignoreParent=false]\n     * @return {*}\n     */getShallow:function getShallow(key,ignoreParent){var option=this.option;var val=option==null?option:option[key];var parentModel=!ignoreParent&&getParent(this,key);if(val==null&&parentModel){val=parentModel.getShallow(key);}return val;},/**\n     * @param {string|Array.<string>} [path]\n     * @param {module:echarts/model/Model} [parentModel]\n     * @return {module:echarts/model/Model}\n     */getModel:function getModel(path,parentModel){var obj=path==null?this.option:doGet(this.option,path=this.parsePath(path));var thisParentModel;parentModel=parentModel||(thisParentModel=getParent(this,path))&&thisParentModel.getModel(path);return new Model(obj,parentModel,this.ecModel);},/**\n     * If model has option\n     */isEmpty:function isEmpty(){return this.option==null;},restoreData:function restoreData(){},// Pending\nclone:function clone(){var Ctor=this.constructor;return new Ctor(_clone(this.option));},setReadOnly:function setReadOnly(properties){// clazzUtil.setReadOnly(this, properties);\n},// If path is null/undefined, return null/undefined.\nparsePath:function parsePath(path){if(typeof path==='string'){path=path.split('.');}return path;},/**\n     * @param {Function} getParentMethod\n     *        param {Array.<string>|string} path\n     *        return {module:echarts/model/Model}\n     */customizeGetParent:function customizeGetParent(getParentMethod){inner(this).getParent=getParentMethod;},isAnimationEnabled:function isAnimationEnabled(){if(!env$1.node){if(this.option.animation!=null){return!!this.option.animation;}else if(this.parentModel){return this.parentModel.isAnimationEnabled();}}}};function doGet(obj,pathArr,parentModel){for(var i=0;i<pathArr.length;i++){// Ignore empty\nif(!pathArr[i]){continue;}// obj could be number/string/... (like 0)\nobj=obj&&_typeof(obj)==='object'?obj[pathArr[i]]:null;if(obj==null){break;}}if(obj==null&&parentModel){obj=parentModel.get(pathArr);}return obj;}// `path` can be null/undefined\nfunction getParent(model,path){var getParentMethod=inner(model).getParent;return getParentMethod?getParentMethod.call(model,path):model.parentModel;}// Enable Model.extend.\nenableClassExtend(Model);enableClassCheck(Model);mixin$1(Model,lineStyleMixin);mixin$1(Model,areaStyleMixin);mixin$1(Model,textStyleMixin);mixin$1(Model,itemStyleMixin);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var base=0;/**\n * @public\n * @param {string} type\n * @return {string}\n */function getUID(type){// Considering the case of crossing js context,\n// use Math.random to make id as unique as possible.\nreturn[type||'',base++,Math.random().toFixed(5)].join('_');}/**\n * @inner\n */function enableSubTypeDefaulter(entity){var subTypeDefaulters={};entity.registerSubTypeDefaulter=function(componentType,defaulter){componentType=parseClassType$1(componentType);subTypeDefaulters[componentType.main]=defaulter;};entity.determineSubType=function(componentType,option){var type=option.type;if(!type){var componentTypeMain=parseClassType$1(componentType).main;if(entity.hasSubTypes(componentType)&&subTypeDefaulters[componentTypeMain]){type=subTypeDefaulters[componentTypeMain](option);}}return type;};return entity;}/**\n * Topological travel on Activity Network (Activity On Vertices).\n * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].\n *\n * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.\n *\n * If there is circle dependencey, Error will be thrown.\n *\n */function enableTopologicalTravel(entity,dependencyGetter){/**\n     * @public\n     * @param {Array.<string>} targetNameList Target Component type list.\n     *                                           Can be ['aa', 'bb', 'aa.xx']\n     * @param {Array.<string>} fullNameList By which we can build dependency graph.\n     * @param {Function} callback Params: componentType, dependencies.\n     * @param {Object} context Scope of callback.\n     */entity.topologicalTravel=function(targetNameList,fullNameList,callback,context){if(!targetNameList.length){return;}var result=makeDepndencyGraph(fullNameList);var graph=result.graph;var stack=result.noEntryList;var targetNameSet={};each$1(targetNameList,function(name){targetNameSet[name]=true;});while(stack.length){var currComponentType=stack.pop();var currVertex=graph[currComponentType];var isInTargetNameSet=!!targetNameSet[currComponentType];if(isInTargetNameSet){callback.call(context,currComponentType,currVertex.originalDeps.slice());delete targetNameSet[currComponentType];}each$1(currVertex.successor,isInTargetNameSet?removeEdgeAndAdd:removeEdge);}each$1(targetNameSet,function(){throw new Error('Circle dependency may exists');});function removeEdge(succComponentType){graph[succComponentType].entryCount--;if(graph[succComponentType].entryCount===0){stack.push(succComponentType);}}// Consider this case: legend depends on series, and we call\n// chart.setOption({series: [...]}), where only series is in option.\n// If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will\n// not be called, but only sereis.mergeOption is called. Thus legend\n// have no chance to update its local record about series (like which\n// name of series is available in legend).\nfunction removeEdgeAndAdd(succComponentType){targetNameSet[succComponentType]=true;removeEdge(succComponentType);}};/**\n     * DepndencyGraph: {Object}\n     * key: conponentType,\n     * value: {\n     *     successor: [conponentTypes...],\n     *     originalDeps: [conponentTypes...],\n     *     entryCount: {number}\n     * }\n     */function makeDepndencyGraph(fullNameList){var graph={};var noEntryList=[];each$1(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$1(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$1(originalDeps,function(dep){indexOf(fullNameList,dep)>=0&&availableDeps.push(dep);});return availableDeps;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* A third-party license is embeded for some of the code in this file:\n* The method \"quantile\" was copied from \"d3.js\".\n* (See more details in the comment of the method below.)\n* The use of the source code of this file is also subject to the terms\n* and consitions of the license of \"d3.js\" (BSD-3Clause, see\n* </licenses/LICENSE-d3>).\n*/var RADIAN_EPSILON=1e-4;function _trim(str){return str.replace(/^\\s+|\\s+$/g,'');}/**\n * Linear mapping a value from domain to range\n * @memberOf module:echarts/util/number\n * @param  {(number|Array.<number>)} val\n * @param  {Array.<number>} domain Domain extent domain[0] can be bigger than domain[1]\n * @param  {Array.<number>} range  Range extent range[0] can be bigger than range[1]\n * @param  {boolean} clamp\n * @return {(number|Array.<number>}\n */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;}// Avoid accuracy problem in edge, such as\n// 146.39 - 62.83 === 83.55999999999999.\n// See echarts/test/ut/spec/util/number.js#linearMap#accuracyError\n// It is a little verbose for efficiency considering this method\n// is a hotspot.\nif(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];}/**\n * Convert a percent string to absolute number.\n * Returns NaN if percent is not a valid string or number\n * @memberOf module:echarts/util/number\n * @param {string|number} percent\n * @param {number} all\n * @return {number}\n */function parsePercent$1(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;}/**\n * (1) Fix rounding error of float numbers.\n * (2) Support return string to avoid scientific notation like '3.5e-7'.\n *\n * @param {number} x\n * @param {number} [precision]\n * @param {boolean} [returnStr]\n * @return {number|string}\n */function round$1(x,precision,returnStr){if(precision==null){precision=10;}// Avoid range error\nprecision=Math.min(Math.max(0,precision),20);x=(+x).toFixed(precision);return returnStr?x:+x;}/**\n * asc sort arr.\n * The input arr will be modified.\n *\n * @param {Array} arr\n * @return {Array} The input arr.\n */function asc(arr){arr.sort(function(a,b){return a-b;});return arr;}/**\n * Get precision\n * @param {number} val\n */function getPrecision(val){val=+val;if(isNaN(val)){return 0;}// It is much faster than methods converting number to string as follows\n//      var tmp = val.toString();\n//      return tmp.length - 1 - tmp.indexOf('.');\n// especially when precision is low\nvar e=1;var count=0;while(Math.round(val*e)/e!==val){e*=10;count++;}return count;}/**\n * @param {string|number} val\n * @return {number}\n */function getPrecisionSafe(val){var str=val.toString();// Consider scientific notation: '3.4e-12' '3.4e+12'\nvar 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;}}/**\n * Minimal dicernible data precisioin according to a single pixel.\n *\n * @param {Array.<number>} dataExtent\n * @param {Array.<number>} pixelExtent\n * @return {number} precision\n */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);// toFixed() digits argument must be between 0 and 20.\nvar precision=Math.min(Math.max(-dataQuantity+sizeQuantity,0),20);return!isFinite(precision)?20:precision;}/**\n * Get a data of given precision, assuring the sum of percentages\n * in valueList is 1.\n * The largest remainer method is used.\n * https://en.wikipedia.org/wiki/Largest_remainder_method\n *\n * @param {Array.<number>} valueList a list of all data\n * @param {number} idx index of the data to be processed in valueList\n * @param {number} precision integer number showing digits of precision\n * @return {number} percent ranging from 0 to 100\n */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){// Assign automatic seats.\nreturn 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];});// Has remainding votes.\nwhile(currentSum<targetSeats){// Find next largest remainder.\nvar 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;}}// Add a vote to max remainder.\n++seats[maxId];remainder[maxId]=0;++currentSum;}return seats[idx]/digits;}// Number.MAX_SAFE_INTEGER, ie do not support.\nvar MAX_SAFE_INTEGER=9007199254740991;/**\n * To 0 - 2 * PI, considering negative radian.\n * @param {number} radian\n * @return {number}\n */function remRadian(radian){var pi2=Math.PI*2;return(radian%pi2+pi2)%pi2;}/**\n * @param {type} radian\n * @return {boolean}\n */function isRadianAroundZero(val){return val>-RADIAN_EPSILON&&val<RADIAN_EPSILON;}/* eslint-disable */var TIME_REG=/^(?:(\\d{4})(?:[-\\/](\\d{1,2})(?:[-\\/](\\d{1,2})(?:[T ](\\d{1,2})(?::(\\d\\d)(?::(\\d\\d)(?:[.,](\\d+))?)?)?(Z|[\\+\\-]\\d\\d:?\\d\\d)?)?)?)?)?$/;// jshint ignore:line\n/* eslint-enable */ /**\n * @param {string|Date|number} value These values can be accepted:\n *   + An instance of Date, represent a time in its own time zone.\n *   + Or string in a subset of ISO 8601, only including:\n *     + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',\n *     + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123',\n *     + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00',\n *     all of which will be treated as local time if time zone is not specified\n *     (see <https://momentjs.com/>).\n *   + Or other string format, including (all of which will be treated as loacal time):\n *     '2012', '2012-3-1', '2012/3/1', '2012/03/01',\n *     '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'\n *   + a timestamp, which represent a time in UTC.\n * @return {Date} date\n */function parseDate(value){if(value instanceof Date){return value;}else if(typeof value==='string'){// Different browsers parse date in different way, so we parse it manually.\n// Some other issues:\n// new Date('1970-01-01') is UTC,\n// new Date('1970/01/01') and new Date('1970-1-01') is local.\n// See issue #3623\nvar match=TIME_REG.exec(value);if(!match){// return Invalid Date.\nreturn new Date(NaN);}// Use local time when no timezone offset specifed.\nif(!match[8]){// match[n] can only be string or undefined.\n// But take care of '12' + 1 => '121'.\nreturn new Date(+match[1],+(match[2]||1)-1,+match[3]||1,+match[4]||0,+(match[5]||0),+match[6]||0,+match[7]||0);}// Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time,\n// https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment).\n// For example, system timezone is set as \"Time Zone: America/Toronto\",\n// then these code will get different result:\n// `new Date(1478411999999).getTimezoneOffset();  // get 240`\n// `new Date(1478412000000).getTimezoneOffset();  // get 300`\n// So we should not use `new Date`, but use `Date.UTC`.\nelse{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));}/**\n * Quantity of a number. e.g. 0.1, 1, 10, 100\n *\n * @param  {number} val\n * @return {number}\n */function quantity(val){return Math.pow(10,quantityExponent(val));}/**\n * Exponent of the quantity of a number\n * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3\n *\n * @param  {number} val non-negative value\n * @return {number}\n */function quantityExponent(val){if(val===0){return 0;}var exp=Math.floor(Math.log(val)/Math.LN10);/**\n     * exp is expected to be the rounded-down result of the base-10 log of val.\n     * But due to the precision loss with Math.log(val), we need to restore it\n     * using 10^exp to make sure we can get val back from exp. #11249\n     */if(val/Math.pow(10,exp)>=10){exp++;}return exp;}/**\n * find a “nice” number approximately equal to x. Round the number if round = true,\n * take ceiling if round = false. The primary observation is that the “nicest”\n * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers.\n *\n * See \"Nice Numbers for Graph Labels\" of Graphic Gems.\n *\n * @param  {number} val Non-negative value.\n * @param  {boolean} round\n * @return {number}\n */function nice(val,round){var exponent=quantityExponent(val);var exp10=Math.pow(10,exponent);var f=val/exp10;// 1 <= f < 10\nvar 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;// Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).\n// 20 is the uppper bound of toFixed.\nreturn exponent>=-20?+val.toFixed(exponent<0?-exponent:0):val;}/**\n * This code was copied from \"d3.js\"\n * <https://github.com/d3/d3/blob/9cc9a875e636a1dcf36cc1e07bdf77e1ad6e2c74/src/arrays/quantile.js>.\n * See the license statement at the head of this file.\n * @param {Array.<number>} ascArr\n */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;}/**\n * Order intervals asc, and split them when overlap.\n * expect(numberUtil.reformIntervals([\n *     {interval: [18, 62], close: [1, 1]},\n *     {interval: [-Infinity, -70], close: [0, 0]},\n *     {interval: [-70, -26], close: [1, 1]},\n *     {interval: [-26, 18], close: [1, 1]},\n *     {interval: [62, 150], close: [1, 1]},\n *     {interval: [106, 150], close: [1, 1]},\n *     {interval: [150, Infinity], close: [0, 0]}\n * ])).toEqual([\n *     {interval: [-Infinity, -70], close: [0, 0]},\n *     {interval: [-70, -26], close: [1, 1]},\n *     {interval: [-26, 18], close: [0, 1]},\n *     {interval: [18, 62], close: [0, 1]},\n *     {interval: [62, 150], close: [0, 1]},\n *     {interval: [150, Infinity], close: [0, 0]}\n * ]);\n * @param {Array.<Object>} list, where `close` mean open or close\n *        of the interval, and Infinity can be used.\n * @return {Array.<Object>} The origin list, which has been reformed.\n */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=list[i].close;for(var lg=0;lg<2;lg++){if(interval[lg]<=curr){interval[lg]=curr;close[lg]=!lg?1-currClose:1;}curr=interval[lg];currClose=close[lg];}if(interval[0]===interval[1]&&close[0]*close[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));}}/**\n * parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n * ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n * subtraction forces infinities to NaN\n *\n * @param {*} v\n * @return {boolean}\n */function isNumeric(v){return v-parseFloat(v)>=0;}var number=(Object.freeze||Object)({linearMap:linearMap,parsePercent:parsePercent$1,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,isNumeric:isNumeric});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // import Text from 'zrender/src/graphic/Text';\n/**\n * add commas after every three numbers\n * @param {string|number} x\n * @return {string}\n */function addCommas(x){if(isNaN(x)){return'-';}x=(x+'').split('.');return x[0].replace(/(\\d{1,3})(?=(?:\\d{3})+(?!\\d))/g,'$1,')+(x.length>1?'.'+x[1]:'');}/**\n * @param {string} str\n * @param {boolean} [upperCaseFirst=false]\n * @return {string} str\n */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];});}var TPL_VAR_ALIAS=['a','b','c','d','e','f','g'];var wrapVar=function wrapVar(varName,seriesIdx){return'{'+varName+(seriesIdx==null?'':seriesIdx)+'}';};/**\n * Template formatter\n * @param {string} tpl\n * @param {Array.<Object>|Object} paramsList\n * @param {boolean} [encode=false]\n * @return {string}\n */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;}/**\n * simple Template formatter\n *\n * @param {string} tpl\n * @param {Object} param\n * @param {boolean} [encode=false]\n * @return {string}\n */function formatTplSimple(tpl,param,encode){each$1(param,function(value,key){tpl=tpl.replace('{'+key+'}',encode?encodeHTML(value):value);});return tpl;}/**\n * @param {Object|string} [opt] If string, means color.\n * @param {string} [opt.color]\n * @param {string} [opt.extraCssText]\n * @param {string} [opt.type='item'] 'item' or 'subItem'\n * @param {string} [opt.renderMode='html'] render mode of tooltip, 'html' or 'richText'\n * @param {string} [opt.markerId='X'] id name for marker. If only one marker is in a rich text, this can be omitted.\n * @return {string}\n */function getTooltipMarker(opt,extraCssText){opt=isString(opt)?{color:opt,extraCssText:extraCssText}:opt||{};var color=opt.color;var type=opt.type;var extraCssText=opt.extraCssText;var renderMode=opt.renderMode||'html';var markerId=opt.markerId||'X';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:5px;'+'border-radius:10px;width:10px;height:10px;background-color:'+encodeHTML(color)+';'+(extraCssText||'')+'\"></span>';}else{// Space for rich element marker\nreturn{renderMode:renderMode,content:'{marker'+markerId+'|}  ',style:{color:color}};}}function pad(str,len){str+='';return'0000'.substr(0,len-str.length)+str;}/**\n * ISO Date format\n * @param {string} tpl\n * @param {number} value\n * @param {boolean} [isUTC=false] Default in local time.\n *           see `module:echarts/scale/Time`\n *           and `module:echarts/util/number#parseDate`.\n * @inner\n */function formatTime(tpl,value,isUTC){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;}/**\n * Capital first\n * @param {string} str\n * @return {string}\n */function capitalFirst(str){return str?str.charAt(0).toUpperCase()+str.substr(1):str;}var truncateText$1=truncateText;/**\n * @public\n * @param {Object} opt\n * @param {string} opt.text\n * @param {string} opt.font\n * @param {string} [opt.textAlign='left']\n * @param {string} [opt.textVerticalAlign='top']\n * @param {Array.<number>} [opt.textPadding]\n * @param {number} [opt.textLineHeight]\n * @param {Object} [opt.rich]\n * @param {Object} [opt.truncate]\n * @return {Object} {x, y, width, height, lineHeight}\n */function getTextBoundingRect(opt){return _getBoundingRect(opt.text,opt.font,opt.textAlign,opt.textVerticalAlign,opt.textPadding,opt.textLineHeight,opt.rich,opt.truncate);}/**\n * @deprecated\n * the `textLineHeight` was added later.\n * For backward compatiblility, put it as the last parameter.\n * But deprecated this interface. Please use `getTextBoundingRect` instead.\n */function getTextRect(text,font,textAlign,textVerticalAlign,textPadding,rich,truncate,textLineHeight){return _getBoundingRect(text,font,textAlign,textVerticalAlign,textPadding,textLineHeight,rich,truncate);}/**\n * open new tab\n * @param {string} link url\n * @param {string} target blank or self\n */function windowOpen(link,target){if(target==='_blank'||target==='blank'){var blank=window.open();blank.opener=null;blank.location=link;}else{window.open(link,target);}}var format=(Object.freeze||Object)({addCommas:addCommas,toCamelCase:toCamelCase,normalizeCssArray:normalizeCssArray$1,encodeHTML:encodeHTML,formatTpl:formatTpl,formatTplSimple:formatTplSimple,getTooltipMarker:getTooltipMarker,formatTime:formatTime,capitalFirst:capitalFirst,truncateText:truncateText$1,getTextBoundingRect:getTextBoundingRect,getTextRect:getTextRect,windowOpen:windowOpen});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Layout helpers for each component positioning\nvar each$3=each$1;/**\n * @public\n */var LOCATION_PARAMS=['left','right','top','bottom','width','height'];/**\n * @public\n */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 position=child.position;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;// Wrap when width exceeds maxWidth or meet a `newline` group\n// FIXME compare before adding gap?\nif(nextX>maxWidth||child.newline){x=0;nextX=moveX;y+=currentLineMaxSize+gap;currentLineMaxSize=rect.height;}else{// FIXME: consider rect.y is not `0`?\ncurrentLineMaxSize=Math.max(currentLineMaxSize,rect.height);}}else{var moveY=rect.height+(nextChildRect?-nextChildRect.y+rect.y:0);nextY=y+moveY;// Wrap when width exceeds maxHeight or meet a `newline` group\nif(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;}position[0]=x;position[1]=y;orient==='horizontal'?x=nextX+gap:y=nextY+gap;});}/**\n * VBox or HBox layouting\n * @param {string} orient\n * @param {module:zrender/container/Group} group\n * @param {number} gap\n * @param {number} [width=Infinity]\n * @param {number} [height=Infinity]\n */var box=boxLayout;/**\n * VBox layouting\n * @param {module:zrender/container/Group} group\n * @param {number} gap\n * @param {number} [width=Infinity]\n * @param {number} [height=Infinity]\n */var vbox=curry(boxLayout,'vertical');/**\n * HBox layouting\n * @param {module:zrender/container/Group} group\n * @param {number} gap\n * @param {number} [width=Infinity]\n * @param {number} [height=Infinity]\n */var hbox=curry(boxLayout,'horizontal');/**\n * If x or x2 is not specified or 'center' 'left' 'right',\n * the width would be as long as possible.\n * If y or y2 is not specified or 'middle' 'top' 'bottom',\n * the height would be as long as possible.\n *\n * @param {Object} positionInfo\n * @param {number|string} [positionInfo.x]\n * @param {number|string} [positionInfo.y]\n * @param {number|string} [positionInfo.x2]\n * @param {number|string} [positionInfo.y2]\n * @param {Object} containerRect {width, height}\n * @param {string|number} margin\n * @return {Object} {width, height}\n */ /**\n * Parse position info.\n *\n * @param {Object} positionInfo\n * @param {number|string} [positionInfo.left]\n * @param {number|string} [positionInfo.top]\n * @param {number|string} [positionInfo.right]\n * @param {number|string} [positionInfo.bottom]\n * @param {number|string} [positionInfo.width]\n * @param {number|string} [positionInfo.height]\n * @param {number|string} [positionInfo.aspect] Aspect is width / height\n * @param {Object} containerRect\n * @param {string|number} [margin]\n *\n * @return {module:zrender/core/BoundingRect}\n */function getLayoutRect(positionInfo,containerRect,margin){margin=normalizeCssArray$1(margin||0);var containerWidth=containerRect.width;var containerHeight=containerRect.height;var left=parsePercent$1(positionInfo.left,containerWidth);var top=parsePercent$1(positionInfo.top,containerHeight);var right=parsePercent$1(positionInfo.right,containerWidth);var bottom=parsePercent$1(positionInfo.bottom,containerHeight);var width=parsePercent$1(positionInfo.width,containerWidth);var height=parsePercent$1(positionInfo.height,containerHeight);var verticalMargin=margin[2]+margin[0];var horizontalMargin=margin[1]+margin[3];var aspect=positionInfo.aspect;// If width is not specified, calculate width from left and right\nif(isNaN(width)){width=containerWidth-right-horizontalMargin-left;}if(isNaN(height)){height=containerHeight-bottom-verticalMargin-top;}if(aspect!=null){// If width and height are not given\n// 1. Graph should not exceeds the container\n// 2. Aspect must be keeped\n// 3. Graph should take the space as more as possible\n// FIXME\n// Margin is not considered, because there is no case that both\n// using margin and aspect so far.\nif(isNaN(width)&&isNaN(height)){if(aspect>containerWidth/containerHeight){width=containerWidth*0.8;}else{height=containerHeight*0.8;}}// Calculate width or height with given aspect\nif(isNaN(width)){width=aspect*height;}if(isNaN(height)){height=width/aspect;}}// If left is not specified, calculate left from right and width\nif(isNaN(left)){left=containerWidth-right-width-horizontalMargin;}if(isNaN(top)){top=containerHeight-bottom-height-verticalMargin;}// Align left and top\nswitch(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;}// If something is wrong and left, top, width, height are calculated as NaN\nleft=left||0;top=top||0;if(isNaN(width)){// Width may be NaN if only one value is given except width\nwidth=containerWidth-horizontalMargin-left-(right||0);}if(isNaN(height)){// Height may be NaN if only one value is given except height\nheight=containerHeight-verticalMargin-top-(bottom||0);}var rect=new BoundingRect(left+margin[3],top+margin[0],width,height);rect.margin=margin;return rect;}/**\n * Position a zr element in viewport\n *  Group position is specified by either\n *  {left, top}, {right, bottom}\n *  If all properties exists, right and bottom will be igonred.\n *\n * Logic:\n *     1. Scale (against origin point in parent coord)\n *     2. Rotate (against origin point in parent coord)\n *     3. Traslate (with el.position by this method)\n * So this method only fixes the last step 'Traslate', which does not affect\n * scaling and rotating.\n *\n * If be called repeatly with the same input el, the same result will be gotten.\n *\n * @param {module:zrender/Element} el Should have `getBoundingRect` method.\n * @param {Object} positionInfo\n * @param {number|string} [positionInfo.left]\n * @param {number|string} [positionInfo.top]\n * @param {number|string} [positionInfo.right]\n * @param {number|string} [positionInfo.bottom]\n * @param {number|string} [positionInfo.width] Only for opt.boundingModel: 'raw'\n * @param {number|string} [positionInfo.height] Only for opt.boundingModel: 'raw'\n * @param {Object} containerRect\n * @param {string|number} margin\n * @param {Object} [opt]\n * @param {Array.<number>} [opt.hv=[1,1]] Only horizontal or only vertical.\n * @param {Array.<number>} [opt.boundingMode='all']\n *        Specify how to calculate boundingRect when locating.\n *        'all': Position the boundingRect that is transformed and uioned\n *               both itself and its descendants.\n *               This mode simplies confine the elements in the bounding\n *               of their container (e.g., using 'right: 0').\n *        'raw': Position the boundingRect that is not transformed and only itself.\n *               This mode is useful when you want a element can overflow its\n *               container. (Consider a rotated circle needs to be located in a corner.)\n *               In this mode positionInfo.width/height can only be number.\n */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();// Notice: raw rect may be inner object of el,\n// which should not be modified.\nrect=rect.clone();rect.applyTransform(transform);}}// The real width and height can not be specified but calculated by the given el.\npositionInfo=getLayoutRect(defaults({width:rect.width,height:rect.height},positionInfo),containerRect,margin);// Because 'tranlate' is the last step in transform\n// (see zrender/core/Transformable#getLocalTransform),\n// we can just only modify el.position to get final result.\nvar elPos=el.position;var dx=h?positionInfo.x-rect.x:0;var dy=v?positionInfo.y-rect.y:0;el.attr('position',boundingMode==='raw'?[dx,dy]:[elPos[0]+dx,elPos[1]+dy]);}/**\n * @param {Object} option Contains some of the properties in HV_NAMES.\n * @param {number} hvIdx 0: horizontal; 1: vertical.\n */ /**\n * Consider Case:\n * When defulat option has {left: 0, width: 100}, and we set {right: 0}\n * through setOption or media query, using normal zrUtil.merge will cause\n * {right: 0} does not take effect.\n *\n * @example\n * ComponentModel.extend({\n *     init: function () {\n *         ...\n *         var inputPositionParams = layout.getLayoutParams(option);\n *         this.mergeOption(inputPositionParams);\n *     },\n *     mergeOption: function (newOption) {\n *         newOption && zrUtil.merge(thisOption, newOption, true);\n *         layout.mergeLayoutParam(thisOption, newOption);\n *     }\n * });\n *\n * @param {Object} targetOption\n * @param {Object} newOption\n * @param {Object|string} [opt]\n * @param {boolean|Array.<boolean>} [opt.ignoreSize=false] Used for the components\n *  that width (or height) should not be calculated by left and right (or top and bottom).\n */function mergeLayoutParam(targetOption,newOption,opt){!isObject$1(opt)&&(opt={});var ignoreSize=opt.ignoreSize;!isArray(ignoreSize)&&(ignoreSize=[ignoreSize,ignoreSize]);var hResult=merge$$1(HV_NAMES[0],0);var vResult=merge$$1(HV_NAMES[1],1);copy(HV_NAMES[0],targetOption,hResult);copy(HV_NAMES[1],targetOption,vResult);function merge$$1(names,hvIdx){var newParams={};var newValueCount=0;var merged={};var mergedValueCount=0;var enoughParamNumber=2;each$3(names,function(name){merged[name]=targetOption[name];});each$3(names,function(name){// Consider case: newOption.width is null, which is\n// set by user for removing width setting.\nhasProp(newOption,name)&&(newParams[name]=merged[name]=newOption[name]);hasValue(newParams,name)&&newValueCount++;hasValue(merged,name)&&mergedValueCount++;});if(ignoreSize[hvIdx]){// Only one of left/right is premitted to exist.\nif(hasValue(newOption,names[1])){merged[names[2]]=null;}else if(hasValue(newOption,names[2])){merged[names[1]]=null;}return merged;}// Case: newOption: {width: ..., right: ...},\n// or targetOption: {right: ...} and newOption: {width: ...},\n// There is no conflict when merged only has params count\n// little than enoughParamNumber.\nif(mergedValueCount===enoughParamNumber||!newValueCount){return merged;}// Case: newOption: {width: ..., right: ...},\n// Than we can make sure user only want those two, and ignore\n// all origin params in targetOption.\nelse if(newValueCount>=enoughParamNumber){return newParams;}else{// Chose another param from targetOption by priority.\nfor(var i=0;i<names.length;i++){var name=names[i];if(!hasProp(newParams,name)&&hasProp(targetOption,name)){newParams[name]=targetOption[name];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$3(names,function(name){target[name]=source[name];});}}/**\n * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.\n * @param {Object} source\n * @return {Object} Result contains those props.\n */function getLayoutParams(source){return copyLayoutParams({},source);}/**\n * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.\n * @param {Object} source\n * @return {Object} Result contains those props.\n */function copyLayoutParams(target,source){source&&target&&each$3(LOCATION_PARAMS,function(name){source.hasOwnProperty(name)&&(target[name]=source[name]);});return target;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var boxLayoutMixin={getBoxLayoutParams:function getBoxLayoutParams(){return{left:this.get('left'),top:this.get('top'),right:this.get('right'),bottom:this.get('bottom'),width:this.get('width'),height:this.get('height')};}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Component model\n *\n * @module echarts/model/Component\n */var inner$1=makeInner();/**\n * @alias module:echarts/model/Component\n * @constructor\n * @param {Object} option\n * @param {module:echarts/model/Model} parentModel\n * @param {module:echarts/model/Model} ecModel\n */var ComponentModel=Model.extend({type:'component',/**\n     * @readOnly\n     * @type {string}\n     */id:'',/**\n     * Because simplified concept is probably better, series.name (or component.name)\n     * has been having too many resposibilities:\n     * (1) Generating id (which requires name in option should not be modified).\n     * (2) As an index to mapping series when merging option or calling API (a name\n     * can refer to more then one components, which is convinient is some case).\n     * (3) Display.\n     * @readOnly\n     */name:'',/**\n     * @readOnly\n     * @type {string}\n     */mainType:'',/**\n     * @readOnly\n     * @type {string}\n     */subType:'',/**\n     * @readOnly\n     * @type {number}\n     */componentIndex:0,/**\n     * @type {Object}\n     * @protected\n     */defaultOption:null,/**\n     * @type {module:echarts/model/Global}\n     * @readOnly\n     */ecModel:null,/**\n     * key: componentType\n     * value:  Component model list, can not be null.\n     * @type {Object.<string, Array.<module:echarts/model/Model>>}\n     * @readOnly\n     */dependentModels:[],/**\n     * @type {string}\n     * @readOnly\n     */uid:null,/**\n     * Support merge layout params.\n     * Only support 'box' now (left/right/top/bottom/width/height).\n     * @type {string|Object} Object can be {ignoreSize: true}\n     * @readOnly\n     */layoutMode:null,$constructor:function $constructor(option,parentModel,ecModel,extraOpt){Model.call(this,option,parentModel,ecModel,extraOpt);this.uid=getUID('ec_cpt_model');},init:function init(option,parentModel,ecModel,extraOpt){this.mergeDefaultAndTheme(option,ecModel);},mergeDefaultAndTheme:function mergeDefaultAndTheme(option,ecModel){var layoutMode=this.layoutMode;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);}},mergeOption:function mergeOption(option,extraOpt){merge(this.option,option,true);var layoutMode=this.layoutMode;if(layoutMode){mergeLayoutParam(this.option,option,layoutMode);}},// Hooker after init or mergeOption\noptionUpdated:function optionUpdated(newCptOption,isInit){},getDefaultOption:function getDefaultOption(){var fields=inner$1(this);if(!fields.defaultOption){var optList=[];var Class=this.constructor;while(Class){var opt=Class.prototype.defaultOption;opt&&optList.push(opt);Class=Class.superClass;}var defaultOption={};for(var i=optList.length-1;i>=0;i--){defaultOption=merge(defaultOption,optList[i],true);}fields.defaultOption=defaultOption;}return fields.defaultOption;},getReferringComponents:function getReferringComponents(mainType){return this.ecModel.queryComponents({mainType:mainType,index:this.get(mainType+'Index',true),id:this.get(mainType+'Id',true)});}});// Reset ComponentModel.extend, add preConstruct.\n// clazzUtil.enableClassExtend(\n//     ComponentModel,\n//     function (option, parentModel, ecModel, extraOpt) {\n//         // Set dependentModels, componentIndex, name, id, mainType, subType.\n//         zrUtil.extend(this, extraOpt);\n//         this.uid = componentUtil.getUID('componentModel');\n//         // this.setReadOnly([\n//         //     'type', 'id', 'uid', 'name', 'mainType', 'subType',\n//         //     'dependentModels', 'componentIndex'\n//         // ]);\n//     }\n// );\n// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.\nenableClassManagement(ComponentModel,{registerWhenExtend:true});enableSubTypeDefaulter(ComponentModel);// Add capability of ComponentModel.topologicalTravel.\nenableTopologicalTravel(ComponentModel,getDependencies);function getDependencies(componentType){var deps=[];each$1(ComponentModel.getClassesByMainType(componentType),function(Clazz){deps=deps.concat(Clazz.prototype.dependencies||[]);});// Ensure main type.\ndeps=map(deps,function(type){return parseClassType$1(type).main;});// Hack dataset for convenience.\nif(componentType!=='dataset'&&indexOf(deps,'dataset')<=0){deps.unshift('dataset');}return deps;}mixin(ComponentModel,boxLayoutMixin);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var platform='';// Navigator not exists in node\nif(typeof navigator!=='undefined'){platform=navigator.platform||'';}var globalDefault={// backgroundColor: 'rgba(0,0,0,0)',\n// https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization\n// color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],\n// Light colors:\n// color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],\n// color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],\n// Dark colors:\ncolor:['#c23531','#2f4554','#61a0a8','#d48265','#91c7ae','#749f83','#ca8622','#bda29a','#6e7074','#546570','#c4ccd3'],gradientColor:['#f6efa6','#d88273','#bf444c'],// If xAxis and yAxis declared, grid is created by default.\n// grid: {},\ntextStyle:{// color: '#000',\n// decoration: 'none',\n// PENDING\nfontFamily:platform.match(/^Win/)?'Microsoft YaHei':'sans-serif',// fontFamily: 'Arial, Verdana, sans-serif',\nfontSize:12,fontStyle:'normal',fontWeight:'normal'},// http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/\n// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation\n// Default is source-over\nblendMode:null,animation:'auto',animationDuration:1000,animationDurationUpdate:300,animationEasing:'exponentialOut',animationEasingUpdate:'cubicOut',animationThreshold:2000,// Configuration for progressive/incremental rendering\nprogressiveThreshold:3000,progressive:400,// Threshold of if use single hover layer to optimize.\n// It is recommended that `hoverLayerThreshold` is equivalent to or less than\n// `progressiveThreshold`, otherwise hover will cause restart of progressive,\n// which is unexpected.\n// see example <echarts/test/heatmap-large.html>.\nhoverLayerThreshold:3000,// See: module:echarts/scale/Time\nuseUTC:false};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$2=makeInner();function getNearestColorPalette(colors,requestColorNum){var paletteNum=colors.length;// TODO colors must be in order\nfor(var i=0;i<paletteNum;i++){if(colors[i].length>requestColorNum){return colors[i];}}return colors[paletteNum-1];}var colorPaletteMixin={clearColorPalette:function clearColorPalette(){inner$2(this).colorIdx=0;inner$2(this).colorNameMap={};},/**\n     * @param {string} name MUST NOT be null/undefined. Otherwise call this function\n     *                 twise with the same parameters will get different result.\n     * @param {Object} [scope=this]\n     * @param {Object} [requestColorNum]\n     * @return {string} color string.\n     */getColorFromPalette:function getColorFromPalette(name,scope,requestColorNum){scope=scope||this;var scopeFields=inner$2(scope);var colorIdx=scopeFields.colorIdx||0;var colorNameMap=scopeFields.colorNameMap=scopeFields.colorNameMap||{};// Use `hasOwnProperty` to avoid conflict with Object.prototype.\nif(colorNameMap.hasOwnProperty(name)){return colorNameMap[name];}var defaultColorPalette=normalizeToArray(this.get('color',true));var layeredColorPalette=this.get('colorLayer',true);var colorPalette=requestColorNum==null||!layeredColorPalette?defaultColorPalette:getNearestColorPalette(layeredColorPalette,requestColorNum);// In case can't find in layered color palette.\ncolorPalette=colorPalette||defaultColorPalette;if(!colorPalette||!colorPalette.length){return;}var color=colorPalette[colorIdx];if(name){colorNameMap[name]=color;}scopeFields.colorIdx=(colorIdx+1)%colorPalette.length;return color;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Avoid typo.\nvar 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_UNKNOWN='unknown';// ??? CHANGE A NAME\nvar SOURCE_FORMAT_TYPED_ARRAY='typedArray';var SERIES_LAYOUT_BY_COLUMN='column';var SERIES_LAYOUT_BY_ROW='row';/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * [sourceFormat]\n *\n * + \"original\":\n * This format is only used in series.data, where\n * itemStyle can be specified in data item.\n *\n * + \"arrayRows\":\n * [\n *     ['product', 'score', 'amount'],\n *     ['Matcha Latte', 89.3, 95.8],\n *     ['Milk Tea', 92.1, 89.4],\n *     ['Cheese Cocoa', 94.4, 91.2],\n *     ['Walnut Brownie', 85.4, 76.9]\n * ]\n *\n * + \"objectRows\":\n * [\n *     {product: 'Matcha Latte', score: 89.3, amount: 95.8},\n *     {product: 'Milk Tea', score: 92.1, amount: 89.4},\n *     {product: 'Cheese Cocoa', score: 94.4, amount: 91.2},\n *     {product: 'Walnut Brownie', score: 85.4, amount: 76.9}\n * ]\n *\n * + \"keyedColumns\":\n * {\n *     'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],\n *     'count': [823, 235, 1042, 988],\n *     'score': [95.8, 81.4, 91.2, 76.9]\n * }\n *\n * + \"typedArray\"\n *\n * + \"unknown\"\n */ /**\n * @constructor\n * @param {Object} fields\n * @param {string} fields.sourceFormat\n * @param {Array|Object} fields.fromDataset\n * @param {Array|Object} [fields.data]\n * @param {string} [seriesLayoutBy='column']\n * @param {Array.<Object|string>} [dimensionsDefine]\n * @param {Objet|HashMap} [encodeDefine]\n * @param {number} [startIndex=0]\n * @param {number} [dimensionsDetectCount]\n */function Source(fields){/**\n     * @type {boolean}\n     */this.fromDataset=fields.fromDataset;/**\n     * Not null/undefined.\n     * @type {Array|Object}\n     */this.data=fields.data||(fields.sourceFormat===SOURCE_FORMAT_KEYED_COLUMNS?{}:[]);/**\n     * See also \"detectSourceFormat\".\n     * Not null/undefined.\n     * @type {string}\n     */this.sourceFormat=fields.sourceFormat||SOURCE_FORMAT_UNKNOWN;/**\n     * 'row' or 'column'\n     * Not null/undefined.\n     * @type {string} seriesLayoutBy\n     */this.seriesLayoutBy=fields.seriesLayoutBy||SERIES_LAYOUT_BY_COLUMN;/**\n     * dimensions definition in option.\n     * can be null/undefined.\n     * @type {Array.<Object|string>}\n     */this.dimensionsDefine=fields.dimensionsDefine;/**\n     * encode definition in option.\n     * can be null/undefined.\n     * @type {Objet|HashMap}\n     */this.encodeDefine=fields.encodeDefine&&createHashMap(fields.encodeDefine);/**\n     * Not null/undefined, uint.\n     * @type {number}\n     */this.startIndex=fields.startIndex||0;/**\n     * Can be null/undefined (when unknown), uint.\n     * @type {number}\n     */this.dimensionsDetectCount=fields.dimensionsDetectCount;}/**\n * Wrap original series data for some compatibility cases.\n */Source.seriesDataToSource=function(data){return new Source({data:data,sourceFormat:isTypedArray(data)?SOURCE_FORMAT_TYPED_ARRAY:SOURCE_FORMAT_ORIGINAL,fromDataset:false});};enableClassCheck(Source);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // The result of `guessOrdinal`.\nvar BE_ORDINAL={Must:1,// Encounter string but not '-' and not number-like.\nMight:2,// Encounter string but number-like.\nNot:3// Other cases\n};var inner$3=makeInner();/**\n * @see {module:echarts/data/Source}\n * @param {module:echarts/component/dataset/DatasetModel} datasetModel\n * @return {string} sourceFormat\n */function detectSourceFormat(datasetModel){var data=datasetModel.option.source;var sourceFormat=SOURCE_FORMAT_UNKNOWN;if(isTypedArray(data)){sourceFormat=SOURCE_FORMAT_TYPED_ARRAY;}else if(isArray(data)){// FIXME Whether tolerate null in top level array?\nif(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$1(item)){sourceFormat=SOURCE_FORMAT_OBJECT_ROWS;break;}}}else if(isObject$1(data)){for(var key in data){if(data.hasOwnProperty(key)&&isArrayLike(data[key])){sourceFormat=SOURCE_FORMAT_KEYED_COLUMNS;break;}}}else if(data!=null){throw new Error('Invalid data');}inner$3(datasetModel).sourceFormat=sourceFormat;}/**\n * [Scenarios]:\n * (1) Provide source data directly:\n *     series: {\n *         encode: {...},\n *         dimensions: [...]\n *         seriesLayoutBy: 'row',\n *         data: [[...]]\n *     }\n * (2) Refer to datasetModel.\n *     series: [{\n *         encode: {...}\n *         // Ignore datasetIndex means `datasetIndex: 0`\n *         // and the dimensions defination in dataset is used\n *     }, {\n *         encode: {...},\n *         seriesLayoutBy: 'column',\n *         datasetIndex: 1\n *     }]\n *\n * Get data from series itself or datset.\n * @return {module:echarts/data/Source} source\n */function _getSource(seriesModel){return inner$3(seriesModel).source;}/**\n * MUST be called before mergeOption of all series.\n * @param {module:echarts/model/Global} ecModel\n */function resetSourceDefaulter(ecModel){// `datasetMap` is used to make default encode.\ninner$3(ecModel).datasetMap=createHashMap();}/**\n * [Caution]:\n * MUST be called after series option merged and\n * before \"series.getInitailData()\" called.\n *\n * [The rule of making default encode]:\n * Category axis (if exists) alway map to the first dimension.\n * Each other axis occupies a subsequent dimension.\n *\n * [Why make default encode]:\n * Simplify the typing of encode in option, avoiding the case like that:\n * series: [{encode: {x: 0, y: 1}}, {encode: {x: 0, y: 2}}, {encode: {x: 0, y: 3}}],\n * where the \"y\" have to be manually typed as \"1, 2, 3, ...\".\n *\n * @param {module:echarts/model/Series} seriesModel\n */function prepareSource(seriesModel){var seriesOption=seriesModel.option;var data=seriesOption.data;var sourceFormat=isTypedArray(data)?SOURCE_FORMAT_TYPED_ARRAY:SOURCE_FORMAT_ORIGINAL;var fromDataset=false;var seriesLayoutBy=seriesOption.seriesLayoutBy;var sourceHeader=seriesOption.sourceHeader;var dimensionsDefine=seriesOption.dimensions;var datasetModel=getDatasetModel(seriesModel);if(datasetModel){var datasetOption=datasetModel.option;data=datasetOption.source;sourceFormat=inner$3(datasetModel).sourceFormat;fromDataset=true;// These settings from series has higher priority.\nseriesLayoutBy=seriesLayoutBy||datasetOption.seriesLayoutBy;sourceHeader==null&&(sourceHeader=datasetOption.sourceHeader);dimensionsDefine=dimensionsDefine||datasetOption.dimensions;}var completeResult=completeBySourceData(data,sourceFormat,seriesLayoutBy,sourceHeader,dimensionsDefine);inner$3(seriesModel).source=new Source({data:data,fromDataset:fromDataset,seriesLayoutBy:seriesLayoutBy,sourceFormat:sourceFormat,dimensionsDefine:completeResult.dimensionsDefine,startIndex:completeResult.startIndex,dimensionsDetectCount:completeResult.dimensionsDetectCount,// Note: dataset option does not have `encode`.\nencodeDefine:seriesOption.encode});}// return {startIndex, dimensionsDefine, dimensionsCount}\nfunction completeBySourceData(data,sourceFormat,seriesLayoutBy,sourceHeader,dimensionsDefine){if(!data){return{dimensionsDefine:normalizeDimensionsDefine(dimensionsDefine)};}var dimensionsDetectCount;var startIndex;if(sourceFormat===SOURCE_FORMAT_ARRAY_ROWS){// Rule: Most of the first line are string: it is header.\n// Caution: consider a line with 5 string and 1 number,\n// it still can not be sure it is a head, because the\n// 5 string may be 5 values of category columns.\nif(sourceHeader==='auto'||sourceHeader==null){arrayRowsTravelFirst(function(val){// '-' is regarded as null/undefined.\nif(val!=null&&val!=='-'){if(isString(val)){startIndex==null&&(startIndex=1);}else{startIndex=0;}}// 10 is an experience number, avoid long loop.\n},seriesLayoutBy,data,10);}else{startIndex=sourceHeader?1:0;}if(!dimensionsDefine&&startIndex===1){dimensionsDefine=[];arrayRowsTravelFirst(function(val,index){dimensionsDefine[index]=val!=null?val:'';},seriesLayoutBy,data);}dimensionsDetectCount=dimensionsDefine?dimensionsDefine.length:seriesLayoutBy===SERIES_LAYOUT_BY_ROW?data.length:data[0]?data[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$1(data,function(colArr,key){dimensionsDefine.push(key);});}}else if(sourceFormat===SOURCE_FORMAT_ORIGINAL){var value0=getDataItemValue(data[0]);dimensionsDetectCount=isArray(value0)&&value0.length||1;}else if(sourceFormat===SOURCE_FORMAT_TYPED_ARRAY){if(__DEV__){assert$1(!!dimensionsDefine,'dimensions must be given if data is TypedArray.');}}return{startIndex:startIndex,dimensionsDefine:normalizeDimensionsDefine(dimensionsDefine),dimensionsDetectCount:dimensionsDetectCount};}// Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'],\n// which is reasonable. But dimension name is duplicated.\n// Returns undefined or an array contains only object without null/undefiend or string.\nfunction normalizeDimensionsDefine(dimensionsDefine){if(!dimensionsDefine){// The meaning of null/undefined is different from empty array.\nreturn;}var nameMap=createHashMap();return map(dimensionsDefine,function(item,index){item=extend({},isObject$1(item)?item:{name:item});// User can set null in dimensions.\n// We dont auto specify name, othewise a given name may\n// cause it be refered unexpectedly.\nif(item.name==null){return item;}// Also consider number form like 2012.\nitem.name+='';// User may also specify displayName.\n// displayName will always exists except user not\n// specified or dim name is not specified or detected.\n// (A auto generated dim name will not be used as\n// displayName).\nif(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){maxLoop==null&&(maxLoop=Infinity);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);}}}function objectRowsCollectDimensions(data){var firstIndex=0;var obj;while(firstIndex<data.length&&!(obj=data[firstIndex++])){}// jshint ignore: line\nif(obj){var dimensions=[];each$1(obj,function(value,key){dimensions.push(key);});return dimensions;}}/**\n * [The strategy of the arrengment of data dimensions for dataset]:\n * \"value way\": all axes are non-category axes. So series one by one take\n *     several (the number is coordSysDims.length) dimensions from dataset.\n *     The result of data arrengment of data dimensions like:\n *     | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y |\n * \"category way\": at least one axis is category axis. So the the first data\n *     dimension is always mapped to the first category axis and shared by\n *     all of the series. The other data dimensions are taken by series like\n *     \"value way\" does.\n *     The result of data arrengment of data dimensions like:\n *     | ser_shared_x | ser0_y | ser1_y | ser2_y |\n *\n * @param {Array.<Object|string>} coordDimensions [{name: <string>, type: <string>, dimsDef: <Array>}, ...]\n * @param {module:model/Series} seriesModel\n * @param {module:data/Source} source\n * @return {Object} encode Never be `null/undefined`.\n */function makeSeriesEncodeForAxisCoordSys(coordDimensions,seriesModel,source){var encode={};var datasetModel=getDatasetModel(seriesModel);// Currently only make default when using dataset, util more reqirements occur.\nif(!datasetModel||!coordDimensions){return encode;}var encodeItemName=[];var encodeSeriesName=[];var ecModel=seriesModel.ecModel;var datasetMap=inner$3(ecModel).datasetMap;var key=datasetModel.uid+'_'+source.seriesLayoutBy;var baseCategoryDimIndex;var categoryWayValueDimStart;coordDimensions=coordDimensions.slice();each$1(coordDimensions,function(coordDimInfo,coordDimIdx){!isObject$1(coordDimInfo)&&(coordDimensions[coordDimIdx]={name:coordDimInfo});if(coordDimInfo.type==='ordinal'&&baseCategoryDimIndex==null){baseCategoryDimIndex=coordDimIdx;categoryWayValueDimStart=getDataDimCountOnCoordDim(coordDimensions[coordDimIdx]);}encode[coordDimInfo.name]=[];});var datasetRecord=datasetMap.get(key)||datasetMap.set(key,{categoryWayDim:categoryWayValueDimStart,valueWayDim:0});// TODO\n// Auto detect first time axis and do arrangement.\neach$1(coordDimensions,function(coordDimInfo,coordDimIdx){var coordDimName=coordDimInfo.name;var count=getDataDimCountOnCoordDim(coordDimInfo);// In value way.\nif(baseCategoryDimIndex==null){var start=datasetRecord.valueWayDim;pushDim(encode[coordDimName],start,count);pushDim(encodeSeriesName,start,count);datasetRecord.valueWayDim+=count;// ??? TODO give a better default series name rule?\n// especially when encode x y specified.\n// consider: when mutiple series share one dimension\n// category axis, series name should better use\n// the other dimsion name. On the other hand, use\n// both dimensions name.\n}// In category way, the first category axis.\nelse if(baseCategoryDimIndex===coordDimIdx){pushDim(encode[coordDimName],0,count);pushDim(encodeItemName,0,count);}// In category way, the other axis.\nelse{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;}/**\n * Work for data like [{name: ..., value: ...}, ...].\n *\n * @param {module:model/Series} seriesModel\n * @param {module:data/Source} source\n * @return {Object} encode Never be `null/undefined`.\n */function makeSeriesEncodeForNameBased(seriesModel,source,dimCount){var encode={};var datasetModel=getDatasetModel(seriesModel);// Currently only make default when using dataset, util more reqirements occur.\nif(!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$1(dimensionsDefine,function(dim,idx){if((isObject$1(dim)?dim.name:dim)==='name'){potentialNameDimIndex=idx;}});}// idxResult: {v, n}.\nvar idxResult=function(){var idxRes0={};var idxRes1={};var guessRecords=[];// 5 is an experience value.\nfor(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;// [Strategy of idxRes0]: find the first BE_ORDINAL.Not as the value dim,\n// and then find a name dim with the priority:\n// \"BE_ORDINAL.Might|BE_ORDINAL.Must\" > \"other dim\" > \"the value dim itself\".\nif(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;}// [Strategy of idxRes1]: if idxRes0 not satisfied (that is, no BE_ORDINAL.Not),\n// find the first BE_ORDINAL.Might as the value dim,\n// and then find a name dim with the priority:\n// \"other dim\" > \"the value dim itself\".\n// That is for backward compat: number-like (e.g., `'3'`, `'55'`) can be\n// treated as number.\nif(!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;// `potentialNameDimIndex` has highest priority.\nvar nameDimIndex=potentialNameDimIndex!=null?potentialNameDimIndex:idxResult.n;// By default, label use itemName in charts.\n// So we dont set encodeLabel here.\nencode.itemName=[nameDimIndex];encode.seriesName=[nameDimIndex];}return encode;}/**\n * If return null/undefined, indicate that should not use datasetModel.\n */function getDatasetModel(seriesModel){var option=seriesModel.option;// Caution: consider the scenario:\n// A dataset is declared and a series is not expected to use the dataset,\n// and at the beginning `setOption({series: { noData })` (just prepare other\n// option but no data), then `setOption({series: {data: [...]}); In this case,\n// the user should set an empty array to avoid that dataset is used by default.\nvar thisData=option.data;if(!thisData){return seriesModel.ecModel.getComponent('dataset',option.datasetIndex||0);}}/**\n * The rule should not be complex, otherwise user might not\n * be able to known where the data is wrong.\n * The code is ugly, but how to make it neat?\n *\n * @param {module:echars/data/Source} source\n * @param {number} dimIndex\n * @return {BE_ORDINAL} guess result.\n */function guessOrdinal(source,dimIndex){return doGuessOrdinal(source.data,source.sourceFormat,source.seriesLayoutBy,source.dimensionsDefine,source.startIndex,dimIndex);}// dimIndex may be overflow source data.\n// return {BE_ORDINAL}\nfunction doGuessOrdinal(data,sourceFormat,seriesLayoutBy,dimensionsDefine,startIndex,dimIndex){var result;// Experience value.\nvar maxLoop=5;if(isTypedArray(data)){return BE_ORDINAL.Not;}// When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine\n// always exists in source.\nvar dimName;var dimType;if(dimensionsDefine){var dimDefItem=dimensionsDefine[dimIndex];if(isObject$1(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){if(seriesLayoutBy===SERIES_LAYOUT_BY_ROW){var sample=data[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<data.length&&i<maxLoop;i++){var row=data[startIndex+i];if(row&&(result=detectValue(row[dimIndex]))!=null){return result;}}}}else if(sourceFormat===SOURCE_FORMAT_OBJECT_ROWS){if(!dimName){return BE_ORDINAL.Not;}for(var i=0;i<data.length&&i<maxLoop;i++){var item=data[i];if(item&&(result=detectValue(item[dimName]))!=null){return result;}}}else if(sourceFormat===SOURCE_FORMAT_KEYED_COLUMNS){if(!dimName){return BE_ORDINAL.Not;}var sample=data[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){for(var i=0;i<data.length&&i<maxLoop;i++){var item=data[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);// Consider usage convenience, '1', '2' will be treated as \"number\".\n// `isFinit('')` get `true`.\nif(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;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * ECharts global model\n *\n * @module {echarts/model/Global}\n */ /**\n * Caution: If the mechanism should be changed some day, these cases\n * should be considered:\n *\n * (1) In `merge option` mode, if using the same option to call `setOption`\n * many times, the result should be the same (try our best to ensure that).\n * (2) In `merge option` mode, if a component has no id/name specified, it\n * will be merged by index, and the result sequence of the components is\n * consistent to the original sequence.\n * (3) `reset` feature (in toolbox). Find detailed info in comments about\n * `mergeOption` in module:echarts/model/OptionManager.\n */var OPTION_INNER_KEY='\\0_ec_inner';/**\n * @alias module:echarts/model/Global\n *\n * @param {Object} option\n * @param {module:echarts/model/Model} parentModel\n * @param {Object} theme\n */var GlobalModel=Model.extend({init:function init(option,parentModel,theme,optionManager){theme=theme||{};this.option=null;// Mark as not initialized.\n/**\n         * @type {module:echarts/model/Model}\n         * @private\n         */this._theme=new Model(theme);/**\n         * @type {module:echarts/model/OptionManager}\n         */this._optionManager=optionManager;},setOption:function setOption(option,optionPreprocessorFuncs){assert$1(!(OPTION_INNER_KEY in option),'please use chart.getOption()');this._optionManager.setOption(option,optionPreprocessorFuncs);this.resetOption(null);},/**\n     * @param {string} type null/undefined: reset all.\n     *                      'recreate': force recreate all.\n     *                      'timeline': only reset timeline option\n     *                      'media': only reset media query option\n     * @return {boolean} Whether option changed.\n     */resetOption:function resetOption(type){var optionChanged=false;var optionManager=this._optionManager;if(!type||type==='recreate'){var baseOption=optionManager.mountOption(type==='recreate');if(!this.option||type==='recreate'){initBase.call(this,baseOption);}else{this.restoreData();this.mergeOption(baseOption);}optionChanged=true;}if(type==='timeline'||type==='media'){this.restoreData();}if(!type||type==='recreate'||type==='timeline'){var timelineOption=optionManager.getTimelineOption(this);timelineOption&&(this.mergeOption(timelineOption),optionChanged=true);}if(!type||type==='recreate'||type==='media'){var mediaOptions=optionManager.getMediaOption(this,this._api);if(mediaOptions.length){each$1(mediaOptions,function(mediaOption){this.mergeOption(mediaOption,optionChanged=true);},this);}}return optionChanged;},/**\n     * @protected\n     */mergeOption:function mergeOption(newOption){var option=this.option;var componentsMap=this._componentsMap;var newCptTypes=[];resetSourceDefaulter(this);// If no component class, merge directly.\n// For example: color, animaiton options, etc.\neach$1(newOption,function(componentOption,mainType){if(componentOption==null){return;}if(!ComponentModel.hasClass(mainType)){// globalSettingTask.dirty();\noption[mainType]=option[mainType]==null?_clone(componentOption):merge(option[mainType],componentOption,true);}else if(mainType){newCptTypes.push(mainType);}});ComponentModel.topologicalTravel(newCptTypes,ComponentModel.getAllClassMainTypes(),visitComponent,this);function visitComponent(mainType,dependencies){var newCptOptionList=normalizeToArray(newOption[mainType]);var mapResult=mappingToExists(componentsMap.get(mainType),newCptOptionList);makeIdAndName(mapResult);// Set mainType and complete subType.\neach$1(mapResult,function(item,index){var opt=item.option;if(isObject$1(opt)){item.keyInfo.mainType=mainType;item.keyInfo.subType=determineSubType(mainType,opt,item.exist);}});var dependentModels=getComponentsByTypes(componentsMap,dependencies);option[mainType]=[];componentsMap.set(mainType,[]);each$1(mapResult,function(resultItem,index){var componentModel=resultItem.exist;var newCptOption=resultItem.option;assert$1(isObject$1(newCptOption)||componentModel,'Empty component definition');// Consider where is no new option and should be merged using {},\n// see removeEdgeAndAdd in topologicalTravel and\n// ComponentModel.getAllClassMainTypes.\nif(!newCptOption){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.settingTask && componentModel.settingTask.dirty();\ncomponentModel.mergeOption(newCptOption,this);componentModel.optionUpdated(newCptOption,false);}else{// PENDING Global as parent ?\nvar extraOpt=extend({dependentModels:dependentModels,componentIndex:index},resultItem.keyInfo);componentModel=new ComponentModelClass(newCptOption,this,this,extraOpt);extend(componentModel,extraOpt);componentModel.init(newCptOption,this,this,extraOpt);// Call optionUpdated after init.\n// newCptOption has been used as componentModel.option\n// and may be merged with theme and default, so pass null\n// to avoid confusion.\ncomponentModel.optionUpdated(null,true);}}componentsMap.get(mainType)[index]=componentModel;option[mainType][index]=componentModel.option;},this);// Backup series for filtering.\nif(mainType==='series'){createSeriesIndices(this,componentsMap.get('series'));}}this._seriesIndicesMap=createHashMap(this._seriesIndices=this._seriesIndices||[]);},/**\n     * Get option for output (cloned option and inner info removed)\n     * @public\n     * @return {Object}\n     */getOption:function getOption(){var option=_clone(this.option);each$1(option,function(opts,mainType){if(ComponentModel.hasClass(mainType)){var opts=normalizeToArray(opts);for(var i=opts.length-1;i>=0;i--){// Remove options with inner id.\nif(isIdInner(opts[i])){opts.splice(i,1);}}option[mainType]=opts;}});delete option[OPTION_INNER_KEY];return option;},/**\n     * @return {module:echarts/model/Model}\n     */getTheme:function getTheme(){return this._theme;},/**\n     * @param {string} mainType\n     * @param {number} [idx=0]\n     * @return {module:echarts/model/Component}\n     */getComponent:function getComponent(mainType,idx){var list=this._componentsMap.get(mainType);if(list){return list[idx||0];}},/**\n     * If none of index and id and name used, return all components with mainType.\n     * @param {Object} condition\n     * @param {string} condition.mainType\n     * @param {string} [condition.subType] If ignore, only query by mainType\n     * @param {number|Array.<number>} [condition.index] Either input index or id or name.\n     * @param {string|Array.<string>} [condition.id] Either input index or id or name.\n     * @param {string|Array.<string>} [condition.name] Either input index or id or name.\n     * @return {Array.<module:echarts/model/Component>}\n     */queryComponents:function queryComponents(condition){var mainType=condition.mainType;if(!mainType){return[];}var index=condition.index;var id=condition.id;var name=condition.name;var cpts=this._componentsMap.get(mainType);if(!cpts||!cpts.length){return[];}var result;if(index!=null){if(!isArray(index)){index=[index];}result=filter(map(index,function(idx){return cpts[idx];}),function(val){return!!val;});}else if(id!=null){var isIdArray=isArray(id);result=filter(cpts,function(cpt){return isIdArray&&indexOf(id,cpt.id)>=0||!isIdArray&&cpt.id===id;});}else if(name!=null){var isNameArray=isArray(name);result=filter(cpts,function(cpt){return isNameArray&&indexOf(name,cpt.name)>=0||!isNameArray&&cpt.name===name;});}else{// Return all components with mainType\nresult=cpts.slice();}return filterBySubType(result,condition);},/**\n     * The interface is different from queryComponents,\n     * which is convenient for inner usage.\n     *\n     * @usage\n     * var result = findComponents(\n     *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}\n     * );\n     * var result = findComponents(\n     *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}\n     * );\n     * var result = findComponents(\n     *     {mainType: 'series',\n     *     filter: function (model, index) {...}}\n     * );\n     * // result like [component0, componnet1, ...]\n     *\n     * @param {Object} condition\n     * @param {string} condition.mainType Mandatory.\n     * @param {string} [condition.subType] Optional.\n     * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName},\n     *        where xxx is mainType.\n     *        If query attribute is null/undefined or has no index/id/name,\n     *        do not filtering by query conditions, which is convenient for\n     *        no-payload situations or when target of action is global.\n     * @param {Function} [condition.filter] parameter: component, return boolean.\n     * @return {Array.<module:echarts/model/Component>}\n     */findComponents:function findComponents(condition){var query=condition.query;var mainType=condition.mainType;var queryCond=getQueryCond(query);var result=queryCond?this.queryComponents(queryCond):this._componentsMap.get(mainType);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,// subType will be filtered finally.\nindex:q[indexAttr],id:q[idAttr],name:q[nameAttr]}:null;}function doFilter(res){return condition.filter?filter(res,condition.filter):res;}},/**\n     * @usage\n     * eachComponent('legend', function (legendModel, index) {\n     *     ...\n     * });\n     * eachComponent(function (componentType, model, index) {\n     *     // componentType does not include subType\n     *     // (componentType is 'xxx' but not 'xxx.aa')\n     * });\n     * eachComponent(\n     *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}},\n     *     function (model, index) {...}\n     * );\n     * eachComponent(\n     *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}},\n     *     function (model, index) {...}\n     * );\n     *\n     * @param {string|Object=} mainType When mainType is object, the definition\n     *                                  is the same as the method 'findComponents'.\n     * @param {Function} cb\n     * @param {*} context\n     */eachComponent:function eachComponent(mainType,cb,context){var componentsMap=this._componentsMap;if(typeof mainType==='function'){context=cb;cb=mainType;componentsMap.each(function(components,componentType){each$1(components,function(component,index){cb.call(context,componentType,component,index);});});}else if(isString(mainType)){each$1(componentsMap.get(mainType),cb,context);}else if(isObject$1(mainType)){var queryResult=this.findComponents(mainType);each$1(queryResult,cb,context);}},/**\n     * @param {string} name\n     * @return {Array.<module:echarts/model/Series>}\n     */getSeriesByName:function getSeriesByName(name){var series=this._componentsMap.get('series');return filter(series,function(oneSeries){return oneSeries.name===name;});},/**\n     * @param {number} seriesIndex\n     * @return {module:echarts/model/Series}\n     */getSeriesByIndex:function getSeriesByIndex(seriesIndex){return this._componentsMap.get('series')[seriesIndex];},/**\n     * Get series list before filtered by type.\n     * FIXME: rename to getRawSeriesByType?\n     *\n     * @param {string} subType\n     * @return {Array.<module:echarts/model/Series>}\n     */getSeriesByType:function getSeriesByType(subType){var series=this._componentsMap.get('series');return filter(series,function(oneSeries){return oneSeries.subType===subType;});},/**\n     * @return {Array.<module:echarts/model/Series>}\n     */getSeries:function getSeries(){return this._componentsMap.get('series').slice();},/**\n     * @return {number}\n     */getSeriesCount:function getSeriesCount(){return this._componentsMap.get('series').length;},/**\n     * After filtering, series may be different\n     * frome raw series.\n     *\n     * @param {Function} cb\n     * @param {*} context\n     */eachSeries:function eachSeries(cb,context){assertSeriesInitialized(this);each$1(this._seriesIndices,function(rawSeriesIndex){var series=this._componentsMap.get('series')[rawSeriesIndex];cb.call(context,series,rawSeriesIndex);},this);},/**\n     * Iterate raw series before filtered.\n     *\n     * @param {Function} cb\n     * @param {*} context\n     */eachRawSeries:function eachRawSeries(cb,context){each$1(this._componentsMap.get('series'),cb,context);},/**\n     * After filtering, series may be different.\n     * frome raw series.\n     *\n     * @param {string} subType.\n     * @param {Function} cb\n     * @param {*} context\n     */eachSeriesByType:function eachSeriesByType(subType,cb,context){assertSeriesInitialized(this);each$1(this._seriesIndices,function(rawSeriesIndex){var series=this._componentsMap.get('series')[rawSeriesIndex];if(series.subType===subType){cb.call(context,series,rawSeriesIndex);}},this);},/**\n     * Iterate raw series before filtered of given type.\n     *\n     * @parma {string} subType\n     * @param {Function} cb\n     * @param {*} context\n     */eachRawSeriesByType:function eachRawSeriesByType(subType,cb,context){return each$1(this.getSeriesByType(subType),cb,context);},/**\n     * @param {module:echarts/model/Series} seriesModel\n     */isSeriesFiltered:function isSeriesFiltered(seriesModel){assertSeriesInitialized(this);return this._seriesIndicesMap.get(seriesModel.componentIndex)==null;},/**\n     * @return {Array.<number>}\n     */getCurrentSeriesIndices:function getCurrentSeriesIndices(){return(this._seriesIndices||[]).slice();},/**\n     * @param {Function} cb\n     * @param {*} context\n     */filterSeries:function filterSeries(cb,context){assertSeriesInitialized(this);var filteredSeries=filter(this._componentsMap.get('series'),cb,context);createSeriesIndices(this,filteredSeries);},restoreData:function restoreData(payload){var componentsMap=this._componentsMap;createSeriesIndices(this,componentsMap.get('series'));var componentTypes=[];componentsMap.each(function(components,componentType){componentTypes.push(componentType);});ComponentModel.topologicalTravel(componentTypes,ComponentModel.getAllClassMainTypes(),function(componentType,dependencies){each$1(componentsMap.get(componentType),function(component){(componentType!=='series'||!isNotTargetSeries(component,payload))&&component.restoreData();});});}});function isNotTargetSeries(seriesModel,payload){if(payload){var index=payload.seiresIndex;var id=payload.seriesId;var name=payload.seriesName;return index!=null&&seriesModel.componentIndex!==index||id!=null&&seriesModel.id!==id||name!=null&&seriesModel.name!==name;}}/**\n * @inner\n */function mergeTheme(option,theme){// PENDING\n// NOT use `colorLayer` in theme if option has `color`\nvar notMergeColorLayer=option.color&&!option.colorLayer;each$1(theme,function(themeItem,name){if(name==='colorLayer'&&notMergeColorLayer){return;}// 如果有 component model 则把具体的 merge 逻辑交给该 model 处理\nif(!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 initBase(baseOption){baseOption=baseOption;// Using OPTION_INNER_KEY to mark that this option can not be used outside,\n// i.e. `chart.setOption(chart.getModel().option);` is forbiden.\nthis.option={};this.option[OPTION_INNER_KEY]=1;/**\n     * Init with series: [], in case of calling findSeries method\n     * before series initialized.\n     * @type {Object.<string, Array.<module:echarts/model/Model>>}\n     * @private\n     */this._componentsMap=createHashMap({series:[]});/**\n     * Mapping between filtered series list and raw series list.\n     * key: filtered series indices, value: raw series indices.\n     * @type {Array.<nubmer>}\n     * @private\n     */this._seriesIndices;this._seriesIndicesMap;mergeTheme(baseOption,this._theme.option);// TODO Needs clone when merging to the unexisted property\nmerge(baseOption,globalDefault,false);this.mergeOption(baseOption);}/**\n * @inner\n * @param {Array.<string>|string} types model types\n * @return {Object} key: {string} type, value: {Array.<Object>} models\n */function getComponentsByTypes(componentsMap,types){if(!isArray(types)){types=types?[types]:[];}var ret={};each$1(types,function(type){ret[type]=(componentsMap.get(type)||[]).slice();});return ret;}/**\n * @inner\n */function determineSubType(mainType,newCptOption,existComponent){var subType=newCptOption.type?newCptOption.type:existComponent?existComponent.subType// Use determineSubType only when there is no existComponent.\n:ComponentModel.determineSubType(mainType,newCptOption);// tooltip, markline, markpoint may always has no subType\nreturn subType;}/**\n * @inner\n */function createSeriesIndices(ecModel,seriesModels){ecModel._seriesIndicesMap=createHashMap(ecModel._seriesIndices=map(seriesModels,function(series){return series.componentIndex;})||[]);}/**\n * @inner\n */function filterBySubType(components,condition){// Using hasOwnProperty for restrict. Consider\n// subType is undefined in user payload.\nreturn condition.hasOwnProperty('subType')?filter(components,function(cpt){return cpt.subType===condition.subType;}):components;}/**\n * @inner\n */function assertSeriesInitialized(ecModel){// Components that use _seriesIndices should depends on series component,\n// which make sure that their initialization is after series.\nif(__DEV__){if(!ecModel._seriesIndices){throw new Error('Option should contains series.');}}}mixin(GlobalModel,colorPaletteMixin);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var echartsAPIList=['getDom','getZr','getWidth','getHeight','getDevicePixelRatio','dispatchAction','isDisposed','on','off','getDataURL','getConnectedDataURL','getModel','getOption','getViewOfComponentModel','getViewOfSeriesModel'];// And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js\nfunction ExtensionAPI(chartInstance){each$1(echartsAPIList,function(name){this[name]=bind(chartInstance[name],chartInstance);},this);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var coordinateSystemCreators={};function CoordinateSystemManager(){this._coordinateSystems=[];}CoordinateSystemManager.prototype={constructor:CoordinateSystemManager,create:function create(ecModel,api){var coordinateSystems=[];each$1(coordinateSystemCreators,function(creater,type){var list=creater.create(ecModel,api);coordinateSystems=coordinateSystems.concat(list||[]);});this._coordinateSystems=coordinateSystems;},update:function update(ecModel,api){each$1(this._coordinateSystems,function(coordSys){coordSys.update&&coordSys.update(ecModel,api);});},getCoordinateSystems:function getCoordinateSystems(){return this._coordinateSystems.slice();}};CoordinateSystemManager.register=function(type,coordinateSystemCreator){coordinateSystemCreators[type]=coordinateSystemCreator;};CoordinateSystemManager.get=function(type){return coordinateSystemCreators[type];};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * ECharts option manager\n *\n * @module {echarts/model/OptionManager}\n */var each$4=each$1;var clone$3=_clone;var map$1=map;var merge$1=merge;var QUERY_REG=/^(min|max)?(.+)$/;/**\n * TERM EXPLANATIONS:\n *\n * [option]:\n *\n *     An object that contains definitions of components. For example:\n *     var option = {\n *         title: {...},\n *         legend: {...},\n *         visualMap: {...},\n *         series: [\n *             {data: [...]},\n *             {data: [...]},\n *             ...\n *         ]\n *     };\n *\n * [rawOption]:\n *\n *     An object input to echarts.setOption. 'rawOption' may be an\n *     'option', or may be an object contains multi-options. For example:\n *     var option = {\n *         baseOption: {\n *             title: {...},\n *             legend: {...},\n *             series: [\n *                 {data: [...]},\n *                 {data: [...]},\n *                 ...\n *             ]\n *         },\n *         timeline: {...},\n *         options: [\n *             {title: {...}, series: {data: [...]}},\n *             {title: {...}, series: {data: [...]}},\n *             ...\n *         ],\n *         media: [\n *             {\n *                 query: {maxWidth: 320},\n *                 option: {series: {x: 20}, visualMap: {show: false}}\n *             },\n *             {\n *                 query: {minWidth: 320, maxWidth: 720},\n *                 option: {series: {x: 500}, visualMap: {show: true}}\n *             },\n *             {\n *                 option: {series: {x: 1200}, visualMap: {show: true}}\n *             }\n *         ]\n *     };\n *\n * @alias module:echarts/model/OptionManager\n * @param {module:echarts/ExtensionAPI} api\n */function OptionManager(api){/**\n     * @private\n     * @type {module:echarts/ExtensionAPI}\n     */this._api=api;/**\n     * @private\n     * @type {Array.<number>}\n     */this._timelineOptions=[];/**\n     * @private\n     * @type {Array.<Object>}\n     */this._mediaList=[];/**\n     * @private\n     * @type {Object}\n     */this._mediaDefault;/**\n     * -1, means default.\n     * empty means no media.\n     * @private\n     * @type {Array.<number>}\n     */this._currentMediaIndices=[];/**\n     * @private\n     * @type {Object}\n     */this._optionBackup;/**\n     * @private\n     * @type {Object}\n     */this._newBaseOption;}// timeline.notMerge is not supported in ec3. Firstly there is rearly\n// case that notMerge is needed. Secondly supporting 'notMerge' requires\n// rawOption cloned and backuped when timeline changed, which does no\n// good to performance. What's more, that both timeline and setOption\n// method supply 'notMerge' brings complex and some problems.\n// Consider this case:\n// (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);\n// (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);\nOptionManager.prototype={constructor:OptionManager,/**\n     * @public\n     * @param {Object} rawOption Raw option.\n     * @param {module:echarts/model/Global} ecModel\n     * @param {Array.<Function>} optionPreprocessorFuncs\n     * @return {Object} Init option\n     */setOption:function setOption(rawOption,optionPreprocessorFuncs){if(rawOption){// That set dat primitive is dangerous if user reuse the data when setOption again.\neach$1(normalizeToArray(rawOption.series),function(series){series&&series.data&&isTypedArray(series.data)&&setAsPrimitive(series.data);});}// Caution: some series modify option data, if do not clone,\n// it should ensure that the repeat modify correctly\n// (create a new object when modify itself).\nrawOption=clone$3(rawOption);// FIXME\n// 如果 timeline options 或者 media 中设置了某个属性，而baseOption中没有设置，则进行警告。\nvar oldOptionBackup=this._optionBackup;var newParsedOption=parseRawOption.call(this,rawOption,optionPreprocessorFuncs,!oldOptionBackup);this._newBaseOption=newParsedOption.baseOption;// For setOption at second time (using merge mode);\nif(oldOptionBackup){// Only baseOption can be merged.\nmergeOption(oldOptionBackup.baseOption,newParsedOption.baseOption);// For simplicity, timeline options and media options do not support merge,\n// that is, if you `setOption` twice and both has timeline options, the latter\n// timeline opitons will not be merged to the formers, but just substitude them.\nif(newParsedOption.timelineOptions.length){oldOptionBackup.timelineOptions=newParsedOption.timelineOptions;}if(newParsedOption.mediaList.length){oldOptionBackup.mediaList=newParsedOption.mediaList;}if(newParsedOption.mediaDefault){oldOptionBackup.mediaDefault=newParsedOption.mediaDefault;}}else{this._optionBackup=newParsedOption;}},/**\n     * @param {boolean} isRecreate\n     * @return {Object}\n     */mountOption:function mountOption(isRecreate){var optionBackup=this._optionBackup;// TODO\n// 如果没有reset功能则不clone。\nthis._timelineOptions=map$1(optionBackup.timelineOptions,clone$3);this._mediaList=map$1(optionBackup.mediaList,clone$3);this._mediaDefault=clone$3(optionBackup.mediaDefault);this._currentMediaIndices=[];return clone$3(isRecreate// this._optionBackup.baseOption, which is created at the first `setOption`\n// called, and is merged into every new option by inner method `mergeOption`\n// each time `setOption` called, can be only used in `isRecreate`, because\n// its reliability is under suspicion. In other cases option merge is\n// performed by `model.mergeOption`.\n?optionBackup.baseOption:this._newBaseOption);},/**\n     * @param {module:echarts/model/Global} ecModel\n     * @return {Object}\n     */getTimelineOption:function getTimelineOption(ecModel){var option;var timelineOptions=this._timelineOptions;if(timelineOptions.length){// getTimelineOption can only be called after ecModel inited,\n// so we can get currentIndex from timelineModel.\nvar timelineModel=ecModel.getComponent('timeline');if(timelineModel){option=clone$3(timelineOptions[timelineModel.getCurrentIndex()],true);}}return option;},/**\n     * @param {module:echarts/model/Global} ecModel\n     * @return {Array.<Object>}\n     */getMediaOption:function getMediaOption(ecModel){var ecWidth=this._api.getWidth();var ecHeight=this._api.getHeight();var mediaList=this._mediaList;var mediaDefault=this._mediaDefault;var indices=[];var result=[];// No media defined.\nif(!mediaList.length&&!mediaDefault){return result;}// Multi media may be applied, the latter defined media has higher priority.\nfor(var i=0,len=mediaList.length;i<len;i++){if(applyMediaQuery(mediaList[i].query,ecWidth,ecHeight)){indices.push(i);}}// FIXME\n// 是否mediaDefault应该强制用户设置，否则可能修改不能回归。\nif(!indices.length&&mediaDefault){indices=[-1];}if(indices.length&&!indicesEquals(indices,this._currentMediaIndices)){result=map$1(indices,function(index){return clone$3(index===-1?mediaDefault.option:mediaList[index].option);});}// Otherwise return nothing.\nthis._currentMediaIndices=indices;return result;}};function parseRawOption(rawOption,optionPreprocessorFuncs,isNew){var timelineOptions=[];var mediaList=[];var mediaDefault;var baseOption;// Compatible with ec2.\nvar timelineOpt=rawOption.timeline;if(rawOption.baseOption){baseOption=rawOption.baseOption;}// For timeline\nif(timelineOpt||rawOption.options){baseOption=baseOption||{};timelineOptions=(rawOption.options||[]).slice();}// For media query\nif(rawOption.media){baseOption=baseOption||{};var media=rawOption.media;each$4(media,function(singleMedia){if(singleMedia&&singleMedia.option){if(singleMedia.query){mediaList.push(singleMedia);}else if(!mediaDefault){// Use the first media default.\nmediaDefault=singleMedia;}}});}// For normal option\nif(!baseOption){baseOption=rawOption;}// Set timelineOpt to baseOption in ec3,\n// which is convenient for merge option.\nif(!baseOption.timeline){baseOption.timeline=timelineOpt;}// Preprocess.\neach$4([baseOption].concat(timelineOptions).concat(map(mediaList,function(media){return media.option;})),function(option){each$4(optionPreprocessorFuncs,function(preProcess){preProcess(option,isNew);});});return{baseOption:baseOption,timelineOptions:timelineOptions,mediaDefault:mediaDefault,mediaList:mediaList};}/**\n * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>\n * Support: width, height, aspectRatio\n * Can use max or min as prefix.\n */function applyMediaQuery(query,ecWidth,ecHeight){var realMap={width:ecWidth,height:ecHeight,aspectratio:ecWidth/ecHeight// lowser case for convenientce.\n};var applicatable=true;each$1(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{// Equals\nreturn real===expect;}}function indicesEquals(indices1,indices2){// indices is always order by asc and has only finite number.\nreturn indices1.join(',')===indices2.join(',');}/**\n * Consider case:\n * `chart.setOption(opt1);`\n * Then user do some interaction like dataZoom, dataView changing.\n * `chart.setOption(opt2);`\n * Then user press 'reset button' in toolbox.\n *\n * After doing that all of the interaction effects should be reset, the\n * chart should be the same as the result of invoke\n * `chart.setOption(opt1); chart.setOption(opt2);`.\n *\n * Although it is not able ensure that\n * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to\n * `chart.setOption(merge(opt1, opt2));` exactly,\n * this might be the only simple way to implement that feature.\n *\n * MEMO: We've considered some other approaches:\n * 1. Each model handle its self restoration but not uniform treatment.\n *     (Too complex in logic and error-prone)\n * 2. Use a shadow ecModel. (Performace expensive)\n */function mergeOption(oldOption,newOption){newOption=newOption||{};each$4(newOption,function(newCptOpt,mainType){if(newCptOpt==null){return;}var oldCptOpt=oldOption[mainType];if(!ComponentModel.hasClass(mainType)){oldOption[mainType]=merge$1(oldCptOpt,newCptOpt,true);}else{newCptOpt=normalizeToArray(newCptOpt);oldCptOpt=normalizeToArray(oldCptOpt);var mapResult=mappingToExists(oldCptOpt,newCptOpt);oldOption[mainType]=map$1(mapResult,function(item){return item.option&&item.exist?merge$1(item.exist,item.option,true):item.exist||item.option;});}});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$5=each$1;var isObject$3=isObject$1;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]){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]){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){// Timeline controlStyle has other properties besides normal and emphasis\nif(useExtend){opt[optType].normal=opt[optType].emphasis=null;defaults(opt[optType],normalOpt);}else{opt[optType]=normalOpt;}}if(emphasisOpt){opt.emphasis=opt.emphasis||{};opt.emphasis[optType]=emphasisOpt;}}}function removeEC3NormalStatus(opt){convertNormalEmphasis(opt,'itemStyle');convertNormalEmphasis(opt,'lineStyle');convertNormalEmphasis(opt,'areaStyle');convertNormalEmphasis(opt,'label');convertNormalEmphasis(opt,'labelLine');// treemap\nconvertNormalEmphasis(opt,'upperLabel');// graph\nconvertNormalEmphasis(opt,'edgeLabel');}function compatTextStyle(opt,propName){// Check whether is not object (string\\null\\undefined ...)\nvar labelOptSingle=isObject$3(opt)&&opt[propName];var textStyle=isObject$3(labelOptSingle)&&labelOptSingle.textStyle;if(textStyle){for(var i=0,len=TEXT_STYLE_OPTIONS.length;i<len;i++){var propName=TEXT_STYLE_OPTIONS[i];if(textStyle.hasOwnProperty(propName)){labelOptSingle[propName]=textStyle[propName];}}}}function compatEC3CommonStyles(opt){if(opt){removeEC3NormalStatus(opt);compatTextStyle(opt,'label');opt.emphasis&&compatTextStyle(opt.emphasis,'label');}}function processSeries(seriesOpt){if(!isObject$3(seriesOpt)){return;}compatEC2ItemStyle(seriesOpt);removeEC3NormalStatus(seriesOpt);compatTextStyle(seriesOpt,'label');// treemap\ncompatTextStyle(seriesOpt,'upperLabel');// graph\ncompatTextStyle(seriesOpt,'edgeLabel');if(seriesOpt.emphasis){compatTextStyle(seriesOpt.emphasis,'label');// treemap\ncompatTextStyle(seriesOpt.emphasis,'upperLabel');// graph\ncompatTextStyle(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;// Break with ec3: if `setOption` again, there may be no `type` in option,\n// then the backward compat based on option type will not be performed.\nif(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$1(seriesOpt.categories,function(opt){removeEC3NormalStatus(opt);});}if(data&&!isTypedArray(data)){for(var i=0;i<data.length;i++){compatEC3CommonStyles(data[i]);}}// mark point data\nvar markPoint=seriesOpt.markPoint;if(markPoint&&markPoint.data){var mpData=markPoint.data;for(var i=0;i<mpData.length;i++){compatEC3CommonStyles(mpData[i]);}}// mark line data\nvar 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]);}}}// Series\nif(seriesOpt.type==='gauge'){compatTextStyle(seriesOpt,'axisLabel');compatTextStyle(seriesOpt,'title');compatTextStyle(seriesOpt,'detail');}else if(seriesOpt.type==='treemap'){convertNormalEmphasis(seriesOpt.breadcrumb,'itemStyle');each$1(seriesOpt.levels,function(opt){removeEC3NormalStatus(opt);});}else if(seriesOpt.type==='tree'){removeEC3NormalStatus(seriesOpt.leaves);}// sunburst starts from ec4, so it does not need to compat levels.\n}function toArr(o){return isArray(o)?o:o?[o]:[];}function toObj(o){return(isArray(o)?o[0]:o)||{};}var compatStyle=function compatStyle(option,isTheme){each$5(toArr(option.series),function(seriesOpt){isObject$3(seriesOpt)&&processSeries(seriesOpt);});var axes=['xAxis','yAxis','radiusAxis','angleAxis','singleAxis','parallelAxis','radar'];isTheme&&axes.push('valueAxis','categoryAxis','logAxis','timeAxis');each$5(axes,function(axisName){each$5(toArr(option[axisName]),function(axisOpt){if(axisOpt){compatTextStyle(axisOpt,'axisLabel');compatTextStyle(axisOpt.axisPointer,'label');}});});each$5(toArr(option.parallel),function(parallelOpt){var parallelAxisDefault=parallelOpt&&parallelOpt.parallelAxisDefault;compatTextStyle(parallelAxisDefault,'axisLabel');compatTextStyle(parallelAxisDefault&&parallelAxisDefault.axisPointer,'label');});each$5(toArr(option.calendar),function(calendarOpt){convertNormalEmphasis(calendarOpt,'itemStyle');compatTextStyle(calendarOpt,'dayLabel');compatTextStyle(calendarOpt,'monthLabel');compatTextStyle(calendarOpt,'yearLabel');});// radar.name.textStyle\neach$5(toArr(option.radar),function(radarOpt){compatTextStyle(radarOpt,'name');});each$5(toArr(option.geo),function(geoOpt){if(isObject$3(geoOpt)){compatEC3CommonStyles(geoOpt);each$5(toArr(geoOpt.regions),function(regionObj){compatEC3CommonStyles(regionObj);});}});each$5(toArr(option.timeline),function(timelineOpt){compatEC3CommonStyles(timelineOpt);convertNormalEmphasis(timelineOpt,'label');convertNormalEmphasis(timelineOpt,'itemStyle');convertNormalEmphasis(timelineOpt,'controlStyle',true);var data=timelineOpt.data;isArray(data)&&each$1(data,function(item){if(isObject$1(item)){convertNormalEmphasis(item,'label');convertNormalEmphasis(item,'itemStyle');}});});each$5(toArr(option.toolbox),function(toolboxOpt){convertNormalEmphasis(toolboxOpt,'iconStyle');each$5(toolboxOpt.feature,function(featureOpt){convertNormalEmphasis(featureOpt,'iconStyle');});});compatTextStyle(toObj(option.axisPointer),'label');compatTextStyle(toObj(option.tooltip).axisPointer,'label');};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Compatitable with 2.0\nfunction get(opt,path){path=path.split(',');var obj=opt;for(var i=0;i<path.length;i++){obj=obj&&obj[path[i]];if(obj==null){break;}}return obj;}function set$1(opt,path,val,overwrite){path=path.split(',');var obj=opt;var key;for(var i=0;i<path.length-1;i++){key=path[i];if(obj[key]==null){obj[key]={};}obj=obj[key];}if(overwrite||obj[path[i]]==null){obj[path[i]]=val;}}function compatLayoutProperties(option){each$1(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 backwardCompat=function backwardCompat(option,isTheme){compatStyle(option,isTheme);// Make sure series array for model initialization.\noption.series=normalizeToArray(option.series);each$1(option.series,function(seriesOpt){if(!isObject$1(seriesOpt)){return;}var seriesType=seriesOpt.type;if(seriesType==='line'){if(seriesOpt.clipOverflow!=null){seriesOpt.clip=seriesOpt.clipOverflow;}}else if(seriesType==='pie'||seriesType==='gauge'){if(seriesOpt.clockWise!=null){seriesOpt.clockwise=seriesOpt.clockWise;}}else if(seriesType==='gauge'){var pointerColor=get(seriesOpt,'pointer.color');pointerColor!=null&&set$1(seriesOpt,'itemStyle.color',pointerColor);}compatLayoutProperties(seriesOpt);});// dataRange has changed to visualMap\nif(option.dataRange){option.visualMap=option.dataRange;}each$1(COMPATITABLE_COMPONENTS,function(componentName){var options=option[componentName];if(options){if(!isArray(options)){options=[options];}each$1(options,function(option){compatLayoutProperties(option);});}});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // (1) [Caution]: the logic is correct based on the premises:\n//     data processing stage is blocked in stream.\n//     See <module:echarts/stream/Scheduler#performDataProcessorTasks>\n// (2) Only register once when import repeatly.\n//     Should be executed after series filtered and before stack calculation.\nvar dataStack=function dataStack(ecModel){var stackInfoMap=createHashMap();ecModel.eachSeries(function(seriesModel){var stack=seriesModel.get('stack');// Compatibal: when `stack` is set as '', do not stack.\nif(stack){var stackInfoList=stackInfoMap.get(stack)||stackInfoMap.set(stack,[]);var data=seriesModel.getData();var stackInfo={// Used for calculate axis extent automatically.\nstackResultDimension:data.getCalculationInfo('stackResultDimension'),stackedOverDimension:data.getCalculationInfo('stackedOverDimension'),stackedDimension:data.getCalculationInfo('stackedDimension'),stackedByDimension:data.getCalculationInfo('stackedByDimension'),isStackedByIndex:data.getCalculationInfo('isStackedByIndex'),data:data,seriesModel:seriesModel};// If stacked on axis that do not support data stack.\nif(!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$1(stackInfoList,function(targetStackInfo,idxInStack){var resultVal=[];var resultNaN=[NaN,NaN];var dims=[targetStackInfo.stackResultDimension,targetStackInfo.stackedOverDimension];var targetData=targetStackInfo.data;var isStackedByIndex=targetStackInfo.isStackedByIndex;// Should not write on raw data, because stack series model list changes\n// depending on legend selection.\nvar newData=targetData.map(dims,function(v0,v1,dataIndex){var sum=targetData.get(targetStackInfo.stackedDimension,dataIndex);// Consider `connectNulls` of line area, if value is NaN, stackedOver\n// should also be NaN, to draw a appropriate belt area.\nif(isNaN(sum)){return resultNaN;}var byValue;var stackedDataRawIndex;if(isStackedByIndex){stackedDataRawIndex=targetData.getRawIndex(dataIndex);}else{byValue=targetData.get(targetStackInfo.stackedByDimension,dataIndex);}// If stackOver is NaN, chart view will render point on value start.\nvar stackedOver=NaN;for(var j=idxInStack-1;j>=0;j--){var stackInfo=stackInfoList[j];// Has been optimized by inverted indices on `stackedByDimension`.\nif(!isStackedByIndex){stackedDataRawIndex=stackInfo.data.rawIndexOf(stackInfo.stackedByDimension,byValue);}if(stackedDataRawIndex>=0){var val=stackInfo.data.getByRawIndex(stackInfo.stackResultDimension,stackedDataRawIndex);// Considering positive stack, negative stack and empty data\nif(sum>=0&&val>0||// Positive stack\nsum<=0&&val<0// Negative stack\n){sum+=val;stackedOver=val;break;}}}resultVal[0]=sum;resultVal[1]=stackedOver;return resultVal;});targetData.hostModel.setData(newData);// Update for consequent calculation\ntargetStackInfo.data=newData;});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // TODO\n// ??? refactor? check the outer usage of data provider.\n// merge with defaultDimValueGetter?\n/**\n * If normal array used, mutable chunk size is supported.\n * If typed array used, chunk size must be fixed.\n */function DefaultDataProvider(source,dimSize){if(!Source.isInstance(source)){source=Source.seriesDataToSource(source);}this._source=source;var data=this._data=source.data;var sourceFormat=source.sourceFormat;// Typed array. TODO IE10+?\nif(sourceFormat===SOURCE_FORMAT_TYPED_ARRAY){if(__DEV__){if(dimSize==null){throw new Error('Typed array data must specify dimension size');}}this._offset=0;this._dimSize=dimSize;this._data=data;}var methods=providerMethods[sourceFormat===SOURCE_FORMAT_ARRAY_ROWS?sourceFormat+'_'+source.seriesLayoutBy:sourceFormat];if(__DEV__){assert$1(methods,'Invalide sourceFormat: '+sourceFormat);}extend(this,methods);}var providerProto=DefaultDataProvider.prototype;// If data is pure without style configuration\nproviderProto.pure=false;// If data is persistent and will not be released after use.\nproviderProto.persistent=true;// ???! FIXME legacy data provider do not has method getSource\nproviderProto.getSource=function(){return this._source;};var providerMethods={'arrayRows_column':{pure:true,count:function count(){return Math.max(0,this._data.length-this._source.startIndex);},getItem:function getItem(idx){return this._data[idx+this._source.startIndex];},appendData:appendDataSimply},'arrayRows_row':{pure:true,count:function count(){var row=this._data[0];return row?Math.max(0,row.length-this._source.startIndex):0;},getItem:function getItem(idx){idx+=this._source.startIndex;var item=[];var data=this._data;for(var i=0;i<data.length;i++){var row=data[i];item.push(row?row[idx]:null);}return item;},appendData:function appendData(){throw new Error('Do not support appendData when set seriesLayoutBy: \"row\".');}},'objectRows':{pure:true,count:countSimply,getItem:getItemSimply,appendData:appendDataSimply},'keyedColumns':{pure:true,count:function count(){var dimName=this._source.dimensionsDefine[0].name;var col=this._data[dimName];return col?col.length:0;},getItem:function getItem(idx){var item=[];var dims=this._source.dimensionsDefine;for(var i=0;i<dims.length;i++){var col=this._data[dims[i].name];item.push(col?col[idx]:null);}return item;},appendData:function appendData(newData){var data=this._data;each$1(newData,function(newCol,key){var oldCol=data[key]||(data[key]=[]);for(var i=0;i<(newCol||[]).length;i++){oldCol.push(newCol[i]);}});}},'original':{count:countSimply,getItem:getItemSimply,appendData:appendDataSimply},'typedArray':{persistent:false,pure:true,count:function count(){return this._data?this._data.length/this._dimSize:0;},getItem:function getItem(idx,out){idx=idx-this._offset;out=out||[];var offset=this._dimSize*idx;for(var i=0;i<this._dimSize;i++){out[i]=this._data[offset+i];}return out;},appendData:function appendData(newData){if(__DEV__){assert$1(isTypedArray(newData),'Added data must be TypedArray if data in initialization is TypedArray');}this._data=newData;},// Clean self if data is already used.\nclean:function clean(){// PENDING\nthis._offset+=this.count();this._data=null;}}};function countSimply(){return this._data.length;}function getItemSimply(idx){return this._data[idx];}function appendDataSimply(newData){for(var i=0;i<newData.length;i++){this._data.push(newData[i]);}}var rawValueGetters={arrayRows:getRawValueSimply,objectRows:function objectRows(dataItem,dataIndex,dimIndex,dimName){return dimIndex!=null?dataItem[dimName]:dataItem;},keyedColumns:getRawValueSimply,original:function original(dataItem,dataIndex,dimIndex,dimName){// FIXME\n// In some case (markpoint in geo (geo-map.html)), dataItem\n// is {coord: [...]}\nvar value=getDataItemValue(dataItem);return dimIndex==null||!(value instanceof Array)?value:value[dimIndex];},typedArray:getRawValueSimply};function getRawValueSimply(dataItem,dataIndex,dimIndex,dimName){return dimIndex!=null?dataItem[dimIndex]:dataItem;}var defaultDimValueGetters={arrayRows:getDimValueSimply,objectRows:function objectRows(dataItem,dimName,dataIndex,dimIndex){return converDataValue(dataItem[dimName],this._dimensionInfos[dimName]);},keyedColumns:getDimValueSimply,original:function original(dataItem,dimName,dataIndex,dimIndex){// Performance sensitive, do not use modelUtil.getDataItemValue.\n// If dataItem is an plain object with no value field, the var `value`\n// will be assigned with the object, but it will be tread correctly\n// in the `convertDataValue`.\nvar value=dataItem&&(dataItem.value==null?dataItem:dataItem.value);// If any dataItem is like { value: 10 }\nif(!this._rawData.pure&&isDataItemOption(dataItem)){this.hasItemOption=true;}return converDataValue(value instanceof Array?value[dimIndex]// If value is a single number or something else not array.\n:value,this._dimensionInfos[dimName]);},typedArray:function typedArray(dataItem,dimName,dataIndex,dimIndex){return dataItem[dimIndex];}};function getDimValueSimply(dataItem,dimName,dataIndex,dimIndex){return converDataValue(dataItem[dimIndex],this._dimensionInfos[dimName]);}/**\n * This helper method convert value in data.\n * @param {string|number|Date} value\n * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'.\n *        If \"dimInfo.ordinalParseAndSave\", ordinal value can be parsed.\n */function converDataValue(value,dimInfo){// Performance sensitive.\nvar dimType=dimInfo&&dimInfo.type;if(dimType==='ordinal'){// If given value is a category string\nvar ordinalMeta=dimInfo&&dimInfo.ordinalMeta;return ordinalMeta?ordinalMeta.parseAndCollect(value):value;}if(dimType==='time'// spead up when using timestamp\n&&typeof value!=='number'&&value!=null&&value!=='-'){value=+parseDate(value);}// dimType defaults 'number'.\n// If dimType is not ordinal and value is null or undefined or NaN or '-',\n// parse to NaN.\nreturn value==null||value===''?NaN// If string (like '-'), using '+' parse to NaN\n// If object, also parse to NaN\n:+value;}// ??? FIXME can these logic be more neat: getRawValue, getRawDataItem,\n// Consider persistent.\n// Caution: why use raw value to display on label or tooltip?\n// A reason is to avoid format. For example time value we do not know\n// how to format is expected. More over, if stack is used, calculated\n// value may be 0.91000000001, which have brings trouble to display.\n// TODO: consider how to treat null/undefined/NaN when display?\n/**\n * @param {module:echarts/data/List} data\n * @param {number} dataIndex\n * @param {string|number} [dim] dimName or dimIndex\n * @return {Array.<number>|string|number} can be null/undefined.\n */function retrieveRawValue(data,dataIndex,dim){if(!data){return;}// Consider data may be not persistent.\nvar 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 rawValueGetters[sourceFormat](dataItem,dataIndex,dimIndex,dimName);}/**\n * Compatible with some cases (in pie, map) like:\n * data: [{name: 'xx', value: 5, selected: true}, ...]\n * where only sourceFormat is 'original' and 'objectRows' supported.\n *\n * ??? TODO\n * Supported detail options in data item when using 'arrayRows'.\n *\n * @param {module:echarts/data/List} data\n * @param {number} dataIndex\n * @param {string} attr like 'selected'\n */function retrieveRawAttr(data,dataIndex,attr){if(!data){return;}var sourceFormat=data.getProvider().getSource().sourceFormat;if(sourceFormat!==SOURCE_FORMAT_ORIGINAL&&sourceFormat!==SOURCE_FORMAT_OBJECT_ROWS){return;}var dataItem=data.getRawDataItem(dataIndex);if(sourceFormat===SOURCE_FORMAT_ORIGINAL&&!isObject$1(dataItem)){dataItem=null;}if(dataItem){return dataItem[attr];}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var DIMENSION_LABEL_REG=/\\{@(.+?)\\}/g;// PENDING A little ugly\nvar dataFormatMixin={/**\n     * Get params for formatter\n     * @param {number} dataIndex\n     * @param {string} [dataType]\n     * @return {Object}\n     */getDataParams:function getDataParams(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 color=data.getItemVisual(dataIndex,'color');var borderColor=data.getItemVisual(dataIndex,'borderColor');var tooltipModel=this.ecModel.getComponent('tooltip');var renderModeOption=tooltipModel&&tooltipModel.get('renderMode');var renderMode=getTooltipRenderMode(renderModeOption);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,marker:getTooltipMarker({color:color,renderMode:renderMode}),// Param name list for mapping `a`, `b`, `c`, `d`, `e`\n$vars:['seriesName','name','value']};},/**\n     * Format label\n     * @param {number} dataIndex\n     * @param {string} [status='normal'] 'normal' or 'emphasis'\n     * @param {string} [dataType]\n     * @param {number} [dimIndex] Only used in some chart that\n     *        use formatter in different dimensions, like radar.\n     * @param {string} [labelProp='label']\n     * @return {string} If not formatter, return null/undefined\n     */getFormattedLabel:function getFormattedLabel(dataIndex,status,dataType,dimIndex,labelProp){status=status||'normal';var data=this.getData(dataType);var itemModel=data.getItemModel(dataIndex);var params=this.getDataParams(dataIndex,dataType);if(dimIndex!=null&&params.value instanceof Array){params.value=params.value[dimIndex];}var formatter=itemModel.get(status==='normal'?[labelProp||'label','formatter']:[status,labelProp||'label','formatter']);if(typeof formatter==='function'){params.status=status;params.dimensionIndex=dimIndex;return formatter(params);}else if(typeof formatter==='string'){var str=formatTpl(formatter,params);// Support 'aaa{@[3]}bbb{@product}ccc'.\n// Do not support '}' in dim name util have to.\nreturn 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);// Also: '[]' => 0\n}return retrieveRawValue(data,dataIndex,dim);});}},/**\n     * Get raw value in option\n     * @param {number} idx\n     * @param {string} [dataType]\n     * @return {Array|number|string}\n     */getRawValue:function getRawValue(idx,dataType){return retrieveRawValue(this.getData(dataType),idx);},/**\n     * Should be implemented.\n     * @param {number} dataIndex\n     * @param {boolean} [multipleSeries=false]\n     * @param {number} [dataType]\n     * @return {string} tooltip string\n     */formatTooltip:function formatTooltip(){// Empty function\n}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {Object} define\n * @return See the return of `createTask`.\n */function createTask(define){return new Task(define);}/**\n * @constructor\n * @param {Object} define\n * @param {Function} define.reset Custom reset\n * @param {Function} [define.plan] Returns 'reset' indicate reset immediately.\n * @param {Function} [define.count] count is used to determin data task.\n * @param {Function} [define.onDirty] count is used to determin data task.\n */function Task(define){define=define||{};this._reset=define.reset;this._plan=define.plan;this._count=define.count;this._onDirty=define.onDirty;this._dirty=true;// Context must be specified implicitly, to\n// avoid miss update context when model changed.\nthis.context;}var taskProto=Task.prototype;/**\n * @param {Object} performArgs\n * @param {number} [performArgs.step] Specified step.\n * @param {number} [performArgs.skip] Skip customer perform call.\n * @param {number} [performArgs.modBy] Sampling window size.\n * @param {number} [performArgs.modDataCount] Sampling count.\n */taskProto.perform=function(performArgs){var upTask=this._upstream;var skip=performArgs&&performArgs.skip;// TODO some refactor.\n// Pull data. Must pull data each time, because context.data\n// may be updated by Series.setData.\nif(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);}// Support sharding by mod, which changes the render sequence and makes the rendered graphic\n// elements uniformed distributed when progress, especially when moving or zooming.\nvar 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);// jshint ignore:line\nreturn val;}var forceFirstProgress;if(this._dirty||planResult==='reset'){this._dirty=false;forceFirstProgress=reset(this,skip);}this._modBy=modBy;this._modDataCount=modDataCount;var step=performArgs&&performArgs.step;if(upTask){if(__DEV__){assert$1(upTask._outputDueEnd!=null);}this._dueEnd=upTask._outputDueEnd;}// DataTask or overallTask\nelse{if(__DEV__){assert$1(!this._progress||this._count);}this._dueEnd=this._count?this._count(this.context):Infinity;}// Note: Stubs, that its host overall task let it has progress, has progress.\n// If no progress, pass index from upstream to downstream each time plan called.\nif(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++){doProgress(this,progress[i],start,end,modBy,modDataCount);}}else{doProgress(this,progress,start,end,modBy,modDataCount);}}this._dueIndex=end;// If no `outputDueEnd`, assume that output data and\n// input data is the same, so use `dueIndex` as `outputDueEnd`.\nvar outputDueEnd=this._settedOutputEnd!=null?this._settedOutputEnd:end;if(__DEV__){// ??? Can not rollback.\nassert$1(outputDueEnd>=this._outputDueEnd);}this._outputDueEnd=outputDueEnd;}else{// (1) Some overall task has no progress.\n// (2) Stubs, that its host overall task do not let it has progress, has no progress.\n// This should always be performed so it can be passed to downstream.\nthis._dueIndex=this._outputDueEnd=this._settedOutputEnd!=null?this._settedOutputEnd:this._dueEnd;}return this.unfinished();};var iterator=function(){var end;var current;var modBy;var modDataCount;var winCount;var it={reset:function reset(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// If modDataCount is smaller than data.count() (consider `appendData` case),\n// Use normal linear rendering mode.\n:current;current++;return result;}}();taskProto.dirty=function(){this._dirty=true;this._onDirty&&this._onDirty(this.context);};function doProgress(taskIns,progress,start,end,modBy,modDataCount){iterator.reset(start,end,modBy,modDataCount);taskIns._callingProgress=progress;taskIns._callingProgress({start:start,end:end,count:end-start,next:iterator.next},taskIns.context);}function reset(taskIns,skip){taskIns._dueIndex=taskIns._outputDueEnd=taskIns._dueEnd=0;taskIns._settedOutputEnd=null;var progress;var forceFirstProgress;if(!skip&&taskIns._reset){progress=taskIns._reset(taskIns.context);if(progress&&progress.progress){forceFirstProgress=progress.forceFirstProgress;progress=progress.progress;}// To simplify no progress checking, array must has item.\nif(isArray(progress)&&!progress.length){progress=null;}}taskIns._progress=progress;taskIns._modBy=taskIns._modDataCount=null;var downstream=taskIns._downstream;downstream&&downstream.dirty();return forceFirstProgress;}/**\n * @return {boolean}\n */taskProto.unfinished=function(){return this._progress&&this._dueIndex<this._dueEnd;};/**\n * @param {Object} downTask The downstream task.\n * @return {Object} The downstream task.\n */taskProto.pipe=function(downTask){if(__DEV__){assert$1(downTask&&!downTask._disposed&&downTask!==this);}// If already downstream, do not dirty downTask.\nif(this._downstream!==downTask||this._dirty){this._downstream=downTask;downTask._upstream=this;downTask.dirty();}};taskProto.dispose=function(){if(this._disposed){return;}this._upstream&&(this._upstream._downstream=null);this._downstream&&(this._downstream._upstream=null);this._dirty=false;this._disposed=true;};taskProto.getUpstream=function(){return this._upstream;};taskProto.getDownstream=function(){return this._downstream;};taskProto.setOutputEnd=function(end){// This only happend in dataTask, dataZoom, map, currently.\n// where dataZoom do not set end each time, but only set\n// when reset. So we should record the setted end, in case\n// that the stub of dataZoom perform again and earse the\n// setted end by upstream.\nthis._outputDueEnd=this._settedOutputEnd=end;};///////////////////////////////////////////////////////////\n// For stream debug (Should be commented out after used!)\n// Usage: printTask(this, 'begin');\n// Usage: printTask(this, null, {someExtraProp});\n// function printTask(task, prefix, extra) {\n//     window.ecTaskUID == null && (window.ecTaskUID = 0);\n//     task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);\n//     task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);\n//     var props = [];\n//     if (task.__pipeline) {\n//         var val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;\n//         props.push({text: 'idx', value: val});\n//     } else {\n//         var stubCount = 0;\n//         task.agentStubMap.each(() => stubCount++);\n//         props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});\n//     }\n//     props.push({text: 'uid', value: task.uidDebug});\n//     if (task.__pipeline) {\n//         props.push({text: 'pid', value: task.__pipeline.id});\n//         task.agent && props.push(\n//             {text: 'stubFor', value: task.agent.uidDebug}\n//         );\n//     }\n//     props.push(\n//         {text: 'dirty', value: task._dirty},\n//         {text: 'dueIndex', value: task._dueIndex},\n//         {text: 'dueEnd', value: task._dueEnd},\n//         {text: 'outputDueEnd', value: task._outputDueEnd}\n//     );\n//     if (extra) {\n//         Object.keys(extra).forEach(key => {\n//             props.push({text: key, value: extra[key]});\n//         });\n//     }\n//     var args = ['color: blue'];\n//     var msg = `%c[${prefix || 'T'}] %c` + props.map(item => (\n//         args.push('color: black', 'color: red'),\n//         `${item.text}: %c${item.value}`\n//     )).join('%c, ');\n//     console.log.apply(console, [msg].concat(args));\n//     // console.log(this);\n// }\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$4=makeInner();var SeriesModel=ComponentModel.extend({type:'series.__base__',/**\n     * @readOnly\n     */seriesIndex:0,// coodinateSystem will be injected in the echarts/CoordinateSystem\ncoordinateSystem:null,/**\n     * @type {Object}\n     * @protected\n     */defaultOption:null,/**\n     * legend visual provider to the legend component\n     * @type {Object}\n     */ // PENDING\nlegendVisualProvider:null,/**\n     * Access path of color for visual\n     */visualColorAccessPath:'itemStyle.color',/**\n     * Access path of borderColor for visual\n     */visualBorderColorAccessPath:'itemStyle.borderColor',/**\n     * Support merge layout params.\n     * Only support 'box' now (left/right/top/bottom/width/height).\n     * @type {string|Object} Object can be {ignoreSize: true}\n     * @readOnly\n     */layoutMode:null,init:function init(option,parentModel,ecModel,extraOpt){/**\n         * @type {number}\n         * @readOnly\n         */this.seriesIndex=this.componentIndex;this.dataTask=createTask({count:dataTaskCount,reset:dataTaskReset});this.dataTask.context={model:this};this.mergeDefaultAndTheme(option,ecModel);prepareSource(this);var data=this.getInitialData(option,ecModel);wrapData(data,this);this.dataTask.context.data=data;if(__DEV__){assert$1(data,'getInitialData returned invalid data.');}/**\n         * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}\n         * @private\n         */inner$4(this).dataBeforeProcessed=data;// If we reverse the order (make data firstly, and then make\n// dataBeforeProcessed by cloneShallow), cloneShallow will\n// cause data.graph.data !== data when using\n// module:echarts/data/Graph or module:echarts/data/Tree.\n// See module:echarts/data/helper/linkList\n// Theoretically, it is unreasonable to call `seriesModel.getData()` in the model\n// init or merge stage, because the data can be restored. So we do not `restoreData`\n// and `setData` here, which forbids calling `seriesModel.getData()` in this stage.\n// Call `seriesModel.getRawData()` instead.\n// this.restoreData();\nautoSeriesName(this);},/**\n     * Util for merge default and theme to option\n     * @param  {Object} option\n     * @param  {module:echarts/model/Global} ecModel\n     */mergeDefaultAndTheme:function mergeDefaultAndTheme(option,ecModel){var layoutMode=this.layoutMode;var inputPositionParams=layoutMode?getLayoutParams(option):{};// Backward compat: using subType on theme.\n// But if name duplicate between series subType\n// (for example: parallel) add component mainType,\n// add suffix 'Series'.\nvar themeSubType=this.subType;if(ComponentModel.hasClass(themeSubType)){themeSubType+='Series';}merge(option,ecModel.getTheme().get(this.subType));merge(option,this.getDefaultOption());// Default label emphasis `show`\ndefaultEmphasis(option,'label',['show']);this.fillDataTextStyle(option.data);if(layoutMode){mergeLayoutParam(option,inputPositionParams,layoutMode);}},mergeOption:function mergeOption(newSeriesOption,ecModel){// this.settingTask.dirty();\nnewSeriesOption=merge(this.option,newSeriesOption,true);this.fillDataTextStyle(newSeriesOption.data);var layoutMode=this.layoutMode;if(layoutMode){mergeLayoutParam(this.option,newSeriesOption,layoutMode);}prepareSource(this);var data=this.getInitialData(newSeriesOption,ecModel);wrapData(data,this);this.dataTask.dirty();this.dataTask.context.data=data;inner$4(this).dataBeforeProcessed=data;autoSeriesName(this);},fillDataTextStyle:function fillDataTextStyle(data){// Default data label emphasis `show`\n// FIXME Tree structure data ?\n// FIXME Performance ?\nif(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);}}}},/**\n     * Init a data structure from data related option in series\n     * Must be overwritten\n     */getInitialData:function getInitialData(){},/**\n     * Append data to list\n     * @param {Object} params\n     * @param {Array|TypedArray} params.data\n     */appendData:function appendData(params){// FIXME ???\n// (1) If data from dataset, forbidden append.\n// (2) support append data of dataset.\nvar data=this.getRawData();data.appendData(params.data);},/**\n     * Consider some method like `filter`, `map` need make new data,\n     * We should make sure that `seriesModel.getData()` get correct\n     * data in the stream procedure. So we fetch data from upstream\n     * each time `task.perform` called.\n     * @param {string} [dataType]\n     * @return {module:echarts/data/List}\n     */getData:function getData(dataType){var task=getCurrentTask(this);if(task){var data=task.context.data;return dataType==null?data:data.getLinkedData(dataType);}else{// When series is not alive (that may happen when click toolbox\n// restore or setOption with not merge mode), series data may\n// be still need to judge animation or something when graphic\n// elements want to know whether fade out.\nreturn inner$4(this).data;}},/**\n     * @param {module:echarts/data/List} data\n     */setData:function setData(data){var task=getCurrentTask(this);if(task){var context=task.context;// Consider case: filter, data sample.\nif(context.data!==data&&task.modifyOutputEnd){task.setOutputEnd(data.count());}context.outputData=data;// Caution: setData should update context.data,\n// Because getData may be called multiply in a\n// single stage and expect to get the data just\n// set. (For example, AxisProxy, x y both call\n// getData and setDate sequentially).\n// So the context.data should be fetched from\n// upstream each time when a stage starts to be\n// performed.\nif(task!==this.dataTask){context.data=data;}}inner$4(this).data=data;},/**\n     * @see {module:echarts/data/helper/sourceHelper#getSource}\n     * @return {module:echarts/data/Source} source\n     */getSource:function getSource(){return _getSource(this);},/**\n     * Get data before processed\n     * @return {module:echarts/data/List}\n     */getRawData:function getRawData(){return inner$4(this).dataBeforeProcessed;},/**\n     * Get base axis if has coordinate system and has axis.\n     * By default use coordSys.getBaseAxis();\n     * Can be overrided for some chart.\n     * @return {type} description\n     */getBaseAxis:function getBaseAxis(){var coordSys=this.coordinateSystem;return coordSys&&coordSys.getBaseAxis&&coordSys.getBaseAxis();},// FIXME\n/**\n     * Default tooltip formatter\n     *\n     * @param {number} dataIndex\n     * @param {boolean} [multipleSeries=false]\n     * @param {number} [dataType]\n     * @param {string} [renderMode='html'] valid values: 'html' and 'richText'.\n     *                                     'html' is used for rendering tooltip in extra DOM form, and the result\n     *                                     string is used as DOM HTML content.\n     *                                     'richText' is used for rendering tooltip in rich text form, for those where\n     *                                     DOM operation is not supported.\n     * @return {Object} formatted tooltip with `html` and `markers`\n     */formatTooltip:function formatTooltip(dataIndex,multipleSeries,dataType,renderMode){var series=this;renderMode=renderMode||'html';var newLine=renderMode==='html'?'<br/>':'\\n';var isRichText=renderMode==='richText';var markers={};var markerId=0;function formatArrayValue(value){// ??? TODO refactor these logic.\n// check: category-no-encode-has-axis-data in dataset.html\nvar vertially=reduce(value,function(vertially,val,idx){var dimItem=data.getDimensionInfo(idx);return vertially|=dimItem&&dimItem.tooltip!==false&&dimItem.displayName!=null;},0);var result=[];tooltipDims.length?each$1(tooltipDims,function(dim){setEachItem(retrieveRawValue(data,dataIndex,dim),dim);})// By default, all dims is used on tooltip.\n:each$1(value,setEachItem);function setEachItem(val,dim){var dimInfo=data.getDimensionInfo(dim);// If `dimInfo.tooltip` is not set, show tooltip.\nif(!dimInfo||dimInfo.otherDims.tooltip===false){return;}var dimType=dimInfo.type;var markName='sub'+series.seriesIndex+'at'+markerId;var dimHead=getTooltipMarker({color:color,type:'subItem',renderMode:renderMode,markerId:markName});var dimHeadStr=typeof dimHead==='string'?dimHead:dimHead.content;var valStr=(vertially?dimHeadStr+encodeHTML(dimInfo.displayName||'-')+': ':'')+// FIXME should not format time for raw data?\nencodeHTML(dimType==='ordinal'?val+'':dimType==='time'?multipleSeries?'':formatTime('yyyy/MM/dd hh:mm:ss',val):addCommas(val));valStr&&result.push(valStr);if(isRichText){markers[markName]=color;++markerId;}}var newLine=vertially?isRichText?'\\n':'<br/>':'';var content=newLine+result.join(newLine||', ');return{renderMode:renderMode,content:content,style:markers};}function formatSingleValue(val){// return encodeHTML(addCommas(val));\nreturn{renderMode:renderMode,content:encodeHTML(addCommas(val)),style:markers};}var data=this.getData();var tooltipDims=data.mapDimension('defaultedTooltip',true);var tooltipDimLen=tooltipDims.length;var value=this.getRawValue(dataIndex);var isValueArr=isArray(value);var color=data.getItemVisual(dataIndex,'color');if(isObject$1(color)&&color.colorStops){color=(color.colorStops[0]||{}).color;}color=color||'transparent';// Complicated rule for pretty tooltip.\nvar formattedValue=tooltipDimLen>1||isValueArr&&!tooltipDimLen?formatArrayValue(value):tooltipDimLen?formatSingleValue(retrieveRawValue(data,dataIndex,tooltipDims[0])):formatSingleValue(isValueArr?value[0]:value);var content=formattedValue.content;var markName=series.seriesIndex+'at'+markerId;var colorEl=getTooltipMarker({color:color,type:'item',renderMode:renderMode,markerId:markName});markers[markName]=color;++markerId;var name=data.getName(dataIndex);var seriesName=this.name;if(!isNameSpecified(this)){seriesName='';}seriesName=seriesName?encodeHTML(seriesName)+(!multipleSeries?newLine:': '):'';var colorStr=typeof colorEl==='string'?colorEl:colorEl.content;var html=!multipleSeries?seriesName+colorStr+(name?encodeHTML(name)+': '+content:content):colorStr+seriesName+content;return{html:html,markers:markers};},/**\n     * @return {boolean}\n     */isAnimationEnabled:function isAnimationEnabled(){if(env$1.node){return false;}var animationEnabled=this.getShallow('animation');if(animationEnabled){if(this.getData().count()>this.getShallow('animationThreshold')){animationEnabled=false;}}return animationEnabled;},restoreData:function restoreData(){this.dataTask.dirty();},getColorFromPalette:function getColorFromPalette(name,scope,requestColorNum){var ecModel=this.ecModel;// PENDING\nvar color=colorPaletteMixin.getColorFromPalette.call(this,name,scope,requestColorNum);if(!color){color=ecModel.getColorFromPalette(name,scope,requestColorNum);}return color;},/**\n     * Use `data.mapDimension(coordDim, true)` instead.\n     * @deprecated\n     */coordDimToDataDim:function coordDimToDataDim(coordDim){return this.getRawData().mapDimension(coordDim,true);},/**\n     * Get progressive rendering count each step\n     * @return {number}\n     */getProgressive:function getProgressive(){return this.get('progressive');},/**\n     * Get progressive rendering count each step\n     * @return {number}\n     */getProgressiveThreshold:function getProgressiveThreshold(){return this.get('progressiveThreshold');},/**\n     * Get data indices for show tooltip content. See tooltip.\n     * @abstract\n     * @param {Array.<string>|string} dim\n     * @param {Array.<number>} value\n     * @param {module:echarts/coord/single/SingleAxis} baseAxis\n     * @return {Object} {dataIndices, nestestValue}.\n     */getAxisTooltipData:null,/**\n     * See tooltip.\n     * @abstract\n     * @param {number} dataIndex\n     * @return {Array.<number>} Point of tooltip. null/undefined can be returned.\n     */getTooltipPosition:null,/**\n     * @see {module:echarts/stream/Scheduler}\n     */pipeTask:null,/**\n     * Convinient for override in extended class.\n     * @protected\n     * @type {Function}\n     */preventIncremental:null,/**\n     * @public\n     * @readOnly\n     * @type {Object}\n     */pipelineContext:null});mixin(SeriesModel,dataFormatMixin);mixin(SeriesModel,colorPaletteMixin);/**\n * MUST be called after `prepareSource` called\n * Here we need to make auto series, especially for auto legend. But we\n * do not modify series.name in option to avoid side effects.\n */function autoSeriesName(seriesModel){// User specified name has higher priority, otherwise it may cause\n// series can not be queried unexpectedly.\nvar name=seriesModel.name;if(!isNameSpecified(seriesModel)){seriesModel.name=getSeriesAutoName(seriesModel)||name;}}function getSeriesAutoName(seriesModel){var data=seriesModel.getRawData();var dataDims=data.mapDimension('seriesName',true);var nameArr=[];each$1(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){// Avoid repead cloneShallow when data just created in reset.\nif(context.outputData&&param.end>context.outputData.count()){context.model.getRawData().cloneShallow(context.outputData);}}// TODO refactor\nfunction wrapData(data,seriesModel){each$1(data.CHANGABLE_METHODS,function(methodName){data.wrapMethod(methodName,curry(onDataSelfChange,seriesModel));});}function onDataSelfChange(seriesModel){var task=getCurrentTask(seriesModel);if(task){// Consider case: filter, selectRange\ntask.setOutputEnd(this.count());}}function getCurrentTask(seriesModel){var scheduler=(seriesModel.ecModel||{}).scheduler;var pipeline=scheduler&&scheduler.getPipeline(seriesModel.uid);if(pipeline){// When pipline finished, the currrentTask keep the last\n// task (renderTask).\nvar task=pipeline.currentTask;if(task){var agentStubMap=task.agentStubMap;if(agentStubMap){task=agentStubMap.get(seriesModel.uid);}}return task;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var Component$1=function Component$1(){/**\n     * @type {module:zrender/container/Group}\n     * @readOnly\n     */this.group=new Group();/**\n     * @type {string}\n     * @readOnly\n     */this.uid=getUID('viewComponent');};Component$1.prototype={constructor:Component$1,init:function init(ecModel,api){},render:function render(componentModel,ecModel,api,payload){},dispose:function dispose(){},/**\n     * @param {string} eventType\n     * @param {Object} query\n     * @param {module:zrender/Element} targetEl\n     * @param {Object} packedEvent\n     * @return {boolen} Pass only when return `true`.\n     */filterForExposedEvent:null};var componentProto=Component$1.prototype;componentProto.updateView=componentProto.updateLayout=componentProto.updateVisual=function(seriesModel,ecModel,api,payload){// Do nothing;\n};// Enable Component.extend.\nenableClassExtend(Component$1);// Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.\nenableClassManagement(Component$1,{registerWhenExtend:true});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @return {string} If large mode changed, return string 'reset';\n */var createRenderPlanner=function createRenderPlanner(){var inner=makeInner();return function(seriesModel){var fields=inner(seriesModel);var pipelineContext=seriesModel.pipelineContext;var originalLarge=fields.large;var originalProgressive=fields.progressiveRender;// FIXME: if the planner works on a filtered series, `pipelineContext` does not\n// exists. See #11611 . Probably we need to modify this structure, see the comment\n// on `performRawSeries` in `Schedular.js`.\nvar large=fields.large=pipelineContext&&pipelineContext.large;var progressive=fields.progressiveRender=pipelineContext&&pipelineContext.progressiveRender;return!!(originalLarge^large||originalProgressive^progressive)&&'reset';};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$5=makeInner();var renderPlanner=createRenderPlanner();function Chart(){/**\n     * @type {module:zrender/container/Group}\n     * @readOnly\n     */this.group=new Group();/**\n     * @type {string}\n     * @readOnly\n     */this.uid=getUID('viewChart');this.renderTask=createTask({plan:renderTaskPlan,reset:renderTaskReset});this.renderTask.context={view:this};}Chart.prototype={type:'chart',/**\n     * Init the chart.\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     */init:function init(ecModel,api){},/**\n     * Render the chart.\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     */render:function render(seriesModel,ecModel,api,payload){},/**\n     * Highlight series or specified data item.\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     */highlight:function highlight(seriesModel,ecModel,api,payload){toggleHighlight(seriesModel.getData(),payload,'emphasis');},/**\n     * Downplay series or specified data item.\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     */downplay:function downplay(seriesModel,ecModel,api,payload){toggleHighlight(seriesModel.getData(),payload,'normal');},/**\n     * Remove self.\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     */remove:function remove(ecModel,api){this.group.removeAll();},/**\n     * Dispose self.\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     */dispose:function dispose(){},/**\n     * Rendering preparation in progressive mode.\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     */incrementalPrepareRender:null,/**\n     * Render in progressive mode.\n     * @param  {Object} params See taskParams in `stream/task.js`\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     */incrementalRender:null,/**\n     * Update transform directly.\n     * @param  {module:echarts/model/Series} seriesModel\n     * @param  {module:echarts/model/Global} ecModel\n     * @param  {module:echarts/ExtensionAPI} api\n     * @param  {Object} payload\n     * @return {Object} {update: true}\n     */updateTransform:null,/**\n     * The view contains the given point.\n     * @interface\n     * @param {Array.<number>} point\n     * @return {boolean}\n     */ // containPoint: function () {}\n/**\n     * @param {string} eventType\n     * @param {Object} query\n     * @param {module:zrender/Element} targetEl\n     * @param {Object} packedEvent\n     * @return {boolen} Pass only when return `true`.\n     */filterForExposedEvent:null};var chartProto=Chart.prototype;chartProto.updateView=chartProto.updateLayout=chartProto.updateVisual=function(seriesModel,ecModel,api,payload){this.render(seriesModel,ecModel,api,payload);};/**\n * Set state of single element\n * @param {module:zrender/Element} el\n * @param {string} state 'normal'|'emphasis'\n * @param {number} highlightDigit\n */function elSetState(el,state,highlightDigit){if(el){el.trigger(state,highlightDigit);if(el.isGroup// Simple optimize.\n&&!isHighDownDispatcher(el)){for(var i=0,len=el.childCount();i<len;i++){elSetState(el.childAt(i),state,highlightDigit);}}}}/**\n * @param {module:echarts/data/List} data\n * @param {Object} payload\n * @param {string} state 'normal'|'emphasis'\n */function toggleHighlight(data,payload,state){var dataIndex=queryDataIndex(data,payload);var highlightDigit=payload&&payload.highlightKey!=null?getHighlightDigit(payload.highlightKey):null;if(dataIndex!=null){each$1(normalizeToArray(dataIndex),function(dataIdx){elSetState(data.getItemGraphicEl(dataIdx),state,highlightDigit);});}else{data.eachItemGraphicEl(function(el){elSetState(el,state,highlightDigit);});}}// Enable Chart.extend.\nenableClassExtend(Chart,['dispose']);// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.\nenableClassManagement(Chart,{registerWhenExtend:true});Chart.markUpdateMethod=function(payload,methodName){inner$5(payload).updateMethod=methodName;};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;// ???! remove updateView updateVisual\nvar progressiveRender=seriesModel.pipelineContext.progressiveRender;var view=context.view;var updateMethod=payload&&inner$5(payload).updateMethod;var methodName=progressiveRender?'incrementalPrepareRender':updateMethod&&view[updateMethod]?updateMethod// `appendData` is also supported when data amount\n// is less than progressive threshold.\n:'render';if(methodName!=='render'){view[methodName](seriesModel,ecModel,api,payload);}return progressMethodMap[methodName];}var progressMethodMap={incrementalPrepareRender:{progress:function progress(params,context){context.view.incrementalRender(params,context.model,context.ecModel,context.api,context.payload);}},render:{// Put view.render in `progress` to support appendData. But in this case\n// view.render should not be called in reset, otherwise it will be called\n// twise. Use `forceFirstProgress` to make sure that view.render is called\n// in any cases.\nforceFirstProgress:true,progress:function progress(params,context){context.view.render(context.model,context.ecModel,context.api,context.payload);}}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var ORIGIN_METHOD='\\0__throttleOriginMethod';var RATE='\\0__throttleRate';var THROTTLE_TYPE='\\0__throttleType';/**\n * @public\n * @param {(Function)} fn\n * @param {number} [delay=0] Unit: ms.\n * @param {boolean} [debounce=false]\n *        true: If call interval less than `delay`, only the last call works.\n *        false: If call interval less than `delay, call works on fixed rate.\n * @return {(Function)} throttled fn.\n */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 cb(){currCall=new Date().getTime();scope=this;args=arguments;var thisDelay=debounceNextCall||delay;var thisDebounce=debounceNextCall||debounce;debounceNextCall=null;diff=currCall-(thisDebounce?lastCall:lastExec)-thisDelay;clearTimeout(timer);// Here we should make sure that: the `exec` SHOULD NOT be called later\n// than a new call of `cb`, that is, preserving the command order. Consider\n// calculating \"scale rate\" when roaming as an example. When a call of `cb`\n// happens, either the `exec` is called dierectly, or the call is delayed.\n// But the delayed call should never be later than next call of `cb`. Under\n// this assurance, we can simply update view state each time `dispatchAction`\n// triggered by user roaming, but not need to add extra code to avoid the\n// state being \"rolled-back\".\nif(thisDebounce){timer=setTimeout(exec,thisDelay);}else{if(diff>=0){exec();}else{timer=setTimeout(exec,-diff);}}lastCall=currCall;};/**\n     * Clear throttle.\n     * @public\n     */cb.clear=function(){if(timer){clearTimeout(timer);timer=null;}};/**\n     * Enable debounce once.\n     */cb.debounceNextCall=function(debounceDelay){debounceNextCall=debounceDelay;};return cb;}/**\n * Create throttle method or update throttle rate.\n *\n * @example\n * ComponentView.prototype.render = function () {\n *     ...\n *     throttle.createOrUpdate(\n *         this,\n *         '_dispatchAction',\n *         this.model.get('throttle'),\n *         'fixRate'\n *     );\n * };\n * ComponentView.prototype.remove = function () {\n *     throttle.clear(this, '_dispatchAction');\n * };\n * ComponentView.prototype.dispose = function () {\n *     throttle.clear(this, '_dispatchAction');\n * };\n *\n * @public\n * @param {Object} obj\n * @param {string} fnAttr\n * @param {number} [rate]\n * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce'\n * @return {Function} throttled function.\n */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;}/**\n * Clear throttle. Example see throttle.createOrUpdate.\n *\n * @public\n * @param {Object} obj\n * @param {string} fnAttr\n */function clear(obj,fnAttr){var fn=obj[fnAttr];if(fn&&fn[ORIGIN_METHOD]){obj[fnAttr]=fn[ORIGIN_METHOD];}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var seriesColor={createOnAllSeries:true,performRawSeries:true,reset:function reset(seriesModel,ecModel){var data=seriesModel.getData();var colorAccessPath=(seriesModel.visualColorAccessPath||'itemStyle.color').split('.');// Set in itemStyle\nvar color=seriesModel.get(colorAccessPath);var colorCallback=isFunction$1(color)&&!(color instanceof Gradient)?color:null;// Default color\nif(!color||colorCallback){color=seriesModel.getColorFromPalette(// TODO series count changed.\nseriesModel.name,null,ecModel.getSeriesCount());}data.setVisual('color',color);var borderColorAccessPath=(seriesModel.visualBorderColorAccessPath||'itemStyle.borderColor').split('.');var borderColor=seriesModel.get(borderColorAccessPath);data.setVisual('borderColor',borderColor);// Only visible series has each data be visual encoded\nif(!ecModel.isSeriesFiltered(seriesModel)){if(colorCallback){data.each(function(idx){data.setItemVisual(idx,'color',colorCallback(seriesModel.getDataParams(idx)));});}// itemStyle in each data item\nvar dataEach=function dataEach(data,idx){var itemModel=data.getItemModel(idx);var color=itemModel.get(colorAccessPath,true);var borderColor=itemModel.get(borderColorAccessPath,true);if(color!=null){data.setItemVisual(idx,'color',color);}if(borderColor!=null){data.setItemVisual(idx,'borderColor',borderColor);}};return{dataEach:data.hasItemOption?dataEach:null};}}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Language: English.\n */var lang={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:'.'}}}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var aria=function aria(dom,ecModel){var ariaModel=ecModel.getModel('aria');if(!ariaModel.get('show')){return;}else if(ariaModel.get('description')){dom.setAttribute('aria-label',ariaModel.get('description'));return;}var seriesCnt=0;ecModel.eachSeries(function(seriesModel,idx){++seriesCnt;},this);var maxDataCnt=ariaModel.get('data.maxCount')||10;var maxSeriesCnt=ariaModel.get('series.maxCount')||10;var displaySeriesCnt=Math.min(seriesCnt,maxSeriesCnt);var ariaLabel;if(seriesCnt<1){// No series, no aria label\nreturn;}else{var title=getTitle();if(title){ariaLabel=replace(getConfig('general.withTitle'),{title:title});}else{ariaLabel=getConfig('general.withoutTitle');}var seriesLabels=[];var prefix=seriesCnt>1?'series.multiple.prefix':'series.single.prefix';ariaLabel+=replace(getConfig(prefix),{seriesCount:seriesCnt});ecModel.eachSeries(function(seriesModel,idx){if(idx<displaySeriesCnt){var seriesLabel;var seriesName=seriesModel.get('name');var seriesTpl='series.'+(seriesCnt>1?'multiple':'single')+'.';seriesLabel=getConfig(seriesName?seriesTpl+'withName':seriesTpl+'withoutName');seriesLabel=replace(seriesLabel,{seriesId:seriesModel.seriesIndex,seriesName:seriesModel.get('name'),seriesType:getSeriesTypeName(seriesModel.subType)});var data=seriesModel.getData();window.data=data;if(data.count()>maxDataCnt){// Show part of data\nseriesLabel+=replace(getConfig('data.partialData'),{displayCnt:maxDataCnt});}else{seriesLabel+=getConfig('data.allData');}var dataLabels=[];for(var i=0;i<data.count();i++){if(i<maxDataCnt){var name=data.getName(i);var value=retrieveRawValue(data,i);dataLabels.push(replace(name?getConfig('data.withName'):getConfig('data.withoutName'),{name:name,value:value}));}}seriesLabel+=dataLabels.join(getConfig('data.separator.middle'))+getConfig('data.separator.end');seriesLabels.push(seriesLabel);}});ariaLabel+=seriesLabels.join(getConfig('series.multiple.separator.middle'))+getConfig('series.multiple.separator.end');dom.setAttribute('aria-label',ariaLabel);}function replace(str,keyValues){if(typeof str!=='string'){return str;}var result=str;each$1(keyValues,function(value,key){result=result.replace(new RegExp('\\\\{\\\\s*'+key+'\\\\s*\\\\}','g'),value);});return result;}function getConfig(path){var userConfig=ariaModel.get(path);if(userConfig==null){var pathArr=path.split('.');var result=lang.aria;for(var i=0;i<pathArr.length;++i){result=result[pathArr[i]];}return result;}else{return userConfig;}}function getTitle(){var title=ecModel.getModel('title').option;if(title&&title.length){title=title[0];}return title&&title.text;}function getSeriesTypeName(type){return lang.series.typeNames[type]||'自定义图';}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var PI$1=Math.PI;/**\n * @param {module:echarts/ExtensionAPI} api\n * @param {Object} [opts]\n * @param {string} [opts.text]\n * @param {string} [opts.color]\n * @param {string} [opts.textColor]\n * @return {module:zrender/Element}\n */var loadingDefault=function loadingDefault(api,opts){opts=opts||{};defaults(opts,{text:'loading',textColor:'#000',fontSize:'12px',maskColor:'rgba(255, 255, 255, 0.8)',showSpinner:true,color:'#c23531',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',text:opts.text,font:font,textPosition:'right',textDistance:10,textFill:opts.textColor},zlevel:opts.zlevel,z:10001});group.add(labelRect);if(opts.showSpinner){var arc=new Arc({shape:{startAngle:-PI$1/2,endAngle:-PI$1/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$1*3/2}).start('circularInOut');arc.animateShape(true).when(1000,{startAngle:PI$1*3/2}).delay(300).start('circularInOut');group.add(arc);}// Inject resize\ngroup.resize=function(){var textWidth=getWidth(opts.text,font);var r=opts.showSpinner?opts.spinnerRadius:0;// cx = (containerWidth - arcDiameter - textDistance - textWidth) / 2\n// textDistance needs to be calculated when both animation and text exist\nvar cx=(api.getWidth()-r*2-(opts.showSpinner&&textWidth?10:0)-textWidth)/2// only show the text\n-(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;};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/stream/Scheduler\n */ /**\n * @constructor\n */function Scheduler(ecInstance,api,dataProcessorHandlers,visualHandlers){this.ecInstance=ecInstance;this.api=api;this.unfinished;// Fix current processors in case that in some rear cases that\n// processors might be registered after echarts instance created.\n// Register processors incrementally for a echarts instance is\n// not supported by this stream architecture.\nvar dataProcessorHandlers=this._dataProcessorHandlers=dataProcessorHandlers.slice();var visualHandlers=this._visualHandlers=visualHandlers.slice();this._allHandlers=dataProcessorHandlers.concat(visualHandlers);/**\n     * @private\n     * @type {\n     *     [handlerUID: string]: {\n     *         seriesTaskMap?: {\n     *             [seriesUID: string]: Task\n     *         },\n     *         overallTask?: Task\n     *     }\n     * }\n     */this._stageTaskMap=createHashMap();}var proto=Scheduler.prototype;/**\n * @param {module:echarts/model/Global} ecModel\n * @param {Object} payload\n */proto.restoreData=function(ecModel,payload){// TODO: Only restore needed series and components, but not all components.\n// Currently `restoreData` of all of the series and component will be called.\n// But some independent components like `title`, `legend`, `graphic`, `toolbox`,\n// `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,\n// and some components like coordinate system, axes, dataZoom, visualMap only\n// need their target series refresh.\n// (1) If we are implementing this feature some day, we should consider these cases:\n// if a data processor depends on a component (e.g., dataZoomProcessor depends\n// on the settings of `dataZoom`), it should be re-performed if the component\n// is modified by `setOption`.\n// (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,\n// it should be re-performed when the result array of `getTargetSeries` changed.\n// We use `dependencies` to cover these issues.\n// (3) How to update target series when coordinate system related components modified.\n// TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,\n// and this case all of the tasks will be set as dirty.\necModel.restoreData(payload);// Theoretically an overall task not only depends on each of its target series, but also\n// depends on all of the series.\n// The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks\n// dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure\n// that the overall task is set as dirty and to be performed, otherwise it probably cause\n// state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it\n// probably cause state chaos (consider `dataZoomProcessor`).\nthis._stageTaskMap.each(function(taskRecord){var overallTask=taskRecord.overallTask;overallTask&&overallTask.dirty();});};// If seriesModel provided, incremental threshold is check by series data.\nproto.getPerformArgs=function(task,isBlock){// For overall task\nif(!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};};proto.getPipeline=function(pipelineId){return this._pipelineMap.get(pipelineId);};/**\n * Current, progressive rendering starts from visual and layout.\n * Always detect render mode in the same stage, avoiding that incorrect\n * detection caused by data filtering.\n * Caution:\n * `updateStreamModes` use `seriesModel.getData()`.\n */proto.updateStreamModes=function(seriesModel,view){var pipeline=this._pipelineMap.get(seriesModel.uid);var data=seriesModel.getData();var dataLen=data.count();// `progressiveRender` means that can render progressively in each\n// animation frame. Note that some types of series do not provide\n// `view.incrementalPrepareRender` but support `chart.appendData`. We\n// use the term `incremental` but not `progressive` to describe the\n// case that `chart.appendData`.\nvar progressiveRender=pipeline.progressiveEnabled&&view.incrementalPrepareRender&&dataLen>=pipeline.threshold;var large=seriesModel.get('large')&&dataLen>=seriesModel.get('largeThreshold');// TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.\n// see `test/candlestick-large3.html`\nvar modDataCount=seriesModel.get('progressiveChunkMode')==='mod'?dataLen:null;seriesModel.pipelineContext=pipeline.context={progressiveRender:progressiveRender,modDataCount:modDataCount,large:large};};proto.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});pipe(scheduler,seriesModel,seriesModel.dataTask);});};proto.prepareStageTasks=function(){var stageTaskMap=this._stageTaskMap;var ecModel=this.ecInstance.getModel();var api=this.api;each$1(this._allHandlers,function(handler){var record=stageTaskMap.get(handler.uid)||stageTaskMap.set(handler.uid,[]);handler.reset&&createSeriesStageTask(this,handler,record,ecModel,api);handler.overallReset&&createOverallStageTask(this,handler,record,ecModel,api);},this);};proto.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;pipe(this,model,renderTask);};proto.performDataProcessorTasks=function(ecModel,payload){// If we do not use `block` here, it should be considered when to update modes.\nperformStageTasks(this,this._dataProcessorHandlers,ecModel,payload,{block:true});};// opt\n// opt.visualType: 'visual' or 'layout'\n// opt.setDirty\nproto.performVisualTasks=function(ecModel,payload,opt){performStageTasks(this,this._visualHandlers,ecModel,payload,opt);};function performStageTasks(scheduler,stageHandlers,ecModel,payload,opt){opt=opt||{};var unfinished;each$1(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;var agentStubMap=overallTask.agentStubMap;agentStubMap.each(function(stub){if(needSetDirty(opt,stub)){stub.dirty();overallNeedDirty=true;}});overallNeedDirty&&overallTask.dirty();updatePayload(overallTask,payload);var performArgs=scheduler.getPerformArgs(overallTask,opt.block);// Execute stubs firstly, which may set the overall task dirty,\n// then execute the overall task. And stub will call seriesModel.setData,\n// which ensures that in the overallTask seriesModel.getData() will not\n// return incorrect data.\nagentStubMap.each(function(stub){stub.perform(performArgs);});unfinished|=overallTask.perform(performArgs);}else if(seriesTaskMap){seriesTaskMap.each(function(task,pipelineId){if(needSetDirty(opt,task)){task.dirty();}var performArgs=scheduler.getPerformArgs(task,opt.block);// FIXME\n// if intending to decalare `performRawSeries` in handlers, only\n// stream-independent (specifically, data item independent) operations can be\n// performed. Because is a series is filtered, most of the tasks will not\n// be performed. A stream-dependent operation probably cause wrong biz logic.\n// Perhaps we should not provide a separate callback for this case instead\n// of providing the config `performRawSeries`. The stream-dependent operaions\n// and stream-independent operations should better not be mixed.\nperformArgs.skip=!stageHandler.performRawSeries&&ecModel.isSeriesFiltered(task.context.model);updatePayload(task,payload);unfinished|=task.perform(performArgs);});}});function needSetDirty(opt,task){return opt.setDirty&&(!opt.dirtyMap||opt.dirtyMap.get(task.__pipeline.id));}scheduler.unfinished|=unfinished;}proto.performSeriesTasks=function(ecModel){var unfinished;ecModel.eachSeries(function(seriesModel){// Progress to the end for dataInit and dataRestore.\nunfinished|=seriesModel.dataTask.perform();});this.unfinished|=unfinished;};proto.plan=function(){// Travel pipelines, check block.\nthis._pipelineMap.each(function(pipeline){var task=pipeline.tail;do{if(task.__block){pipeline.blockIndex=task.__idxInPipeline;break;}task=task.getUpstream();}while(task);});};var updatePayload=proto.updatePayload=function(task,payload){payload!=='remain'&&(task.context.payload=payload);};function createSeriesStageTask(scheduler,stageHandler,stageHandlerRecord,ecModel,api){var seriesTaskMap=stageHandlerRecord.seriesTaskMap||(stageHandlerRecord.seriesTaskMap=createHashMap());var seriesType=stageHandler.seriesType;var getTargetSeries=stageHandler.getTargetSeries;// If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,\n// to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,\n// it works but it may cause other irrelevant charts blocked.\nif(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;// Init tasks for each seriesModel only once.\n// Reuse original task instance.\nvar task=seriesTaskMap.get(pipelineId)||seriesTaskMap.set(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};pipe(scheduler,seriesModel,task);}// Clear unused series tasks.\nvar pipelineMap=scheduler._pipelineMap;seriesTaskMap.each(function(task,pipelineId){if(!pipelineMap.get(pipelineId)){task.dispose();seriesTaskMap.removeKey(pipelineId);}});}function createOverallStageTask(scheduler,stageHandler,stageHandlerRecord,ecModel,api){var overallTask=stageHandlerRecord.overallTask=stageHandlerRecord.overallTask// For overall task, the function only be called on reset stage.\n||createTask({reset:overallTaskReset});overallTask.context={ecModel:ecModel,api:api,overallReset:stageHandler.overallReset,scheduler:scheduler};// Reuse orignal stubs.\nvar agentStubMap=overallTask.agentStubMap=overallTask.agentStubMap||createHashMap();var seriesType=stageHandler.seriesType;var getTargetSeries=stageHandler.getTargetSeries;var overallProgress=true;var modifyOutputEnd=stageHandler.modifyOutputEnd;// An overall task with seriesType detected or has `getTargetSeries`, we add\n// stub in each pipelines, it will set the overall task dirty when the pipeline\n// progress. Moreover, to avoid call the overall task each frame (too frequent),\n// we set the pipeline block.\nif(seriesType){ecModel.eachRawSeriesByType(seriesType,createStub);}else if(getTargetSeries){getTargetSeries(ecModel,api).each(createStub);}// Otherwise, (usually it is legancy case), the overall task will only be\n// executed when upstream dirty. Otherwise the progressive rendering of all\n// pipelines will be disabled unexpectedly. But it still needs stubs to receive\n// dirty info from upsteam.\nelse{overallProgress=false;each$1(ecModel.getSeries(),createStub);}function createStub(seriesModel){var pipelineId=seriesModel.uid;var stub=agentStubMap.get(pipelineId);if(!stub){stub=agentStubMap.set(pipelineId,createTask({reset:stubReset,onDirty:stubOnDirty}));// When the result of `getTargetSeries` changed, the overallTask\n// should be set as dirty and re-performed.\noverallTask.dirty();}stub.context={model:seriesModel,overallProgress:overallProgress,modifyOutputEnd:modifyOutputEnd};stub.agent=overallTask;stub.__block=overallProgress;pipe(scheduler,seriesModel,stub);}// Clear unused stubs.\nvar pipelineMap=scheduler._pipelineMap;agentStubMap.each(function(stub,pipelineId){if(!pipelineMap.get(pipelineId)){stub.dispose();// When the result of `getTargetSeries` changed, the overallTask\n// should be set as dirty and re-performed.\noverallTask.dirty();agentStubMap.removeKey(pipelineId);}});}function overallTaskReset(context){context.overallReset(context.ecModel,context.api,context.payload);}function stubReset(context,upstreamContext){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);}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 pipe(scheduler,seriesModel,task){var pipelineId=seriesModel.uid;var pipeline=scheduler._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$1(stageHandler)){stageHandler={overallReset:stageHandler,seriesType:detectSeriseType(stageHandler)};}stageHandler.uid=getUID('stageHandler');visualType&&(stageHandler.visualType=visualType);return stageHandler;};/**\n * Only some legacy stage handlers (usually in echarts extensions) are pure function.\n * To ensure that they can work normally, they should work in block mode, that is,\n * they should not be started util the previous tasks finished. So they cause the\n * progressive rendering disabled. We try to detect the series type, to narrow down\n * the block range to only the series type they concern, but not all series.\n */function detectSeriseType(legacyFunc){seriesType=null;try{// Assume there is no async when calling `eachSeriesByType`.\nlegacyFunc(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){/* eslint-disable */for(var name in Clz.prototype){// Do not use hasOwnProperty\ntarget[name]=noop;}/* eslint-enable */}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/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]};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var contrastColor='#eee';var axisCommon=function axisCommon(){return{axisLine:{lineStyle:{color:contrastColor}},axisTick:{lineStyle:{color:contrastColor}},axisLabel:{textStyle:{color:contrastColor}},splitLine:{lineStyle:{type:'dashed',color:'#aaa'}},splitArea:{areaStyle:{color:contrastColor}}};};var colorPalette=['#dd6b66','#759aa0','#e69d87','#8dc1a9','#ea7e53','#eedd78','#73a373','#73b9bc','#7289ab','#91ca8c','#f49f42'];var theme={color:colorPalette,backgroundColor:'#333',tooltip:{axisPointer:{lineStyle:{color:contrastColor},crossStyle:{color:contrastColor},label:{color:'#000'}}},legend:{textStyle:{color:contrastColor}},textStyle:{color:contrastColor},title:{textStyle:{color:contrastColor}},toolbox:{iconStyle:{normal:{borderColor:contrastColor}}},dataZoom:{textStyle:{color:contrastColor}},visualMap:{textStyle:{color:contrastColor}},timeline:{lineStyle:{color:contrastColor},itemStyle:{normal:{color:colorPalette[1]}},label:{normal:{textStyle:{color:contrastColor}}},controlStyle:{normal:{color:contrastColor,borderColor:contrastColor}}},timeAxis:axisCommon(),logAxis:axisCommon(),valueAxis:axisCommon(),categoryAxis:axisCommon(),line:{symbol:'circle'},graph:{color:colorPalette},gauge:{title:{textStyle:{color:contrastColor}}},candlestick:{itemStyle:{normal:{color:'#FD1050',color0:'#0CF49B',borderColor:'#FD1050',borderColor0:'#0CF49B'}}}};theme.categoryAxis.splitLine.show=false;/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * This module is imported by echarts directly.\n *\n * Notice:\n * Always keep this file exists for backward compatibility.\n * Because before 4.1.0, dataset is an optional component,\n * some users may import this module manually.\n */ComponentModel.extend({type:'dataset',/**\n     * @protected\n     */defaultOption:{// 'row', 'column'\nseriesLayoutBy:SERIES_LAYOUT_BY_COLUMN,// null/'auto': auto detect header, see \"module:echarts/data/helper/sourceHelper\"\nsourceHeader:null,dimensions:null,source:null},optionUpdated:function optionUpdated(){detectSourceFormat(this);}});Component$1.extend({type:'dataset'});/**\n * 椭圆形状\n * @module zrender/graphic/shape/Ellipse\n */var Ellipse=Path.extend({type:'ellipse',shape:{cx:0,cy:0,rx:0,ry:0},buildPath:function buildPath(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;// 水平控制点偏移量\nvar oy=b*k;// 垂直控制点偏移量\n// 从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线\nctx.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();}});// import RadialGradient from '../graphic/RadialGradient';\n// import Pattern from '../graphic/Pattern';\n// import * as vector from '../core/vector';\n// Most of the values can be separated by comma and/or white space.\nvar DILIMITER_REG=/[\\s,]+/;/**\n * For big svg string, this method might be time consuming.\n *\n * @param {string} svg xml string\n * @return {Object} xml root.\n */function parseXML(svg){if(isString(svg)){var parser=new DOMParser();svg=parser.parseFromString(svg,'text/xml');}// Document node. If using $.get, doc node may be input.\nif(svg.nodeType===9){svg=svg.firstChild;}// nodeName of <!DOCTYPE svg> is also 'svg'.\nwhile(svg.nodeName.toLowerCase()!=='svg'||svg.nodeType!==1){svg=svg.nextSibling;}return svg;}function SVGParser(){this._defs={};this._root=null;this._isDefine=false;this._isText=false;}SVGParser.prototype.parse=function(xml,opt){opt=opt||{};var svg=parseXML(xml);if(!svg){throw new Error('Illegal svg');}var root=new Group();this._root=root;// parse view port\nvar viewBox=svg.getAttribute('viewBox')||'';// If width/height not specified, means \"100%\" of `opt.width/height`.\n// TODO: Other percent value not supported yet.\nvar width=parseFloat(svg.getAttribute('width')||opt.width);var height=parseFloat(svg.getAttribute('height')||opt.height);// If width/height not specified, set as null for output.\nisNaN(width)&&(width=null);isNaN(height)&&(height=null);// Apply inline style on svg element.\nparseAttributes(svg,root,null,true);var child=svg.firstChild;while(child){this._parseNode(child,root);child=child.nextSibling;}var viewBoxRect;var viewBoxTransform;if(viewBox){var viewBoxArr=trim(viewBox).split(DILIMITER_REG);// Some invalid case like viewBox: 'none'.\nif(viewBoxArr.length>=4){viewBoxRect={x:parseFloat(viewBoxArr[0]||0),y:parseFloat(viewBoxArr[1]||0),width:parseFloat(viewBoxArr[2]),height:parseFloat(viewBoxArr[3])};}}if(viewBoxRect&&width!=null&&height!=null){viewBoxTransform=makeViewBoxTransform(viewBoxRect,width,height);if(!opt.ignoreViewBox){// If set transform on the output group, it probably bring trouble when\n// some users only intend to show the clipped content inside the viewBox,\n// but not intend to transform the output group. So we keep the output\n// group no transform. If the user intend to use the viewBox as a\n// camera, just set `opt.ignoreViewBox` as `true` and set transfrom\n// manually according to the viewBox info in the output of this method.\nvar elRoot=root;root=new Group();root.add(elRoot);elRoot.scale=viewBoxTransform.scale.slice();elRoot.position=viewBoxTransform.position.slice();}}// Some shapes might be overflow the viewport, which should be\n// clipped despite whether the viewBox is used, as the SVG does.\nif(!opt.ignoreRootClip&&width!=null&&height!=null){root.setClipPath(new Rect({shape:{x:0,y:0,width:width,height:height}}));}// Set width/height on group just for output the viewport size.\nreturn{root:root,width:width,height:height,viewBoxRect:viewBoxRect,viewBoxTransform:viewBoxTransform};};SVGParser.prototype._parseNode=function(xmlNode,parentGroup){var nodeName=xmlNode.nodeName.toLowerCase();// TODO\n// support <style>...</style> in svg, where nodeName is 'style',\n// CSS classes is defined globally wherever the style tags are declared.\nif(nodeName==='defs'){// define flag\nthis._isDefine=true;}else if(nodeName==='text'){this._isText=true;}var el;if(this._isDefine){var parser=defineParsers[nodeName];if(parser){var def=parser.call(this,xmlNode);var id=xmlNode.getAttribute('id');if(id){this._defs[id]=def;}}}else{var parser=nodeParsers[nodeName];if(parser){el=parser.call(this,xmlNode,parentGroup);parentGroup.add(el);}}var child=xmlNode.firstChild;while(child){if(child.nodeType===1){this._parseNode(child,el);}// Is text\nif(child.nodeType===3&&this._isText){this._parseText(child,el);}child=child.nextSibling;}// Quit define\nif(nodeName==='defs'){this._isDefine=false;}else if(nodeName==='text'){this._isText=false;}};SVGParser.prototype._parseText=function(xmlNode,parentGroup){if(xmlNode.nodeType===1){var dx=xmlNode.getAttribute('dx')||0;var dy=xmlNode.getAttribute('dy')||0;this._textX+=parseFloat(dx);this._textY+=parseFloat(dy);}var text=new Text({style:{text:xmlNode.textContent,transformText:true},position:[this._textX||0,this._textY||0]});inheritStyle(parentGroup,text);parseAttributes(xmlNode,text,this._defs);var fontSize=text.style.fontSize;if(fontSize&&fontSize<9){// PENDING\ntext.style.fontSize=9;text.scale=text.scale||[1,1];text.scale[0]*=fontSize/9;text.scale[1]*=fontSize/9;}var rect=text.getBoundingRect();this._textX+=rect.width;parentGroup.add(text);return text;};var nodeParsers={'g':function g(xmlNode,parentGroup){var g=new Group();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);return g;},'rect':function rect(xmlNode,parentGroup){var rect=new Rect();inheritStyle(parentGroup,rect);parseAttributes(xmlNode,rect,this._defs);rect.setShape({x:parseFloat(xmlNode.getAttribute('x')||0),y:parseFloat(xmlNode.getAttribute('y')||0),width:parseFloat(xmlNode.getAttribute('width')||0),height:parseFloat(xmlNode.getAttribute('height')||0)});// console.log(xmlNode.getAttribute('transform'));\n// console.log(rect.transform);\nreturn rect;},'circle':function circle(xmlNode,parentGroup){var circle=new Circle();inheritStyle(parentGroup,circle);parseAttributes(xmlNode,circle,this._defs);circle.setShape({cx:parseFloat(xmlNode.getAttribute('cx')||0),cy:parseFloat(xmlNode.getAttribute('cy')||0),r:parseFloat(xmlNode.getAttribute('r')||0)});return circle;},'line':function line(xmlNode,parentGroup){var line=new Line();inheritStyle(parentGroup,line);parseAttributes(xmlNode,line,this._defs);line.setShape({x1:parseFloat(xmlNode.getAttribute('x1')||0),y1:parseFloat(xmlNode.getAttribute('y1')||0),x2:parseFloat(xmlNode.getAttribute('x2')||0),y2:parseFloat(xmlNode.getAttribute('y2')||0)});return line;},'ellipse':function ellipse(xmlNode,parentGroup){var ellipse=new Ellipse();inheritStyle(parentGroup,ellipse);parseAttributes(xmlNode,ellipse,this._defs);ellipse.setShape({cx:parseFloat(xmlNode.getAttribute('cx')||0),cy:parseFloat(xmlNode.getAttribute('cy')||0),rx:parseFloat(xmlNode.getAttribute('rx')||0),ry:parseFloat(xmlNode.getAttribute('ry')||0)});return ellipse;},'polygon':function polygon(xmlNode,parentGroup){var points=xmlNode.getAttribute('points');if(points){points=parsePoints(points);}var polygon=new Polygon({shape:{points:points||[]}});inheritStyle(parentGroup,polygon);parseAttributes(xmlNode,polygon,this._defs);return polygon;},'polyline':function polyline(xmlNode,parentGroup){var path=new Path();inheritStyle(parentGroup,path);parseAttributes(xmlNode,path,this._defs);var points=xmlNode.getAttribute('points');if(points){points=parsePoints(points);}var polyline=new Polyline({shape:{points:points||[]}});return polyline;},'image':function image(xmlNode,parentGroup){var img=new ZImage();inheritStyle(parentGroup,img);parseAttributes(xmlNode,img,this._defs);img.setStyle({image:xmlNode.getAttribute('xlink:href'),x:xmlNode.getAttribute('x'),y:xmlNode.getAttribute('y'),width:xmlNode.getAttribute('width'),height:xmlNode.getAttribute('height')});return img;},'text':function text(xmlNode,parentGroup){var x=xmlNode.getAttribute('x')||0;var y=xmlNode.getAttribute('y')||0;var dx=xmlNode.getAttribute('dx')||0;var dy=xmlNode.getAttribute('dy')||0;this._textX=parseFloat(x)+parseFloat(dx);this._textY=parseFloat(y)+parseFloat(dy);var g=new Group();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);return g;},'tspan':function tspan(xmlNode,parentGroup){var x=xmlNode.getAttribute('x');var y=xmlNode.getAttribute('y');if(x!=null){// new offset x\nthis._textX=parseFloat(x);}if(y!=null){// new offset y\nthis._textY=parseFloat(y);}var dx=xmlNode.getAttribute('dx')||0;var dy=xmlNode.getAttribute('dy')||0;var g=new Group();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);this._textX+=dx;this._textY+=dy;return g;},'path':function path(xmlNode,parentGroup){// TODO svg fill rule\n// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule\n// path.style.globalCompositeOperation = 'xor';\nvar d=xmlNode.getAttribute('d')||'';// Performance sensitive.\nvar path=createFromString(d);inheritStyle(parentGroup,path);parseAttributes(xmlNode,path,this._defs);return path;}};var defineParsers={'lineargradient':function lineargradient(xmlNode){var x1=parseInt(xmlNode.getAttribute('x1')||0,10);var y1=parseInt(xmlNode.getAttribute('y1')||0,10);var x2=parseInt(xmlNode.getAttribute('x2')||10,10);var y2=parseInt(xmlNode.getAttribute('y2')||0,10);var gradient=new LinearGradient(x1,y1,x2,y2);_parseGradientColorStops(xmlNode,gradient);return gradient;},'radialgradient':function radialgradient(xmlNode){}};function _parseGradientColorStops(xmlNode,gradient){var stop=xmlNode.firstChild;while(stop){if(stop.nodeType===1){var offset=stop.getAttribute('offset');if(offset.indexOf('%')>0){// percentage\noffset=parseInt(offset,10)/100;}else if(offset){// number from 0 to 1\noffset=parseFloat(offset);}else{offset=0;}var stopColor=stop.getAttribute('stop-color')||'#000000';gradient.addColorStop(offset,stopColor);}stop=stop.nextSibling;}}function inheritStyle(parent,child){if(parent&&parent.__inheritedStyle){if(!child.__inheritedStyle){child.__inheritedStyle={};}defaults(child.__inheritedStyle,parent.__inheritedStyle);}}function parsePoints(pointsString){var list=trim(pointsString).split(DILIMITER_REG);var points=[];for(var i=0;i<list.length;i+=2){var x=parseFloat(list[i]);var y=parseFloat(list[i+1]);points.push([x,y]);}return points;}var attributesMap={'fill':'fill','stroke':'stroke','stroke-width':'lineWidth','opacity':'opacity','fill-opacity':'fillOpacity','stroke-opacity':'strokeOpacity','stroke-dasharray':'lineDash','stroke-dashoffset':'lineDashOffset','stroke-linecap':'lineCap','stroke-linejoin':'lineJoin','stroke-miterlimit':'miterLimit','font-family':'fontFamily','font-size':'fontSize','font-style':'fontStyle','font-weight':'fontWeight','text-align':'textAlign','alignment-baseline':'textBaseline'};function parseAttributes(xmlNode,el,defs,onlyInlineStyle){var zrStyle=el.__inheritedStyle||{};var isTextEl=el.type==='text';// TODO Shadow\nif(xmlNode.nodeType===1){parseTransformAttribute(xmlNode,el);extend(zrStyle,parseStyleAttribute(xmlNode));if(!onlyInlineStyle){for(var svgAttrName in attributesMap){if(attributesMap.hasOwnProperty(svgAttrName)){var attrValue=xmlNode.getAttribute(svgAttrName);if(attrValue!=null){zrStyle[attributesMap[svgAttrName]]=attrValue;}}}}}var elFillProp=isTextEl?'textFill':'fill';var elStrokeProp=isTextEl?'textStroke':'stroke';el.style=el.style||new Style();var elStyle=el.style;zrStyle.fill!=null&&elStyle.set(elFillProp,getPaint(zrStyle.fill,defs));zrStyle.stroke!=null&&elStyle.set(elStrokeProp,getPaint(zrStyle.stroke,defs));each$1(['lineWidth','opacity','fillOpacity','strokeOpacity','miterLimit','fontSize'],function(propName){var elPropName=propName==='lineWidth'&&isTextEl?'textStrokeWidth':propName;zrStyle[propName]!=null&&elStyle.set(elPropName,parseFloat(zrStyle[propName]));});if(!zrStyle.textBaseline||zrStyle.textBaseline==='auto'){zrStyle.textBaseline='alphabetic';}if(zrStyle.textBaseline==='alphabetic'){zrStyle.textBaseline='bottom';}if(zrStyle.textAlign==='start'){zrStyle.textAlign='left';}if(zrStyle.textAlign==='end'){zrStyle.textAlign='right';}each$1(['lineDashOffset','lineCap','lineJoin','fontWeight','fontFamily','fontStyle','textAlign','textBaseline'],function(propName){zrStyle[propName]!=null&&elStyle.set(propName,zrStyle[propName]);});if(zrStyle.lineDash){el.style.lineDash=trim(zrStyle.lineDash).split(DILIMITER_REG);}if(elStyle[elStrokeProp]&&elStyle[elStrokeProp]!=='none'){// enable stroke\nel[elStrokeProp]=true;}el.__inheritedStyle=zrStyle;}var urlRegex=/url\\(\\s*#(.*?)\\)/;function getPaint(str,defs){// if (str === 'none') {\n//     return;\n// }\nvar urlMatch=defs&&str&&str.match(urlRegex);if(urlMatch){var url=trim(urlMatch[1]);var def=defs[url];return def;}return str;}var transformRegex=/(translate|scale|rotate|skewX|skewY|matrix)\\(([\\-\\s0-9\\.e,]*)\\)/g;function parseTransformAttribute(xmlNode,node){var transform=xmlNode.getAttribute('transform');if(transform){transform=transform.replace(/,/g,' ');var m=null;var transformOps=[];transform.replace(transformRegex,function(str,type,value){transformOps.push(type,value);});for(var i=transformOps.length-1;i>0;i-=2){var value=transformOps[i];var type=transformOps[i-1];m=m||create$1();switch(type){case'translate':value=trim(value).split(DILIMITER_REG);translate(m,m,[parseFloat(value[0]),parseFloat(value[1]||0)]);break;case'scale':value=trim(value).split(DILIMITER_REG);scale$1(m,m,[parseFloat(value[0]),parseFloat(value[1]||value[0])]);break;case'rotate':value=trim(value).split(DILIMITER_REG);rotate(m,m,parseFloat(value[0]));break;case'skew':value=trim(value).split(DILIMITER_REG);console.warn('Skew transform is not supported yet');break;case'matrix':var value=trim(value).split(DILIMITER_REG);m[0]=parseFloat(value[0]);m[1]=parseFloat(value[1]);m[2]=parseFloat(value[2]);m[3]=parseFloat(value[3]);m[4]=parseFloat(value[4]);m[5]=parseFloat(value[5]);break;}}node.setLocalTransform(m);}}// Value may contain space.\nvar styleRegex=/([^\\s:;]+)\\s*:\\s*([^:;]+)/g;function parseStyleAttribute(xmlNode){var style=xmlNode.getAttribute('style');var result={};if(!style){return result;}var styleList={};styleRegex.lastIndex=0;var styleRegResult;while((styleRegResult=styleRegex.exec(style))!=null){styleList[styleRegResult[1]]=styleRegResult[2];}for(var svgAttrName in attributesMap){if(attributesMap.hasOwnProperty(svgAttrName)&&styleList[svgAttrName]!=null){result[attributesMap[svgAttrName]]=styleList[svgAttrName];}}return result;}/**\n * @param {Array.<number>} viewBoxRect\n * @param {number} width\n * @param {number} height\n * @return {Object} {scale, position}\n */function makeViewBoxTransform(viewBoxRect,width,height){var scaleX=width/viewBoxRect.width;var scaleY=height/viewBoxRect.height;var scale=Math.min(scaleX,scaleY);// preserveAspectRatio 'xMidYMid'\nvar viewBoxScale=[scale,scale];var viewBoxPosition=[-(viewBoxRect.x+viewBoxRect.width/2)*scale+width/2,-(viewBoxRect.y+viewBoxRect.height/2)*scale+height/2];return{scale:viewBoxScale,position:viewBoxPosition};}/**\n * @param {string|XMLElement} xml\n * @param {Object} [opt]\n * @param {number} [opt.width] Default width if svg width not specified or is a percent value.\n * @param {number} [opt.height] Default height if svg height not specified or is a percent value.\n * @param {boolean} [opt.ignoreViewBox]\n * @param {boolean} [opt.ignoreRootClip]\n * @return {Object} result:\n * {\n *     root: Group, The root of the the result tree of zrender shapes,\n *     width: number, the viewport width of the SVG,\n *     height: number, the viewport height of the SVG,\n *     viewBoxRect: {x, y, width, height}, the declared viewBox rect of the SVG, if exists,\n *     viewBoxTransform: the {scale, position} calculated by viewBox and viewport, is exists.\n * }\n */ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var storage=createHashMap();// For minimize the code size of common echarts package,\n// do not put too much logic in this module.\nvar mapDataStorage={// The format of record: see `echarts.registerMap`.\n// Compatible with previous `echarts.registerMap`.\nregisterMap:function registerMap(mapName,rawGeoJson,rawSpecialAreas){var records;if(isArray(rawGeoJson)){records=rawGeoJson;}else if(rawGeoJson.svg){records=[{type:'svg',source:rawGeoJson.svg,specialAreas:rawGeoJson.specialAreas}];}else{// Backward compatibility.\nif(rawGeoJson.geoJson&&!rawGeoJson.features){rawSpecialAreas=rawGeoJson.specialAreas;rawGeoJson=rawGeoJson.geoJson;}records=[{type:'geoJSON',source:rawGeoJson,specialAreas:rawSpecialAreas}];}each$1(records,function(record){var type=record.type;type==='geoJson'&&(type=record.type='geoJSON');var parse=parsers[type];if(__DEV__){assert$1(parse,'Illegal map type: '+type);}parse(record);});return storage.set(mapName,records);},retrieveMap:function retrieveMap(mapName){return storage.get(mapName);}};var parsers={geoJSON:function geoJSON(record){var source=record.source;record.geoJSON=!isString(source)?source:typeof JSON!=='undefined'&&JSON.parse?JSON.parse(source):new Function('return ('+source+');')();},// Only perform parse to XML object here, which might be time\n// consiming for large SVG.\n// Although convert XML to zrender element is also time consiming,\n// if we do it here, the clone of zrender elements has to be\n// required. So we do it once for each geo instance, util real\n// performance issues call for optimizing it.\nsvg:function svg(record){record.svgXML=parseXML(record.source);}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var assert=assert$1;var each=each$1;var isFunction=isFunction$1;var isObject=isObject$1;var parseClassType=ComponentModel.parseClassType;var version='4.9.0';var dependencies={zrender:'4.3.2'};var TEST_FRAME_REMAIN_TIME=1;var PRIORITY_PROCESSOR_FILTER=1000;var PRIORITY_PROCESSOR_SERIES_FILTER=800;var PRIORITY_PROCESSOR_DATASTACK=900;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_POST_CHART_LAYOUT=3500;var PRIORITY_VISUAL_COMPONENT=4000;// FIXME\n// necessary?\nvar PRIORITY_VISUAL_BRUSH=5000;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}};// Main process have three entries: `setOption`, `dispatchAction` and `resize`,\n// where they must not be invoked nestedly, except the only case: invoke\n// dispatchAction with updateMethod \"none\" in main process.\n// This flag is used to carry out this rule.\n// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).\nvar IN_MAIN_PROCESS='__flagInMainProcess';var OPTION_UPDATED='__optionUpdated';var ACTION_REG=/^[a-zA-Z0-9_]+$/;function createRegisterEventWithLowercaseName(method,ignoreDisposed){return function(eventName,handler,context){if(!ignoreDisposed&&this._disposed){disposedWarning(this.id);return;}// Event name is all lowercase\neventName=eventName&&eventName.toLowerCase();Eventful.prototype[method].call(this,eventName,handler,context);};}/**\n * @module echarts~MessageCenter\n */function MessageCenter(){Eventful.call(this);}MessageCenter.prototype.on=createRegisterEventWithLowercaseName('on',true);MessageCenter.prototype.off=createRegisterEventWithLowercaseName('off',true);MessageCenter.prototype.one=createRegisterEventWithLowercaseName('one',true);mixin(MessageCenter,Eventful);/**\n * @module echarts~ECharts\n */function ECharts(dom,theme$$1,opts){opts=opts||{};// Get theme by name\nif(typeof theme$$1==='string'){theme$$1=themeStorage[theme$$1];}/**\n     * @type {string}\n     */this.id;/**\n     * Group id\n     * @type {string}\n     */this.group;/**\n     * @type {HTMLElement}\n     * @private\n     */this._dom=dom;var defaultRenderer='canvas';if(__DEV__){defaultRenderer=(typeof window==='undefined'?global:window).__ECHARTS__DEFAULT__RENDERER__||defaultRenderer;}/**\n     * @type {module:zrender/ZRender}\n     * @private\n     */var zr=this._zr=init$1(dom,{renderer:opts.renderer||defaultRenderer,devicePixelRatio:opts.devicePixelRatio,width:opts.width,height:opts.height});/**\n     * Expect 60 fps.\n     * @type {Function}\n     * @private\n     */this._throttledZrFlush=throttle(bind(zr.flush,zr),17);var theme$$1=_clone(theme$$1);theme$$1&&backwardCompat(theme$$1,true);/**\n     * @type {Object}\n     * @private\n     */this._theme=theme$$1;/**\n     * @type {Array.<module:echarts/view/Chart>}\n     * @private\n     */this._chartsViews=[];/**\n     * @type {Object.<string, module:echarts/view/Chart>}\n     * @private\n     */this._chartsMap={};/**\n     * @type {Array.<module:echarts/view/Component>}\n     * @private\n     */this._componentsViews=[];/**\n     * @type {Object.<string, module:echarts/view/Component>}\n     * @private\n     */this._componentsMap={};/**\n     * @type {module:echarts/CoordinateSystem}\n     * @private\n     */this._coordSysMgr=new CoordinateSystemManager();/**\n     * @type {module:echarts/ExtensionAPI}\n     * @private\n     */var api=this._api=createExtensionAPI(this);// Sort on demand\nfunction prioritySortFunc(a,b){return a.__prio-b.__prio;}sort(visualFuncs,prioritySortFunc);sort(dataProcessorFuncs,prioritySortFunc);/**\n     * @type {module:echarts/stream/Scheduler}\n     */this._scheduler=new Scheduler(this,api,dataProcessorFuncs,visualFuncs);Eventful.call(this,this._ecEventProcessor=new EventProcessor());/**\n     * @type {module:echarts~MessageCenter}\n     * @private\n     */this._messageCenter=new MessageCenter();// Init mouse events\nthis._initEvents();// In case some people write `window.onresize = chart.resize`\nthis.resize=bind(this.resize,this);// Can't dispatch action during rendering procedure\nthis._pendingActions=[];zr.animation.on('frame',this._onframe,this);bindRenderedEvent(zr,this);// ECharts instance can be used as value.\nsetAsPrimitive(this);}var echartsProto=ECharts.prototype;echartsProto._onframe=function(){if(this._disposed){return;}var scheduler=this._scheduler;// Lazy update\nif(this[OPTION_UPDATED]){var silent=this[OPTION_UPDATED].silent;this[IN_MAIN_PROCESS]=true;prepare(this);updateMethods.update.call(this);this[IN_MAIN_PROCESS]=false;this[OPTION_UPDATED]=false;flushPendingActions.call(this,silent);triggerUpdatedEvent.call(this,silent);}// Avoid do both lazy update and progress in one frame.\nelse if(scheduler.unfinished){// Stream progress.\nvar remainTime=TEST_FRAME_REMAIN_TIME;var ecModel=this._model;var api=this._api;scheduler.unfinished=false;do{var startTime=+new Date();scheduler.performSeriesTasks(ecModel);// Currently dataProcessorFuncs do not check threshold.\nscheduler.performDataProcessorTasks(ecModel);updateStreamModes(this,ecModel);// Do not update coordinate system here. Because that coord system update in\n// each frame is not a good user experience. So we follow the rule that\n// the extent of the coordinate system is determin in the first frame (the\n// frame is executed immedietely after task reset.\n// this._coordSysMgr.update(ecModel, api);\n// console.log('--- ec frame visual ---', remainTime);\nscheduler.performVisualTasks(ecModel);renderSeries(this,this._model,api,'remain');remainTime-=+new Date()-startTime;}while(remainTime>0&&scheduler.unfinished);// Call flush explicitly for trigger finished event.\nif(!scheduler.unfinished){this._zr.flush();}// Else, zr flushing be ensue within the same frame,\n// because zr flushing is after onframe event.\n}};/**\n * @return {HTMLElement}\n */echartsProto.getDom=function(){return this._dom;};/**\n * @return {module:zrender~ZRender}\n */echartsProto.getZr=function(){return this._zr;};/**\n * Usage:\n * chart.setOption(option, notMerge, lazyUpdate);\n * chart.setOption(option, {\n *     notMerge: ...,\n *     lazyUpdate: ...,\n *     silent: ...\n * });\n *\n * @param {Object} option\n * @param {Object|boolean} [opts] opts or notMerge.\n * @param {boolean} [opts.notMerge=false]\n * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently.\n */echartsProto.setOption=function(option,notMerge,lazyUpdate){if(__DEV__){assert(!this[IN_MAIN_PROCESS],'`setOption` should not be called during main process.');}if(this._disposed){disposedWarning(this.id);return;}var silent;if(isObject(notMerge)){lazyUpdate=notMerge.lazyUpdate;silent=notMerge.silent;notMerge=notMerge.notMerge;}this[IN_MAIN_PROCESS]=true;if(!this._model||notMerge){var optionManager=new OptionManager(this._api);var theme$$1=this._theme;var ecModel=this._model=new GlobalModel();ecModel.scheduler=this._scheduler;ecModel.init(null,null,theme$$1,optionManager);}this._model.setOption(option,optionPreprocessorFuncs);if(lazyUpdate){this[OPTION_UPDATED]={silent:silent};this[IN_MAIN_PROCESS]=false;}else{prepare(this);updateMethods.update.call(this);// Ensure zr refresh sychronously, and then pixel in canvas can be\n// fetched after `setOption`.\nthis._zr.flush();this[OPTION_UPDATED]=false;this[IN_MAIN_PROCESS]=false;flushPendingActions.call(this,silent);triggerUpdatedEvent.call(this,silent);}};/**\n * @DEPRECATED\n */echartsProto.setTheme=function(){console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');};/**\n * @return {module:echarts/model/Global}\n */echartsProto.getModel=function(){return this._model;};/**\n * @return {Object}\n */echartsProto.getOption=function(){return this._model&&this._model.getOption();};/**\n * @return {number}\n */echartsProto.getWidth=function(){return this._zr.getWidth();};/**\n * @return {number}\n */echartsProto.getHeight=function(){return this._zr.getHeight();};/**\n * @return {number}\n */echartsProto.getDevicePixelRatio=function(){return this._zr.painter.dpr||window.devicePixelRatio||1;};/**\n * Get canvas which has all thing rendered\n * @param {Object} opts\n * @param {string} [opts.backgroundColor]\n * @return {string}\n */echartsProto.getRenderedCanvas=function(opts){if(!env$1.canvasSupported){return;}opts=opts||{};opts.pixelRatio=opts.pixelRatio||1;opts.backgroundColor=opts.backgroundColor||this._model.get('backgroundColor');var zr=this._zr;// var list = zr.storage.getDisplayList();\n// Stop animations\n// Never works before in init animation, so remove it.\n// zrUtil.each(list, function (el) {\n//     el.stopAnimation(true);\n// });\nreturn zr.painter.getRenderedCanvas(opts);};/**\n * Get svg data url\n * @return {string}\n */echartsProto.getSvgDataURL=function(){if(!env$1.svgSupported){return;}var zr=this._zr;var list=zr.storage.getDisplayList();// Stop animations\neach$1(list,function(el){el.stopAnimation(true);});return zr.painter.toDataURL();};/**\n * @return {string}\n * @param {Object} opts\n * @param {string} [opts.type='png']\n * @param {string} [opts.pixelRatio=1]\n * @param {string} [opts.backgroundColor]\n * @param {string} [opts.excludeComponents]\n */echartsProto.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(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(excludesComponentViews,function(view){view.group.ignore=false;});return url;};/**\n * @return {string}\n * @param {Object} opts\n * @param {string} [opts.type='png']\n * @param {string} [opts.pixelRatio=1]\n * @param {string} [opts.backgroundColor]\n */echartsProto.getConnectedDataURL=function(opts){if(this._disposed){disposedWarning(this.id);return;}if(!env$1.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=MAX_NUMBER;var top=MAX_NUMBER;var right=-MAX_NUMBER;var bottom=-MAX_NUMBER;var canvasList=[];var dpr=opts&&opts.pixelRatio||1;each$1(instances,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=mathMin(boundingRect.left,left);top=mathMin(boundingRect.top,top);right=mathMax(boundingRect.right,right);bottom=mathMax(boundingRect.bottom,bottom);canvasList.push({dom:canvas,left:boundingRect.left,top:boundingRect.top});}});left*=dpr;top*=dpr;right*=dpr;bottom*=dpr;var width=right-left;var height=bottom-top;var targetCanvas=createCanvas();var zr=init$1(targetCanvas,{renderer:isSvg?'svg':'canvas'});zr.resize({width:width,height:height});if(isSvg){var content='';each(canvasList,function(item){var x=item.left-left;var y=item.top-top;content+='<g transform=\"translate('+x+','+y+')\">'+item.dom+'</g>';});zr.painter.getSvgRoot().innerHTML=content;if(opts.connectedBackgroundColor){zr.painter.setBackgroundColor(opts.connectedBackgroundColor);}zr.refreshImmediately();return zr.painter.toDataURL();}else{// Background between the charts\nif(opts.connectedBackgroundColor){zr.add(new Rect({shape:{x:0,y:0,width:width,height:height},style:{fill:opts.connectedBackgroundColor}}));}each(canvasList,function(item){var img=new ZImage({style:{x:item.left*dpr-left,y:item.top*dpr-top,image:item.dom}});zr.add(img);});zr.refreshImmediately();return targetCanvas.toDataURL('image/'+(opts&&opts.type||'png'));}}else{return this.getDataURL(opts);}};/**\n * Convert from logical coordinate system to pixel coordinate system.\n * See CoordinateSystem#convertToPixel.\n * @param {string|Object} finder\n *        If string, e.g., 'geo', means {geoIndex: 0}.\n *        If Object, could contain some of these properties below:\n *        {\n *            seriesIndex / seriesId / seriesName,\n *            geoIndex / geoId, geoName,\n *            bmapIndex / bmapId / bmapName,\n *            xAxisIndex / xAxisId / xAxisName,\n *            yAxisIndex / yAxisId / yAxisName,\n *            gridIndex / gridId / gridName,\n *            ... (can be extended)\n *        }\n * @param {Array|number} value\n * @return {Array|number} result\n */echartsProto.convertToPixel=curry(doConvertPixel,'convertToPixel');/**\n * Convert from pixel coordinate system to logical coordinate system.\n * See CoordinateSystem#convertFromPixel.\n * @param {string|Object} finder\n *        If string, e.g., 'geo', means {geoIndex: 0}.\n *        If Object, could contain some of these properties below:\n *        {\n *            seriesIndex / seriesId / seriesName,\n *            geoIndex / geoId / geoName,\n *            bmapIndex / bmapId / bmapName,\n *            xAxisIndex / xAxisId / xAxisName,\n *            yAxisIndex / yAxisId / yAxisName\n *            gridIndex / gridId / gridName,\n *            ... (can be extended)\n *        }\n * @param {Array|number} value\n * @return {Array|number} result\n */echartsProto.convertFromPixel=curry(doConvertPixel,'convertFromPixel');function doConvertPixel(methodName,finder,value){if(this._disposed){disposedWarning(this.id);return;}var ecModel=this._model;var coordSysList=this._coordSysMgr.getCoordinateSystems();var result;finder=parseFinder(ecModel,finder);for(var i=0;i<coordSysList.length;i++){var coordSys=coordSysList[i];if(coordSys[methodName]&&(result=coordSys[methodName](ecModel,finder,value))!=null){return result;}}if(__DEV__){console.warn('No coordinate system that supports '+methodName+' found by the given finder.');}}/**\n * Is the specified coordinate systems or components contain the given pixel point.\n * @param {string|Object} finder\n *        If string, e.g., 'geo', means {geoIndex: 0}.\n *        If Object, could contain some of these properties below:\n *        {\n *            seriesIndex / seriesId / seriesName,\n *            geoIndex / geoId / geoName,\n *            bmapIndex / bmapId / bmapName,\n *            xAxisIndex / xAxisId / xAxisName,\n *            yAxisIndex / yAxisId / yAxisName,\n *            gridIndex / gridId / gridName,\n *            ... (can be extended)\n *        }\n * @param {Array|number} value\n * @return {boolean} result\n */echartsProto.containPixel=function(finder,value){if(this._disposed){disposedWarning(this.id);return;}var ecModel=this._model;var result;finder=parseFinder(ecModel,finder);each$1(finder,function(models,key){key.indexOf('Models')>=0&&each$1(models,function(model){var coordSys=model.coordinateSystem;if(coordSys&&coordSys.containPoint){result|=!!coordSys.containPoint(value);}else if(key==='seriesModels'){var view=this._chartsMap[model.__viewId];if(view&&view.containPoint){result|=view.containPoint(value,model);}else{if(__DEV__){console.warn(key+': '+(view?'The found component do not support containPoint.':'No view mapping to the found component.'));}}}else{if(__DEV__){console.warn(key+': containPoint is not supported');}}},this);},this);return!!result;};/**\n * Get visual from series or data.\n * @param {string|Object} finder\n *        If string, e.g., 'series', means {seriesIndex: 0}.\n *        If Object, could contain some of these properties below:\n *        {\n *            seriesIndex / seriesId / seriesName,\n *            dataIndex / dataIndexInside\n *        }\n *        If dataIndex is not specified, series visual will be fetched,\n *        but not data item visual.\n *        If all of seriesIndex, seriesId, seriesName are not specified,\n *        visual will be fetched from first series.\n * @param {string} visualType 'color', 'symbol', 'symbolSize'\n */echartsProto.getVisual=function(finder,visualType){var ecModel=this._model;finder=parseFinder(ecModel,finder,{defaultMainType:'series'});var seriesModel=finder.seriesModel;if(__DEV__){if(!seriesModel){console.warn('There is no specified seires model');}}var data=seriesModel.getData();var dataIndexInside=finder.hasOwnProperty('dataIndexInside')?finder.dataIndexInside:finder.hasOwnProperty('dataIndex')?data.indexOfRawIndex(finder.dataIndex):null;return dataIndexInside!=null?data.getItemVisual(dataIndexInside,visualType):data.getVisual(visualType);};/**\n * Get view of corresponding component model\n * @param  {module:echarts/model/Component} componentModel\n * @return {module:echarts/view/Component}\n */echartsProto.getViewOfComponentModel=function(componentModel){return this._componentsMap[componentModel.__viewId];};/**\n * Get view of corresponding series model\n * @param  {module:echarts/model/Series} seriesModel\n * @return {module:echarts/view/Chart}\n */echartsProto.getViewOfSeriesModel=function(seriesModel){return this._chartsMap[seriesModel.__viewId];};var updateMethods={prepareAndUpdate:function prepareAndUpdate(payload){prepare(this);updateMethods.update.call(this,payload);},/**\n     * @param {Object} payload\n     * @private\n     */update:function update(payload){// console.profile && console.profile('update');\nvar ecModel=this._model;var api=this._api;var zr=this._zr;var coordSysMgr=this._coordSysMgr;var scheduler=this._scheduler;// update before setOption\nif(!ecModel){return;}scheduler.restoreData(ecModel,payload);scheduler.performSeriesTasks(ecModel);// TODO\n// Save total ecModel here for undo/redo (after restoring data and before processing data).\n// Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.\n// Create new coordinate system each update\n// In LineView may save the old coordinate system and use it to get the orignal point\ncoordSysMgr.create(ecModel,api);scheduler.performDataProcessorTasks(ecModel,payload);// Current stream render is not supported in data process. So we can update\n// stream modes after data processing, where the filtered data is used to\n// deteming whether use progressive rendering.\nupdateStreamModes(this,ecModel);// We update stream modes before coordinate system updated, then the modes info\n// can be fetched when coord sys updating (consider the barGrid extent fix). But\n// the drawback is the full coord info can not be fetched. Fortunately this full\n// coord is not requied in stream mode updater currently.\ncoordSysMgr.update(ecModel,api);clearColorPalette(ecModel);scheduler.performVisualTasks(ecModel,payload);render(this,ecModel,api,payload);// Set background\nvar backgroundColor=ecModel.get('backgroundColor')||'transparent';// In IE8\nif(!env$1.canvasSupported){var colorArr=parse(backgroundColor);backgroundColor=stringify(colorArr,'rgb');if(colorArr[3]===0){backgroundColor='transparent';}}else{zr.setBackgroundColor(backgroundColor);}performPostUpdateFuncs(ecModel,api);// console.profile && console.profileEnd('update');\n},/**\n     * @param {Object} payload\n     * @private\n     */updateTransform:function updateTransform(payload){var ecModel=this._model;var ecIns=this;var api=this._api;// update before setOption\nif(!ecModel){return;}// ChartView.markUpdateMethod(payload, 'updateTransform');\nvar componentDirtyList=[];ecModel.eachComponent(function(componentType,componentModel){var componentView=ecIns.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=ecIns._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);// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.\n// this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);\nthis._scheduler.performVisualTasks(ecModel,payload,{setDirty:true,dirtyMap:seriesDirtyMap});// Currently, not call render of components. Geo render cost a lot.\n// renderComponents(ecIns, ecModel, api, payload, componentDirtyList);\nrenderSeries(ecIns,ecModel,api,payload,seriesDirtyMap);performPostUpdateFuncs(ecModel,this._api);},/**\n     * @param {Object} payload\n     * @private\n     */updateView:function updateView(payload){var ecModel=this._model;// update before setOption\nif(!ecModel){return;}Chart.markUpdateMethod(payload,'updateView');clearColorPalette(ecModel);// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.\nthis._scheduler.performVisualTasks(ecModel,payload,{setDirty:true});render(this,this._model,this._api,payload);performPostUpdateFuncs(ecModel,this._api);},/**\n     * @param {Object} payload\n     * @private\n     */updateVisual:function updateVisual(payload){updateMethods.update.call(this,payload);// var ecModel = this._model;\n// // update before setOption\n// if (!ecModel) {\n//     return;\n// }\n// ChartView.markUpdateMethod(payload, 'updateVisual');\n// clearColorPalette(ecModel);\n// // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.\n// this._scheduler.performVisualTasks(ecModel, payload, {visualType: 'visual', setDirty: true});\n// render(this, this._model, this._api, payload);\n// performPostUpdateFuncs(ecModel, this._api);\n},/**\n     * @param {Object} payload\n     * @private\n     */updateLayout:function updateLayout(payload){updateMethods.update.call(this,payload);// var ecModel = this._model;\n// // update before setOption\n// if (!ecModel) {\n//     return;\n// }\n// ChartView.markUpdateMethod(payload, 'updateLayout');\n// // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.\n// // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);\n// this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true});\n// render(this, this._model, this._api, payload);\n// performPostUpdateFuncs(ecModel, this._api);\n}};function prepare(ecIns){var ecModel=ecIns._model;var scheduler=ecIns._scheduler;scheduler.restorePipelines(ecModel);scheduler.prepareStageTasks();prepareView(ecIns,'component',ecModel,scheduler);prepareView(ecIns,'chart',ecModel,scheduler);scheduler.plan();}/**\n * @private\n */function updateDirectly(ecIns,method,payload,mainType,subType){var ecModel=ecIns._model;// broadcast\nif(!mainType){// FIXME\n// Chart will not be update directly here, except set dirty.\n// But there is no such scenario now.\neach(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);// subType may be '' by parseClassType;\nvar excludeSeriesId=payload.excludeSeriesId;if(excludeSeriesId!=null){excludeSeriesId=createHashMap(normalizeToArray(excludeSeriesId));}// If dispatchAction before setOption, do nothing.\necModel&&ecModel.eachComponent(condition,function(model){if(!excludeSeriesId||excludeSeriesId.get(model.id)==null){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);}}/**\n * Resize the chart\n * @param {Object} opts\n * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)\n * @param {boolean} [opts.silent=false]\n */echartsProto.resize=function(opts){if(__DEV__){assert(!this[IN_MAIN_PROCESS],'`resize` should not be called during main process.');}if(this._disposed){disposedWarning(this.id);return;}this._zr.resize(opts);var ecModel=this._model;// Resize loading effect\nthis._loadingFX&&this._loadingFX.resize();if(!ecModel){return;}var optionChanged=ecModel.resetOption('media');var silent=opts&&opts.silent;this[IN_MAIN_PROCESS]=true;optionChanged&&prepare(this);updateMethods.update.call(this);this[IN_MAIN_PROCESS]=false;flushPendingActions.call(this,silent);triggerUpdatedEvent.call(this,silent);};function updateStreamModes(ecIns,ecModel){var chartsMap=ecIns._chartsMap;var scheduler=ecIns._scheduler;ecModel.eachSeries(function(seriesModel){scheduler.updateStreamModes(seriesModel,chartsMap[seriesModel.__viewId]);});}/**\n * Show loading effect\n * @param  {string} [name='default']\n * @param  {Object} [cfg]\n */echartsProto.showLoading=function(name,cfg){if(this._disposed){disposedWarning(this.id);return;}if(isObject(name)){cfg=name;name='';}name=name||'default';this.hideLoading();if(!loadingEffects[name]){if(__DEV__){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);};/**\n * Hide loading effect\n */echartsProto.hideLoading=function(){if(this._disposed){disposedWarning(this.id);return;}this._loadingFX&&this._zr.remove(this._loadingFX);this._loadingFX=null;};/**\n * @param {Object} eventObj\n * @return {Object}\n */echartsProto.makeActionFromEvent=function(eventObj){var payload=extend({},eventObj);payload.type=eventActionMap[eventObj.type];return payload;};/**\n * @pubilc\n * @param {Object} payload\n * @param {string} [payload.type] Action type\n * @param {Object|boolean} [opt] If pass boolean, means opt.silent\n * @param {boolean} [opt.silent=false] Whether trigger events.\n * @param {boolean} [opt.flush=undefined]\n *                  true: Flush immediately, and then pixel in canvas can be fetched\n *                      immediately. Caution: it might affect performance.\n *                  false: Not flush.\n *                  undefined: Auto decide whether perform flush.\n */echartsProto.dispatchAction=function(payload,opt){if(this._disposed){disposedWarning(this.id);return;}if(!isObject(opt)){opt={silent:!!opt};}if(!actions[payload.type]){return;}// Avoid dispatch action before setOption. Especially in `connect`.\nif(!this._model){return;}// May dispatchAction in rendering procedure\nif(this[IN_MAIN_PROCESS]){this._pendingActions.push(payload);return;}doDispatchAction.call(this,payload,opt.silent);if(opt.flush){this._zr.flush(true);}else if(opt.flush!==false&&env$1.browser.weChat){// In WeChat embeded browser, `requestAnimationFrame` and `setInterval`\n// hang when sliding page (on touch event), which cause that zr does not\n// refresh util user interaction finished, which is not expected.\n// But `dispatchAction` may be called too frequently when pan on touch\n// screen, which impacts performance if do not throttle them.\nthis._throttledZrFlush();}flushPendingActions.call(this,opt.silent);triggerUpdatedEvent.call(this,opt.silent);};function doDispatchAction(payload,silent){var payloadType=payload.type;var escapeConnect=payload.escapeConnect;var actionWrap=actions[payloadType];var actionInfo=actionWrap.actionInfo;var cptType=(actionInfo.update||'update').split(':');var updateMethod=cptType.pop();cptType=cptType[0]!=null&&parseClassType(cptType[0]);this[IN_MAIN_PROCESS]=true;var payloads=[payload];var batched=false;// Batch action\nif(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 isHighDown=payloadType==='highlight'||payloadType==='downplay';each(payloads,function(batchItem){// Action can specify the event by return it.\neventObj=actionWrap.action(batchItem,this._model,this._api);// Emit event outside\neventObj=eventObj||extend({},batchItem);// Convert type to eventType\neventObj.type=actionInfo.event||eventObj.type;eventObjBatch.push(eventObj);// light update does not perform data process, layout and visual.\nif(isHighDown){// method, payload, mainType, subType\nupdateDirectly(this,updateMethod,batchItem,'series');}else if(cptType){updateDirectly(this,updateMethod,batchItem,cptType.main,cptType.sub);}},this);if(updateMethod!=='none'&&!isHighDown&&!cptType){// Still dirty\nif(this[OPTION_UPDATED]){// FIXME Pass payload ?\nprepare(this);updateMethods.update.call(this,payload);this[OPTION_UPDATED]=false;}else{updateMethods[updateMethod].call(this,payload);}}// Follow the rule of action batch\nif(batched){eventObj={type:actionInfo.event||payloadType,escapeConnect:escapeConnect,batch:eventObjBatch};}else{eventObj=eventObjBatch[0];}this[IN_MAIN_PROCESS]=false;!silent&&this._messageCenter.trigger(eventObj.type,eventObj);}function flushPendingActions(silent){var pendingActions=this._pendingActions;while(pendingActions.length){var payload=pendingActions.shift();doDispatchAction.call(this,payload,silent);}}function triggerUpdatedEvent(silent){!silent&&this.trigger('updated');}/**\n * Event `rendered` is triggered when zr\n * rendered. It is useful for realtime\n * snapshot (reflect animation).\n *\n * Event `finished` is triggered when:\n * (1) zrender rendering finished.\n * (2) initial animation finished.\n * (3) progressive rendering finished.\n * (4) no pending action.\n * (5) no delayed setOption needs to be processed.\n */function bindRenderedEvent(zr,ecIns){zr.on('rendered',function(){ecIns.trigger('rendered');// The `finished` event should not be triggered repeatly,\n// so it should only be triggered when rendering indeed happend\n// in zrender. (Consider the case that dipatchAction is keep\n// triggering when mouse move).\nif(// Although zr is dirty if initial animation is not finished\n// and this checking is called on frame, we also check\n// animation finished for robustness.\nzr.animation.isFinished()&&!ecIns[OPTION_UPDATED]&&!ecIns._scheduler.unfinished&&!ecIns._pendingActions.length){ecIns.trigger('finished');}});}/**\n * @param {Object} params\n * @param {number} params.seriesIndex\n * @param {Array|TypedArray} params.data\n */echartsProto.appendData=function(params){if(this._disposed){disposedWarning(this.id);return;}var seriesIndex=params.seriesIndex;var ecModel=this.getModel();var seriesModel=ecModel.getSeriesByIndex(seriesIndex);if(__DEV__){assert(params.data&&seriesModel);}seriesModel.appendData(params);// Note: `appendData` does not support that update extent of coordinate\n// system, util some scenario require that. In the expected usage of\n// `appendData`, the initial extent of coordinate system should better\n// be fixed by axis `min`/`max` setting or initial data, otherwise if\n// the extent changed while `appendData`, the location of the painted\n// graphic elements have to be changed, which make the usage of\n// `appendData` meaningless.\nthis._scheduler.unfinished=true;};/**\n * Register event\n * @method\n */echartsProto.on=createRegisterEventWithLowercaseName('on',false);echartsProto.off=createRegisterEventWithLowercaseName('off',false);echartsProto.one=createRegisterEventWithLowercaseName('one',false);/**\n * Prepare view instances of charts and components\n * @param  {module:echarts/model/Global} ecModel\n * @private\n */function prepareView(ecIns,type,ecModel,scheduler){var isComponent=type==='component';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){// Consider: id same and type changed.\nvar viewId='_ec_'+model.id+'_'+model.type;var view=viewMap[viewId];if(!view){var classType=parseClassType(model.type);var Clazz=isComponent?Component$1.getClass(classType.main,classType.sub):Chart.getClass(classType.sub);if(__DEV__){assert(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);delete viewMap[view.__id];view.__id=view.group.__ecComponentInfo=null;}else{i++;}}}// /**\n//  * Encode visual infomation from data after data processing\n//  *\n//  * @param {module:echarts/model/Global} ecModel\n//  * @param {object} layout\n//  * @param {boolean} [layoutFilter] `true`: only layout,\n//  *                                 `false`: only not layout,\n//  *                                 `null`/`undefined`: all.\n//  * @param {string} taskBaseTag\n//  * @private\n//  */\n// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {\n//     each(visualFuncs, function (visual, index) {\n//         var isLayout = visual.isLayout;\n//         if (layoutFilter == null\n//             || (layoutFilter === false && !isLayout)\n//             || (layoutFilter === true && isLayout)\n//         ) {\n//             visual.func(ecModel, api, payload);\n//         }\n//     });\n// }\nfunction clearColorPalette(ecModel){ecModel.clearColorPalette();ecModel.eachSeries(function(seriesModel){seriesModel.clearColorPalette();});}function render(ecIns,ecModel,api,payload){renderComponents(ecIns,ecModel,api,payload);each(ecIns._chartsViews,function(chart){chart.__alive=false;});renderSeries(ecIns,ecModel,api,payload);// Remove groups of unrendered charts\neach(ecIns._chartsViews,function(chart){if(!chart.__alive){chart.remove(ecModel,api);}});}function renderComponents(ecIns,ecModel,api,payload,dirtyList){each(dirtyList||ecIns._componentsViews,function(componentView){var componentModel=componentView.__model;componentView.render(componentModel,ecModel,api,payload);updateZ(componentModel,componentView);});}/**\n * Render each chart and component\n * @private\n */function renderSeries(ecIns,ecModel,api,payload,dirtyMap){// Render all charts\nvar scheduler=ecIns._scheduler;var unfinished;ecModel.eachSeries(function(seriesModel){var chartView=ecIns._chartsMap[seriesModel.__viewId];chartView.__alive=true;var renderTask=chartView.renderTask;scheduler.updatePayload(renderTask,payload);if(dirtyMap&&dirtyMap.get(seriesModel.uid)){renderTask.dirty();}unfinished|=renderTask.perform(scheduler.getPerformArgs(renderTask));chartView.group.silent=!!seriesModel.get('silent');updateZ(seriesModel,chartView);updateBlend(seriesModel,chartView);});scheduler.unfinished|=unfinished;// If use hover layer\nupdateHoverLayerStatus(ecIns,ecModel);// Add aria\naria(ecIns._zr.dom,ecModel);}function performPostUpdateFuncs(ecModel,api){each(postUpdateFuncs,function(func){func(ecModel,api);});}var MOUSE_EVENT_NAMES=['click','dblclick','mouseover','mouseout','mousemove','mousedown','mouseup','globalout','contextmenu'];/**\n * @private\n */echartsProto._initEvents=function(){each(MOUSE_EVENT_NAMES,function(eveName){var handler=function handler(e){var ecModel=this.getModel();var el=e.target;var params;var isGlobalOut=eveName==='globalout';// no e.target when 'globalout'.\nif(isGlobalOut){params={};}else if(el&&el.dataIndex!=null){var dataModel=el.dataModel||ecModel.getSeriesByIndex(el.seriesIndex);params=dataModel&&dataModel.getDataParams(el.dataIndex,el.dataType,el)||{};}// If element has custom eventData of components\nelse if(el&&el.eventData){params=extend({},el.eventData);}// Contract: if params prepared in mouse event,\n// these properties must be specified:\n// {\n//    componentType: string (component main type)\n//    componentIndex: number\n// }\n// Otherwise event query can not work.\nif(params){var componentType=params.componentType;var componentIndex=params.componentIndex;// Special handling for historic reason: when trigger by\n// markLine/markPoint/markArea, the componentType is\n// 'markLine'/'markPoint'/'markArea', but we should better\n// enable them to be queried by seriesIndex, since their\n// option is set in each series.\nif(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(__DEV__){// `event.componentType` and `event[componentTpype + 'Index']` must not\n// be missed, otherwise there is no way to distinguish source component.\n// See `dataFormat.getDataParams`.\nif(!isGlobalOut&&!(model&&view)){console.warn('model or view can not be found by params');}}params.event=e;params.type=eveName;this._ecEventProcessor.eventInfo={targetEl:el,packedEvent:params,model:model,view:view};this.trigger(eveName,params);}};// Consider that some component (like tooltip, brush, ...)\n// register zr event handler, but user event handler might\n// do anything, such as call `setOption` or `dispatchAction`,\n// which probably update any of the content and probably\n// cause problem if it is called previous other inner handlers.\nhandler.zrEventfulCallAtLast=true;this._zr.on(eveName,handler,this);},this);each(eventActionMap,function(actionType,eventType){this._messageCenter.on(eventType,function(event){this.trigger(eventType,event);},this);},this);};/**\n * @return {boolean}\n */echartsProto.isDisposed=function(){return this._disposed;};/**\n * Clear\n */echartsProto.clear=function(){if(this._disposed){disposedWarning(this.id);return;}this.setOption({series:[]},true);};/**\n * Dispose instance\n */echartsProto.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(this._componentsViews,function(component){component.dispose(ecModel,api);});each(this._chartsViews,function(chart){chart.dispose(ecModel,api);});// Dispose after all views disposed\nthis._zr.dispose();delete instances[this.id];};mixin(ECharts,Eventful);function disposedWarning(id){if(__DEV__){console.warn('Instance '+id+' has been disposed');}}function updateHoverLayerStatus(ecIns,ecModel){var zr=ecIns._zr;var storage=zr.storage;var elCount=0;storage.traverse(function(el){elCount++;});if(elCount>ecModel.get('hoverLayerThreshold')&&!env$1.node){ecModel.eachSeries(function(seriesModel){if(seriesModel.preventUsingHoverLayer){return;}var chartView=ecIns._chartsMap[seriesModel.__viewId];if(chartView.__alive){chartView.group.traverse(function(el){// Don't switch back.\nel.useHoverLayer=true;});}});}}/**\n * Update chart progressive and blend.\n * @param {module:echarts/model/Series|module:echarts/model/Component} model\n * @param {module:echarts/view/Component|module:echarts/view/Chart} view\n */function updateBlend(seriesModel,chartView){var blendMode=seriesModel.get('blendMode')||null;if(__DEV__){if(!env$1.canvasSupported&&blendMode&&blendMode!=='source-over'){console.warn('Only canvas support blendMode');}}chartView.group.traverse(function(el){// FIXME marker and other components\nif(!el.isGroup){// Only set if blendMode is changed. In case element is incremental and don't wan't to rerender.\nif(el.style.blend!==blendMode){el.setStyle('blend',blendMode);}}if(el.eachPendingDisplayable){el.eachPendingDisplayable(function(displayable){displayable.setStyle('blend',blendMode);});}});}/**\n * @param {module:echarts/model/Series|module:echarts/model/Component} model\n * @param {module:echarts/view/Component|module:echarts/view/Chart} view\n */function updateZ(model,view){var z=model.get('z');var zlevel=model.get('zlevel');// Set z and zlevel\nview.group.traverse(function(el){if(el.type!=='group'){z!=null&&(el.z=z);zlevel!=null&&(el.zlevel=zlevel);}});}function createExtensionAPI(ecInstance){var coordSysMgr=ecInstance._coordSysMgr;return extend(new ExtensionAPI(ecInstance),{// Inject methods\ngetCoordinateSystems:bind(coordSysMgr.getCoordinateSystems,coordSysMgr),getComponentByElement:function getComponentByElement(el){while(el){var modelInfo=el.__ecComponentInfo;if(modelInfo!=null){return ecInstance._model.getComponent(modelInfo.mainType,modelInfo.index);}el=el.parent;}}});}/**\n * @class\n * Usage of query:\n * `chart.on('click', query, handler);`\n * The `query` can be:\n * + The component type query string, only `mainType` or `mainType.subType`,\n *   like: 'xAxis', 'series', 'xAxis.category' or 'series.line'.\n * + The component query object, like:\n *   `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`,\n *   `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`.\n * + The data query object, like:\n *   `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`.\n * + The other query object (cmponent customized query), like:\n *   `{element: 'some'}` (only available in custom series).\n *\n * Caveat: If a prop in the `query` object is `null/undefined`, it is the\n * same as there is no such prop in the `query` object.\n */function EventProcessor(){// These info required: targetEl, packedEvent, model, view\nthis.eventInfo;}EventProcessor.prototype={constructor:EventProcessor,normalizeQuery:function normalizeQuery(query){var cptQuery={};var dataQuery={};var otherQuery={};// `query` is `mainType` or `mainType.subType` of component.\nif(isString(query)){var condCptType=parseClassType(query);// `.main` and `.sub` may be ''.\ncptQuery.mainType=condCptType.main||null;cptQuery.subType=condCptType.sub||null;}// `query` is an object, convert to {mainType, index, name, id}.\nelse{// `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved,\n// can not be used in `compomentModel.filterForExposedEvent`.\nvar suffixes=['Index','Name','Id'];var dataKeys={name:1,dataIndex:1,dataType:1};each$1(query,function(val,key){var reserved=false;for(var i=0;i<suffixes.length;i++){var propSuffix=suffixes[i];var suffixPos=key.lastIndexOf(propSuffix);if(suffixPos>0&&suffixPos===key.length-propSuffix.length){var mainType=key.slice(0,suffixPos);// Consider `dataIndex`.\nif(mainType!=='data'){cptQuery.mainType=mainType;cptQuery[propSuffix.toLowerCase()]=val;reserved=true;}}}if(dataKeys.hasOwnProperty(key)){dataQuery[key]=val;reserved=true;}if(!reserved){otherQuery[key]=val;}});}return{cptQuery:cptQuery,dataQuery:dataQuery,otherQuery:otherQuery};},filter:function filter(eventType,query,args){// They should be assigned before each trigger call.\nvar eventInfo=this.eventInfo;if(!eventInfo){return true;}var targetEl=eventInfo.targetEl;var packedEvent=eventInfo.packedEvent;var model=eventInfo.model;var view=eventInfo.view;// For event like 'globalout'.\nif(!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];}},afterTrigger:function afterTrigger(){// Make sure the eventInfo wont be used in next trigger.\nthis.eventInfo=null;}};/**\n * @type {Object} key: actionType.\n * @inner\n */var actions={};/**\n * Map eventType to actionType\n * @type {Object}\n */var eventActionMap={};/**\n * Data processor functions of each stage\n * @type {Array.<Object.<string, Function>>}\n * @inner\n */var dataProcessorFuncs=[];/**\n * @type {Array.<Function>}\n * @inner\n */var optionPreprocessorFuncs=[];/**\n * @type {Array.<Function>}\n * @inner\n */var postUpdateFuncs=[];/**\n * Visual encoding functions of each stage\n * @type {Array.<Object.<string, Function>>}\n */var visualFuncs=[];/**\n * Theme storage\n * @type {Object.<key, Object>}\n */var themeStorage={};/**\n * Loading effects\n */var loadingEffects={};var instances={};var connectedGroups={};var idBase=new Date()-0;var groupIdBase=new Date()-0;var DOM_ATTRIBUTE_KEY='_echarts_instance_';function enableConnect(chart){var STATUS_PENDING=0;var STATUS_UPDATING=1;var STATUS_UPDATED=2;var STATUS_KEY='__connectUpdateStatus';function updateConnectedChartsStatus(charts,status){for(var i=0;i<charts.length;i++){var otherChart=charts[i];otherChart[STATUS_KEY]=status;}}each(eventActionMap,function(actionType,eventType){chart._messageCenter.on(eventType,function(event){if(connectedGroups[chart.group]&&chart[STATUS_KEY]!==STATUS_PENDING){if(event&&event.escapeConnect){return;}var action=chart.makeActionFromEvent(event);var otherCharts=[];each(instances,function(otherChart){if(otherChart!==chart&&otherChart.group===chart.group){otherCharts.push(otherChart);}});updateConnectedChartsStatus(otherCharts,STATUS_PENDING);each(otherCharts,function(otherChart){if(otherChart[STATUS_KEY]!==STATUS_UPDATING){otherChart.dispatchAction(action);}});updateConnectedChartsStatus(otherCharts,STATUS_UPDATED);}});});}/**\n * @param {HTMLElement} dom\n * @param {Object} [theme]\n * @param {Object} opts\n * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default\n * @param {string} [opts.renderer] Can choose 'canvas' or 'svg' to render the chart.\n * @param {number} [opts.width] Use clientWidth of the input `dom` by default.\n *                              Can be 'auto' (the same as null/undefined)\n * @param {number} [opts.height] Use clientHeight of the input `dom` by default.\n *                               Can be 'auto' (the same as null/undefined)\n */function init(dom,theme$$1,opts){if(__DEV__){// Check version\nif(version$1.replace('.','')-0<dependencies.zrender.replace('.','')-0){throw new Error('zrender/src '+version$1+' is too old for ECharts '+version+'. Current version need ZRender '+dependencies.zrender+'+');}if(!dom){throw new Error('Initialize failed: invalid dom.');}}var existInstance=getInstanceByDom(dom);if(existInstance){if(__DEV__){console.warn('There is a chart instance already initialized on the dom.');}return existInstance;}if(__DEV__){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$$1,opts);chart.id='ec_'+idBase++;instances[chart.id]=chart;setAttribute(dom,DOM_ATTRIBUTE_KEY,chart.id);enableConnect(chart);return chart;}/**\n * @return {string|Array.<module:echarts~ECharts>} groupId\n */function connect(groupId){// Is array of charts\nif(isArray(groupId)){var charts=groupId;groupId=null;// If any chart has group\neach(charts,function(chart){if(chart.group!=null){groupId=chart.group;}});groupId=groupId||'g_'+groupIdBase++;each(charts,function(chart){chart.group=groupId;});}connectedGroups[groupId]=true;return groupId;}/**\n * @DEPRECATED\n * @return {string} groupId\n */function disConnect(groupId){connectedGroups[groupId]=false;}/**\n * @return {string} groupId\n */var disconnect=disConnect;/**\n * Dispose a chart instance\n * @param  {module:echarts~ECharts|HTMLDomElement|string} chart\n */function dispose(chart){if(typeof chart==='string'){chart=instances[chart];}else if(!(chart instanceof ECharts)){// Try to treat as dom\nchart=getInstanceByDom(chart);}if(chart instanceof ECharts&&!chart.isDisposed()){chart.dispose();}}/**\n * @param  {HTMLElement} dom\n * @return {echarts~ECharts}\n */function getInstanceByDom(dom){return instances[getAttribute(dom,DOM_ATTRIBUTE_KEY)];}/**\n * @param {string} key\n * @return {echarts~ECharts}\n */function getInstanceById(key){return instances[key];}/**\n * Register theme\n */function registerTheme(name,theme$$1){themeStorage[name]=theme$$1;}/**\n * Register option preprocessor\n * @param {Function} preprocessorFunc\n */function registerPreprocessor(preprocessorFunc){optionPreprocessorFuncs.push(preprocessorFunc);}/**\n * @param {number} [priority=1000]\n * @param {Object|Function} processor\n */function registerProcessor(priority,processor){normalizeRegister(dataProcessorFuncs,priority,processor,PRIORITY_PROCESSOR_FILTER);}/**\n * Register postUpdater\n * @param {Function} postUpdateFunc\n */function registerPostUpdate(postUpdateFunc){postUpdateFuncs.push(postUpdateFunc);}/**\n * Usage:\n * registerAction('someAction', 'someEvent', function () { ... });\n * registerAction('someAction', function () { ... });\n * registerAction(\n *     {type: 'someAction', event: 'someEvent', update: 'updateView'},\n *     function () { ... }\n * );\n *\n * @param {(string|Object)} actionInfo\n * @param {string} actionInfo.type\n * @param {string} [actionInfo.event]\n * @param {string} [actionInfo.update]\n * @param {string} [eventName]\n * @param {Function} action\n */function registerAction(actionInfo,eventName,action){if(typeof eventName==='function'){action=eventName;eventName='';}var actionType=isObject(actionInfo)?actionInfo.type:[actionInfo,actionInfo={event:eventName}][0];// Event name is all lowercase\nactionInfo.event=(actionInfo.event||actionType).toLowerCase();eventName=actionInfo.event;// Validate action type and event name.\nassert(ACTION_REG.test(actionType)&&ACTION_REG.test(eventName));if(!actions[actionType]){actions[actionType]={action:action,actionInfo:actionInfo};}eventActionMap[eventName]=actionType;}/**\n * @param {string} type\n * @param {*} CoordinateSystem\n */function registerCoordinateSystem(type,CoordinateSystem$$1){CoordinateSystemManager.register(type,CoordinateSystem$$1);}/**\n * Get dimensions of specified coordinate system.\n * @param {string} type\n * @return {Array.<string|Object>}\n */function getCoordinateSystemDimensions(type){var coordSysCreator=CoordinateSystemManager.get(type);if(coordSysCreator){return coordSysCreator.getDimensionsInfo?coordSysCreator.getDimensionsInfo():coordSysCreator.dimensions.slice();}}/**\n * Layout is a special stage of visual encoding\n * Most visual encoding like color are common for different chart\n * But each chart has it's own layout algorithm\n *\n * @param {number} [priority=1000]\n * @param {Function} layoutTask\n */function registerLayout(priority,layoutTask){normalizeRegister(visualFuncs,priority,layoutTask,PRIORITY_VISUAL_LAYOUT,'layout');}/**\n * @param {number} [priority=3000]\n * @param {module:echarts/stream/Task} visualTask\n */function registerVisual(priority,visualTask){normalizeRegister(visualFuncs,priority,visualTask,PRIORITY_VISUAL_CHART,'visual');}/**\n * @param {Object|Function} fn: {seriesType, createOnAllSeries, performRawSeries, reset}\n */function normalizeRegister(targetList,priority,fn,defaultPriority,visualType){if(isFunction(priority)||isObject(priority)){fn=priority;priority=defaultPriority;}if(__DEV__){if(isNaN(priority)||priority==null){throw new Error('Illegal priority');}// Check duplicate\neach(targetList,function(wrap){assert(wrap.__raw!==fn);});}var stageHandler=Scheduler.wrapStageHandler(fn,visualType);stageHandler.__prio=priority;stageHandler.__raw=fn;targetList.push(stageHandler);return stageHandler;}/**\n * @param {string} name\n */function registerLoading(name,loadingFx){loadingEffects[name]=loadingFx;}/**\n * @param {Object} opts\n * @param {string} [superClass]\n */function extendComponentModel(opts/*, superClass*/){// var Clazz = ComponentModel;\n// if (superClass) {\n//     var classType = parseClassType(superClass);\n//     Clazz = ComponentModel.getClass(classType.main, classType.sub, true);\n// }\nreturn ComponentModel.extend(opts);}/**\n * @param {Object} opts\n * @param {string} [superClass]\n */function extendComponentView(opts/*, superClass*/){// var Clazz = ComponentView;\n// if (superClass) {\n//     var classType = parseClassType(superClass);\n//     Clazz = ComponentView.getClass(classType.main, classType.sub, true);\n// }\nreturn Component$1.extend(opts);}/**\n * @param {Object} opts\n * @param {string} [superClass]\n */function extendSeriesModel(opts/*, superClass*/){// var Clazz = SeriesModel;\n// if (superClass) {\n//     superClass = 'series.' + superClass.replace('series.', '');\n//     var classType = parseClassType(superClass);\n//     Clazz = ComponentModel.getClass(classType.main, classType.sub, true);\n// }\nreturn SeriesModel.extend(opts);}/**\n * @param {Object} opts\n * @param {string} [superClass]\n */function extendChartView(opts/*, superClass*/){// var Clazz = ChartView;\n// if (superClass) {\n//     superClass = superClass.replace('series.', '');\n//     var classType = parseClassType(superClass);\n//     Clazz = ChartView.getClass(classType.main, true);\n// }\nreturn Chart.extend(opts);}/**\n * ZRender need a canvas context to do measureText.\n * But in node environment canvas may be created by node-canvas.\n * So we need to specify how to create a canvas instead of using document.createElement('canvas')\n *\n * Be careful of using it in the browser.\n *\n * @param {Function} creator\n * @example\n *     var Canvas = require('canvas');\n *     var echarts = require('echarts');\n *     echarts.setCanvasCreator(function () {\n *         // Small size is enough.\n *         return new Canvas(32, 32);\n *     });\n */function setCanvasCreator(creator){$override('createCanvas',creator);}/**\n * @param {string} mapName\n * @param {Array.<Object>|Object|string} geoJson\n * @param {Object} [specialAreas]\n *\n * @example GeoJSON\n *     $.get('USA.json', function (geoJson) {\n *         echarts.registerMap('USA', geoJson);\n *         // Or\n *         echarts.registerMap('USA', {\n *             geoJson: geoJson,\n *             specialAreas: {}\n *         })\n *     });\n *\n *     $.get('airport.svg', function (svg) {\n *         echarts.registerMap('airport', {\n *             svg: svg\n *         }\n *     });\n *\n *     echarts.registerMap('eu', [\n *         {svg: eu-topographic.svg},\n *         {geoJSON: eu.json}\n *     ])\n */function registerMap(mapName,geoJson,specialAreas){mapDataStorage.registerMap(mapName,geoJson,specialAreas);}/**\n * @param {string} mapName\n * @return {Object}\n */function getMap(mapName){// For backward compatibility, only return the first one.\nvar records=mapDataStorage.retrieveMap(mapName);return records&&records[0]&&{geoJson:records[0].geoJSON,specialAreas:records[0].specialAreas};}registerVisual(PRIORITY_VISUAL_GLOBAL,seriesColor);registerPreprocessor(backwardCompat);registerProcessor(PRIORITY_PROCESSOR_DATASTACK,dataStack);registerLoading('default',loadingDefault);// Default actions\nregisterAction({type:'highlight',event:'highlight',update:'highlight'},noop);registerAction({type:'downplay',event:'downplay',update:'downplay'},noop);// Default theme\nregisterTheme('light',lightTheme);registerTheme('dark',theme);// For backward compatibility, where the namespace `dataTool` will\n// be mounted on `echarts` is the extension `dataTool` is imported.\nvar dataTool={};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function defaultKeyGetter(item){return item;}/**\n * @param {Array} oldArr\n * @param {Array} newArr\n * @param {Function} oldKeyGetter\n * @param {Function} newKeyGetter\n * @param {Object} [context] Can be visited by this.context in callback.\n */function DataDiffer(oldArr,newArr,oldKeyGetter,newKeyGetter,context){this._old=oldArr;this._new=newArr;this._oldKeyGetter=oldKeyGetter||defaultKeyGetter;this._newKeyGetter=newKeyGetter||defaultKeyGetter;this.context=context;}DataDiffer.prototype={constructor:DataDiffer,/**\n     * Callback function when add a data\n     */add:function add(func){this._add=func;return this;},/**\n     * Callback function when update a data\n     */update:function update(func){this._update=func;return this;},/**\n     * Callback function when remove a data\n     */remove:function remove(func){this._remove=func;return this;},execute:function execute(){var oldArr=this._old;var newArr=this._new;var oldDataIndexMap={};var newDataIndexMap={};var oldDataKeyArr=[];var newDataKeyArr=[];var i;initIndexMap(oldArr,oldDataIndexMap,oldDataKeyArr,'_oldKeyGetter',this);initIndexMap(newArr,newDataIndexMap,newDataKeyArr,'_newKeyGetter',this);for(i=0;i<oldArr.length;i++){var key=oldDataKeyArr[i];var idx=newDataIndexMap[key];// idx can never be empty array here. see 'set null' logic below.\nif(idx!=null){// Consider there is duplicate key (for example, use dataItem.name as key).\n// We should make sure every item in newArr and oldArr can be visited.\nvar len=idx.length;if(len){len===1&&(newDataIndexMap[key]=null);idx=idx.shift();}else{newDataIndexMap[key]=null;}this._update&&this._update(idx,i);}else{this._remove&&this._remove(i);}}for(var i=0;i<newDataKeyArr.length;i++){var key=newDataKeyArr[i];if(newDataIndexMap.hasOwnProperty(key)){var idx=newDataIndexMap[key];if(idx==null){continue;}// idx can never be empty array here. see 'set null' logic above.\nif(!idx.length){this._add&&this._add(idx);}else{for(var j=0,len=idx.length;j<len;j++){this._add&&this._add(idx[j]);}}}}}};function initIndexMap(arr,map,keyArr,keyGetterName,dataDiffer){for(var i=0;i<arr.length;i++){// Add prefix to avoid conflict with Object.prototype.\nvar key='_ec_'+dataDiffer[keyGetterName](arr[i],i);var existence=map[key];if(existence==null){keyArr.push(key);map[key]=i;}else{if(!existence.length){map[key]=existence=[existence];}existence.push(i);}}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var OTHER_DIMENSIONS=createHashMap(['tooltip','label','itemName','itemId','seriesName']);function summarizeDimensions(data){var summary={};var encode=summary.encode={};var notExtraCoordDimMap=createHashMap();var defaultedLabel=[];var defaultedTooltip=[];// See the comment of `List.js#userOutput`.\nvar userOutput=summary.userOutput={dimensionNames:data.dimensions.slice(),encode:{}};each$1(data.dimensions,function(dimName){var dimItem=data.getDimensionInfo(dimName);var coordDim=dimItem.coordDim;if(coordDim){if(__DEV__){assert$1(OTHER_DIMENSIONS.get(coordDim)==null);}var coordDimIndex=dimItem.coordDimIndex;getOrCreateEncodeArr(encode,coordDim)[coordDimIndex]=dimName;if(!dimItem.isExtraCoord){notExtraCoordDimMap.set(coordDim,1);// Use the last coord dim (and label friendly) as default label,\n// because when dataset is used, it is hard to guess which dimension\n// can be value dimension. If both show x, y on label is not look good,\n// and conventionally y axis is focused more.\nif(mayLabelDimType(dimItem.type)){defaultedLabel[0]=dimName;}// User output encode do not contain generated coords.\n// And it only has index. User can use index to retrieve value from the raw item array.\ngetOrCreateEncodeArr(userOutput.encode,coordDim)[coordDimIndex]=dimItem.index;}if(dimItem.defaultTooltip){defaultedTooltip.push(dimName);}}OTHER_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];// ??? FIXME extra coord should not be set in dataDimsOnCoord.\n// But should fix the case that radar axes: simplify the logic\n// of `completeDimension`, remove `extraPrefix`.\nencodeFirstDimNotExtra[coordDim]=dimArr[0];// Not necessary to remove duplicate, because a data\n// dim canot on more than one coordDim.\ndataDimsOnCoord=dataDimsOnCoord.concat(dimArr);});summary.dataDimsOnCoord=dataDimsOnCoord;summary.encodeFirstDimNotExtra=encodeFirstDimNotExtra;var encodeLabel=encode.label;// FIXME `encode.label` is not recommanded, because formatter can not be set\n// in this way. Use label.formatter instead. May be remove this approach someday.\nif(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){// In most cases, ordinal and time do not suitable for label.\n// Ordinal info can be displayed on axis. Time is too long.\nreturn!(dimType==='ordinal'||dimType==='time');}// function findTheLastDimMayLabel(data) {\n//     // Get last value dim\n//     var dimensions = data.dimensions.slice();\n//     var valueType;\n//     var valueDim;\n//     while (dimensions.length && (\n//         valueDim = dimensions.pop(),\n//         valueType = data.getDimensionInfo(valueDim).type,\n//         valueType === 'ordinal' || valueType === 'time'\n//     )) {} // jshint ignore:line\n//     return valueDim;\n// }\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @class\n * @param {Object|DataDimensionInfo} [opt] All of the fields will be shallow copied.\n */function DataDimensionInfo(opt){if(opt!=null){extend(this,opt);}/**\n     * Dimension name.\n     * Mandatory.\n     * @type {string}\n     */ // this.name;\n/**\n     * The origin name in dimsDef, see source helper.\n     * If displayName given, the tooltip will displayed vertically.\n     * Optional.\n     * @type {string}\n     */ // this.displayName;\n/**\n     * Which coordSys dimension this dimension mapped to.\n     * A `coordDim` can be a \"coordSysDim\" that the coordSys required\n     * (for example, an item in `coordSysDims` of `model/referHelper#CoordSysInfo`),\n     * or an generated \"extra coord name\" if does not mapped to any \"coordSysDim\"\n     * (That is determined by whether `isExtraCoord` is `true`).\n     * Mandatory.\n     * @type {string}\n     */ // this.coordDim;\n/**\n     * The index of this dimension in `series.encode[coordDim]`.\n     * Mandatory.\n     * @type {number}\n     */ // this.coordDimIndex;\n/**\n     * Dimension type. The enumerable values are the key of\n     * `dataCtors` of `data/List`.\n     * Optional.\n     * @type {string}\n     */ // this.type;\n/**\n     * This index of this dimension info in `data/List#_dimensionInfos`.\n     * Mandatory after added to `data/List`.\n     * @type {number}\n     */ // this.index;\n/**\n     * The format of `otherDims` is:\n     * ```js\n     * {\n     *     tooltip: number optional,\n     *     label: number optional,\n     *     itemName: number optional,\n     *     seriesName: number optional,\n     * }\n     * ```\n     *\n     * A `series.encode` can specified these fields:\n     * ```js\n     * encode: {\n     *     // \"3, 1, 5\" is the index of data dimension.\n     *     tooltip: [3, 1, 5],\n     *     label: [0, 3],\n     *     ...\n     * }\n     * ```\n     * `otherDims` is the parse result of the `series.encode` above, like:\n     * ```js\n     * // Suppose the index of this data dimension is `3`.\n     * this.otherDims = {\n     *     // `3` is at the index `0` of the `encode.tooltip`\n     *     tooltip: 0,\n     *     // `3` is at the index `1` of the `encode.tooltip`\n     *     label: 1\n     * };\n     * ```\n     *\n     * This prop should never be `null`/`undefined` after initialized.\n     * @type {Object}\n     */this.otherDims={};/**\n     * Be `true` if this dimension is not mapped to any \"coordSysDim\" that the\n     * \"coordSys\" required.\n     * Mandatory.\n     * @type {boolean}\n     */ // this.isExtraCoord;\n/**\n     * @type {module:data/OrdinalMeta}\n     */ // this.ordinalMeta;\n/**\n     * Whether to create inverted indices.\n     * @type {boolean}\n     */ // this.createInvertedIndices;\n}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /* global Float64Array, Int32Array, Uint32Array, Uint16Array */ /**\n * List for data storage\n * @module echarts/data/List\n */var isObject$4=isObject$1;var UNDEFINED='undefined';var INDEX_NOT_FOUND=-1;// Use prefix to avoid index to be the same as otherIdList[idx],\n// which will cause weird udpate animation.\nvar ID_PREFIX='e\\0\\0';var dataCtors={'float':(typeof Float64Array===\"undefined\"?\"undefined\":_typeof(Float64Array))===UNDEFINED?Array:Float64Array,'int':(typeof Int32Array===\"undefined\"?\"undefined\":_typeof(Int32Array))===UNDEFINED?Array:Int32Array,// Ordinal data type can be string or int\n'ordinal':Array,'number':Array,'time':Array};// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is\n// different from the Ctor of typed array.\nvar CtorUint32Array=(typeof Uint32Array===\"undefined\"?\"undefined\":_typeof(Uint32Array))===UNDEFINED?Array:Uint32Array;var CtorInt32Array=(typeof Int32Array===\"undefined\"?\"undefined\":_typeof(Int32Array))===UNDEFINED?Array:Int32Array;var CtorUint16Array=(typeof Uint16Array===\"undefined\"?\"undefined\":_typeof(Uint16Array))===UNDEFINED?Array:Uint16Array;function getIndicesCtor(list){// The possible max value in this._indicies is always this._rawCount despite of filtering.\nreturn list._rawCount>65535?CtorUint32Array:CtorUint16Array;}function cloneChunk(originalChunk){var Ctor=originalChunk.constructor;// Only shallow clone is enough when Array.\nreturn Ctor===Array?originalChunk.slice():new Ctor(originalChunk);}var TRANSFERABLE_PROPERTIES=['hasItemOption','_nameList','_idList','_invertedIndicesMap','_rawData','_chunkSize','_chunkCount','_dimValueGetter','_count','_rawCount','_nameDimIdx','_idDimIdx'];var CLONE_PROPERTIES=['_extent','_approximateExtent','_rawExtent'];function transferProperties(target,source){each$1(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods||[]),function(propName){if(source.hasOwnProperty(propName)){target[propName]=source[propName];}});target.__wrappedMethods=source.__wrappedMethods;each$1(CLONE_PROPERTIES,function(propName){target[propName]=_clone(source[propName]);});target._calculationInfo=extend(source._calculationInfo);}/**\n * @constructor\n * @alias module:echarts/data/List\n *\n * @param {Array.<string|Object|module:data/DataDimensionInfo>} dimensions\n *      For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].\n *      Dimensions should be concrete names like x, y, z, lng, lat, angle, radius\n * @param {module:echarts/model/Model} hostModel\n */var List=function List(dimensions,hostModel){dimensions=dimensions||['x','y'];var dimensionInfos={};var dimensionNames=[];var invertedIndicesMap={};for(var i=0;i<dimensions.length;i++){// Use the original dimensions[i], where other flag props may exists.\nvar dimensionInfo=dimensions[i];if(isString(dimensionInfo)){dimensionInfo=new DataDimensionInfo({name:dimensionInfo});}else if(!(dimensionInfo instanceof DataDimensionInfo)){dimensionInfo=new DataDimensionInfo(dimensionInfo);}var dimensionName=dimensionInfo.name;dimensionInfo.type=dimensionInfo.type||'float';if(!dimensionInfo.coordDim){dimensionInfo.coordDim=dimensionName;dimensionInfo.coordDimIndex=0;}dimensionInfo.otherDims=dimensionInfo.otherDims||{};dimensionNames.push(dimensionName);dimensionInfos[dimensionName]=dimensionInfo;dimensionInfo.index=i;if(dimensionInfo.createInvertedIndices){invertedIndicesMap[dimensionName]=[];}}/**\n     * @readOnly\n     * @type {Array.<string>}\n     */this.dimensions=dimensionNames;/**\n     * Infomation of each data dimension, like data type.\n     * @type {Object}\n     */this._dimensionInfos=dimensionInfos;/**\n     * @type {module:echarts/model/Model}\n     */this.hostModel=hostModel;/**\n     * @type {module:echarts/model/Model}\n     */this.dataType;/**\n     * Indices stores the indices of data subset after filtered.\n     * This data subset will be used in chart.\n     * @type {Array.<number>}\n     * @readOnly\n     */this._indices=null;this._count=0;this._rawCount=0;/**\n     * Data storage\n     * @type {Object.<key, Array.<TypedArray|Array>>}\n     * @private\n     */this._storage={};/**\n     * @type {Array.<string>}\n     */this._nameList=[];/**\n     * @type {Array.<string>}\n     */this._idList=[];/**\n     * Models of data option is stored sparse for optimizing memory cost\n     * @type {Array.<module:echarts/model/Model>}\n     * @private\n     */this._optionModels=[];/**\n     * Global visual properties after visual coding\n     * @type {Object}\n     * @private\n     */this._visual={};/**\n     * Globel layout properties.\n     * @type {Object}\n     * @private\n     */this._layout={};/**\n     * Item visual properties after visual coding\n     * @type {Array.<Object>}\n     * @private\n     */this._itemVisuals=[];/**\n     * Key: visual type, Value: boolean\n     * @type {Object}\n     * @readOnly\n     */this.hasItemVisual={};/**\n     * Item layout properties after layout\n     * @type {Array.<Object>}\n     * @private\n     */this._itemLayouts=[];/**\n     * Graphic elemnents\n     * @type {Array.<module:zrender/Element>}\n     * @private\n     */this._graphicEls=[];/**\n     * Max size of each chunk.\n     * @type {number}\n     * @private\n     */this._chunkSize=1e5;/**\n     * @type {number}\n     * @private\n     */this._chunkCount=0;/**\n     * @type {Array.<Array|Object>}\n     * @private\n     */this._rawData;/**\n     * Raw extent will not be cloned, but only transfered.\n     * It will not be calculated util needed.\n     * key: dim,\n     * value: {end: number, extent: Array.<number>}\n     * @type {Object}\n     * @private\n     */this._rawExtent={};/**\n     * @type {Object}\n     * @private\n     */this._extent={};/**\n     * key: dim\n     * value: extent\n     * @type {Object}\n     * @private\n     */this._approximateExtent={};/**\n     * Cache summary info for fast visit. See \"dimensionHelper\".\n     * @type {Object}\n     * @private\n     */this._dimensionsSummary=summarizeDimensions(this);/**\n     * @type {Object.<Array|TypedArray>}\n     * @private\n     */this._invertedIndicesMap=invertedIndicesMap;/**\n     * @type {Object}\n     * @private\n     */this._calculationInfo={};/**\n     * User output info of this data.\n     * DO NOT use it in other places!\n     *\n     * When preparing user params for user callbacks, we have\n     * to clone these inner data structures to prevent users\n     * from modifying them to effect built-in logic. And for\n     * performance consideration we make this `userOutput` to\n     * avoid clone them too many times.\n     *\n     * @type {Object}\n     * @readOnly\n     */this.userOutput=this._dimensionsSummary.userOutput;};var listProto=List.prototype;listProto.type='list';/**\n * If each data item has it's own option\n * @type {boolean}\n */listProto.hasItemOption=true;/**\n * The meanings of the input parameter `dim`:\n *\n * + If dim is a number (e.g., `1`), it means the index of the dimension.\n *   For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.\n * + If dim is a number-like string (e.g., `\"1\"`):\n *     + If there is the same concrete dim name defined in `this.dimensions`, it means that concrete name.\n *     + If not, it will be converted to a number, which means the index of the dimension.\n *        (why? because of the backward compatbility. We have been tolerating number-like string in\n *        dimension setting, although now it seems that it is not a good idea.)\n *     For example, `visualMap[i].dimension: \"1\"` is the same meaning as `visualMap[i].dimension: 1`,\n *     if no dimension name is defined as `\"1\"`.\n * + If dim is a not-number-like string, it means the concrete dim name.\n *   For example, it can be be default name `\"x\"`, `\"y\"`, `\"z\"`, `\"lng\"`, `\"lat\"`, `\"angle\"`, `\"radius\"`,\n *   or customized in `dimensions` property of option like `\"age\"`.\n *\n * Get dimension name\n * @param {string|number} dim See above.\n * @return {string} Concrete dim name.\n */listProto.getDimension=function(dim){if(typeof dim==='number'// If being a number-like string but not being defined a dimension name.\n||!isNaN(dim)&&!this._dimensionInfos.hasOwnProperty(dim)){dim=this.dimensions[dim];}return dim;};/**\n * Get type and calculation info of particular dimension\n * @param {string|number} dim\n *        Dimension can be concrete names like x, y, z, lng, lat, angle, radius\n *        Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'\n */listProto.getDimensionInfo=function(dim){// Do not clone, because there may be categories in dimInfo.\nreturn this._dimensionInfos[this.getDimension(dim)];};/**\n * @return {Array.<string>} concrete dimension name list on coord.\n */listProto.getDimensionsOnCoord=function(){return this._dimensionsSummary.dataDimsOnCoord.slice();};/**\n * @param {string} coordDim\n * @param {number} [idx] A coordDim may map to more than one data dim.\n *        If idx is `true`, return a array of all mapped dims.\n *        If idx is not specified, return the first dim not extra.\n * @return {string|Array.<string>} concrete data dim.\n *        If idx is number, and not found, return null/undefined.\n *        If idx is `true`, and not found, return empty array (always return array).\n */listProto.mapDimension=function(coordDim,idx){var dimensionsSummary=this._dimensionsSummary;if(idx==null){return dimensionsSummary.encodeFirstDimNotExtra[coordDim];}var dims=dimensionsSummary.encode[coordDim];return idx===true// always return array if idx is `true`\n?(dims||[]).slice():dims&&dims[idx];};/**\n * Initialize from data\n * @param {Array.<Object|number|Array>} data source or data or data provider.\n * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and\n *        default label/tooltip.\n *        A name can be specified in encode.itemName,\n *        or dataItem.name (only for series option data),\n *        or provided in nameList from outside.\n * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number\n */listProto.initData=function(data,nameList,dimValueGetter){var notProvider=Source.isInstance(data)||isArrayLike(data);if(notProvider){data=new DefaultDataProvider(data,this.dimensions.length);}if(__DEV__){if(!notProvider&&(typeof data.getItem!=='function'||typeof data.count!=='function')){throw new Error('Inavlid data provider.');}}this._rawData=data;// Clear\nthis._storage={};this._indices=null;this._nameList=nameList||[];this._idList=[];this._nameRepeatCount={};if(!dimValueGetter){this.hasItemOption=false;}/**\n     * @readOnly\n     */this.defaultDimValueGetter=defaultDimValueGetters[this._rawData.getSource().sourceFormat];// Default dim value getter\nthis._dimValueGetter=dimValueGetter=dimValueGetter||this.defaultDimValueGetter;this._dimValueGetterArrayRows=defaultDimValueGetters.arrayRows;// Reset raw extent.\nthis._rawExtent={};this._initDataFromProvider(0,data.count());// If data has no item option.\nif(data.pure){this.hasItemOption=false;}};listProto.getProvider=function(){return this._rawData;};/**\n * Caution: Can be only called on raw data (before `this._indices` created).\n */listProto.appendData=function(data){if(__DEV__){assert$1(!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);};/**\n * Caution: Can be only called on raw data (before `this._indices` created).\n * This method does not modify `rawData` (`dataProvider`), but only\n * add values to storage.\n *\n * The final count will be increased by `Math.max(values.length, names.length)`.\n *\n * @param {Array.<Array.<*>>} values That is the SourceType: 'arrayRows', like\n *        [\n *            [12, 33, 44],\n *            [NaN, 43, 1],\n *            ['-', 'asdf', 0]\n *        ]\n *        Each item is exaclty cooresponding to a dimension.\n * @param {Array.<string>} [names]\n */listProto.appendValues=function(values,names){var chunkSize=this._chunkSize;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);var originalChunkCount=this._chunkCount;for(var i=0;i<dimLen;i++){var dim=dimensions[i];if(!rawExtent[dim]){rawExtent[dim]=getInitialExtent();}if(!storage[dim]){storage[dim]=[];}prepareChunks(storage,this._dimensionInfos[dim],chunkSize,originalChunkCount,end);this._chunkCount=storage[dim].length;}var emptyDataItem=new Array(dimLen);for(var idx=start;idx<end;idx++){var sourceIdx=idx-start;var chunkIndex=Math.floor(idx/chunkSize);var chunkOffset=idx%chunkSize;// Store the data by dimensions\nfor(var k=0;k<dimLen;k++){var dim=dimensions[k];var val=this._dimValueGetterArrayRows(values[sourceIdx]||emptyDataItem,dim,sourceIdx,k);storage[dim][chunkIndex][chunkOffset]=val;var dimRawExtent=rawExtent[dim];val<dimRawExtent[0]&&(dimRawExtent[0]=val);val>dimRawExtent[1]&&(dimRawExtent[1]=val);}if(names){this._nameList[idx]=names[sourceIdx];}}this._rawCount=this._count=end;// Reset data extent\nthis._extent={};prepareInvertedIndex(this);};listProto._initDataFromProvider=function(start,end){// Optimize.\nif(start>=end){return;}var chunkSize=this._chunkSize;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 nameRepeatCount=this._nameRepeatCount={};var nameDimIdx;var originalChunkCount=this._chunkCount;for(var i=0;i<dimLen;i++){var dim=dimensions[i];if(!rawExtent[dim]){rawExtent[dim]=getInitialExtent();}var dimInfo=dimensionInfoMap[dim];if(dimInfo.otherDims.itemName===0){nameDimIdx=this._nameDimIdx=i;}if(dimInfo.otherDims.itemId===0){this._idDimIdx=i;}if(!storage[dim]){storage[dim]=[];}prepareChunks(storage,dimInfo,chunkSize,originalChunkCount,end);this._chunkCount=storage[dim].length;}var dataItem=new Array(dimLen);for(var idx=start;idx<end;idx++){// NOTICE: Try not to write things into dataItem\ndataItem=rawData.getItem(idx,dataItem);// Each data item is value\n// [1, 2]\n// 2\n// Bar chart, line chart which uses category axis\n// only gives the 'y' value. 'x' value is the indices of category\n// Use a tempValue to normalize the value to be a (x, y) value\nvar chunkIndex=Math.floor(idx/chunkSize);var chunkOffset=idx%chunkSize;// Store the data by dimensions\nfor(var k=0;k<dimLen;k++){var dim=dimensions[k];var dimStorage=storage[dim][chunkIndex];// PENDING NULL is empty or zero\nvar val=this._dimValueGetter(dataItem,dim,idx,k);dimStorage[chunkOffset]=val;var dimRawExtent=rawExtent[dim];val<dimRawExtent[0]&&(dimRawExtent[0]=val);val>dimRawExtent[1]&&(dimRawExtent[1]=val);}// ??? FIXME not check by pure but sourceFormat?\n// TODO refactor these logic.\nif(!rawData.pure){var name=nameList[idx];if(dataItem&&name==null){// If dataItem is {name: ...}, it has highest priority.\n// That is appropriate for many common cases.\nif(dataItem.name!=null){// There is no other place to persistent dataItem.name,\n// so save it to nameList.\nnameList[idx]=name=dataItem.name;}else if(nameDimIdx!=null){var nameDim=dimensions[nameDimIdx];var nameDimChunk=storage[nameDim][chunkIndex];if(nameDimChunk){name=nameDimChunk[chunkOffset];var ordinalMeta=dimensionInfoMap[nameDim].ordinalMeta;if(ordinalMeta&&ordinalMeta.categories.length){name=ordinalMeta.categories[name];}}}}// Try using the id in option\n// id or name is used on dynamical data, mapping old and new items.\nvar id=dataItem==null?null:dataItem.id;if(id==null&&name!=null){// Use name as id and add counter to avoid same name\nnameRepeatCount[name]=nameRepeatCount[name]||0;id=name;if(nameRepeatCount[name]>0){id+='__ec__'+nameRepeatCount[name];}nameRepeatCount[name]++;}id!=null&&(idList[idx]=id);}}if(!rawData.persistent&&rawData.clean){// Clean unused data if data source is typed array.\nrawData.clean();}this._rawCount=this._count=end;// Reset data extent\nthis._extent={};prepareInvertedIndex(this);};function prepareChunks(storage,dimInfo,chunkSize,chunkCount,end){var DataCtor=dataCtors[dimInfo.type];var lastChunkIndex=chunkCount-1;var dim=dimInfo.name;var resizeChunkArray=storage[dim][lastChunkIndex];if(resizeChunkArray&&resizeChunkArray.length<chunkSize){var newStore=new DataCtor(Math.min(end-lastChunkIndex*chunkSize,chunkSize));// The cost of the copy is probably inconsiderable\n// within the initial chunkSize.\nfor(var j=0;j<resizeChunkArray.length;j++){newStore[j]=resizeChunkArray[j];}storage[dim][lastChunkIndex]=newStore;}// Create new chunks.\nfor(var k=chunkCount*chunkSize;k<end;k+=chunkSize){storage[dim].push(new DataCtor(Math.min(end-k,chunkSize)));}}function prepareInvertedIndex(list){var invertedIndicesMap=list._invertedIndicesMap;each$1(invertedIndicesMap,function(invertedIndices,dim){var dimInfo=list._dimensionInfos[dim];// Currently, only dimensions that has ordinalMeta can create inverted indices.\nvar ordinalMeta=dimInfo.ordinalMeta;if(ordinalMeta){invertedIndices=invertedIndicesMap[dim]=new CtorInt32Array(ordinalMeta.categories.length);// The default value of TypedArray is 0. To avoid miss\n// mapping to 0, we should set it as INDEX_NOT_FOUND.\nfor(var i=0;i<invertedIndices.length;i++){invertedIndices[i]=INDEX_NOT_FOUND;}for(var i=0;i<list._count;i++){// Only support the case that all values are distinct.\ninvertedIndices[list.get(dim,i)]=i;}}});}function getRawValueFromStore(list,dimIndex,rawIndex){var val;if(dimIndex!=null){var chunkSize=list._chunkSize;var chunkIndex=Math.floor(rawIndex/chunkSize);var chunkOffset=rawIndex%chunkSize;var dim=list.dimensions[dimIndex];var chunk=list._storage[dim][chunkIndex];if(chunk){val=chunk[chunkOffset];var ordinalMeta=list._dimensionInfos[dim].ordinalMeta;if(ordinalMeta&&ordinalMeta.categories.length){val=ordinalMeta.categories[val];}}}return val;}/**\n * @return {number}\n */listProto.count=function(){return this._count;};listProto.getIndices=function(){var newIndices;var indices=this._indices;if(indices){var Ctor=indices.constructor;var thisCount=this._count;// `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.\nif(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);var newIndices=new Ctor(this.count());for(var i=0;i<newIndices.length;i++){newIndices[i]=i;}}return newIndices;};/**\n * Get value. Return NaN if idx is out of range.\n * @param {string} dim Dim must be concrete name.\n * @param {number} idx\n * @param {boolean} stack\n * @return {number}\n */listProto.get=function(dim,idx/*, stack */){if(!(idx>=0&&idx<this._count)){return NaN;}var storage=this._storage;if(!storage[dim]){// TODO Warn ?\nreturn NaN;}idx=this.getRawIndex(idx);var chunkIndex=Math.floor(idx/this._chunkSize);var chunkOffset=idx%this._chunkSize;var chunkStore=storage[dim][chunkIndex];var value=chunkStore[chunkOffset];// FIXME ordinal data type is not stackable\n// if (stack) {\n//     var dimensionInfo = this._dimensionInfos[dim];\n//     if (dimensionInfo && dimensionInfo.stackable) {\n//         var stackedOn = this.stackedOn;\n//         while (stackedOn) {\n//             // Get no stacked data of stacked on\n//             var stackedValue = stackedOn.get(dim, idx);\n//             // Considering positive stack, negative stack and empty data\n//             if ((value >= 0 && stackedValue > 0)  // Positive stack\n//                 || (value <= 0 && stackedValue < 0) // Negative stack\n//             ) {\n//                 value += stackedValue;\n//             }\n//             stackedOn = stackedOn.stackedOn;\n//         }\n//     }\n// }\nreturn value;};/**\n * @param {string} dim concrete dim\n * @param {number} rawIndex\n * @return {number|string}\n */listProto.getByRawIndex=function(dim,rawIdx){if(!(rawIdx>=0&&rawIdx<this._rawCount)){return NaN;}var dimStore=this._storage[dim];if(!dimStore){// TODO Warn ?\nreturn NaN;}var chunkIndex=Math.floor(rawIdx/this._chunkSize);var chunkOffset=rawIdx%this._chunkSize;var chunkStore=dimStore[chunkIndex];return chunkStore[chunkOffset];};/**\n * FIXME Use `get` on chrome maybe slow(in filterSelf and selectRange).\n * Hack a much simpler _getFast\n * @private\n */listProto._getFast=function(dim,rawIdx){var chunkIndex=Math.floor(rawIdx/this._chunkSize);var chunkOffset=rawIdx%this._chunkSize;var chunkStore=this._storage[dim][chunkIndex];return chunkStore[chunkOffset];};/**\n * Get value for multi dimensions.\n * @param {Array.<string>} [dimensions] If ignored, using all dimensions.\n * @param {number} idx\n * @return {number}\n */listProto.getValues=function(dimensions,idx/*, stack */){var values=[];if(!isArray(dimensions)){// stack = idx;\nidx=dimensions;dimensions=this.dimensions;}for(var i=0,len=dimensions.length;i<len;i++){values.push(this.get(dimensions[i],idx/*, stack */));}return values;};/**\n * If value is NaN. Inlcuding '-'\n * Only check the coord dimensions.\n * @param {string} dim\n * @param {number} idx\n * @return {number}\n */listProto.hasValue=function(idx){var dataDimsOnCoord=this._dimensionsSummary.dataDimsOnCoord;for(var i=0,len=dataDimsOnCoord.length;i<len;i++){// Ordinal type originally can be string or number.\n// But when an ordinal type is used on coord, it can\n// not be string but only number. So we can also use isNaN.\nif(isNaN(this.get(dataDimsOnCoord[i],idx))){return false;}}return true;};/**\n * Get extent of data in one dimension\n * @param {string} dim\n * @param {boolean} stack\n */listProto.getDataExtent=function(dim/*, stack */){// Make sure use concrete dim as cache name.\ndim=this.getDimension(dim);var dimData=this._storage[dim];var initialExtent=getInitialExtent();// stack = !!((stack || false) && this.getCalculationInfo(dim));\nif(!dimData){return initialExtent;}// Make more strict checkings to ensure hitting cache.\nvar currEnd=this.count();// var cacheName = [dim, !!stack].join('_');\n// var cacheName = dim;\n// Consider the most cases when using data zoom, `getDataExtent`\n// happened before filtering. We cache raw extent, which is not\n// necessary to be cleared and recalculated when restore data.\nvar useRaw=!this._indices;// && !stack;\nvar 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 value = stack ? this.get(dim, i, true) : this._getFast(dim, this.getRawIndex(i));\nvar value=this._getFast(dim,this.getRawIndex(i));value<min&&(min=value);value>max&&(max=value);}dimExtent=[min,max];this._extent[dim]=dimExtent;return dimExtent;};/**\n * Optimize for the scenario that data is filtered by a given extent.\n * Consider that if data amount is more than hundreds of thousand,\n * extent calculation will cost more than 10ms and the cache will\n * be erased because of the filtering.\n */listProto.getApproximateExtent=function(dim/*, stack */){dim=this.getDimension(dim);return this._approximateExtent[dim]||this.getDataExtent(dim/*, stack */);};listProto.setApproximateExtent=function(extent,dim/*, stack */){dim=this.getDimension(dim);this._approximateExtent[dim]=extent.slice();};/**\n * @param {string} key\n * @return {*}\n */listProto.getCalculationInfo=function(key){return this._calculationInfo[key];};/**\n * @param {string|Object} key or k-v object\n * @param {*} [value]\n */listProto.setCalculationInfo=function(key,value){isObject$4(key)?extend(this._calculationInfo,key):this._calculationInfo[key]=value;};/**\n * Get sum of data in one dimension\n * @param {string} dim\n */listProto.getSum=function(dim/*, stack */){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/*, stack */);if(!isNaN(value)){sum+=value;}}}return sum;};/**\n * Get median of data in one dimension\n * @param {string} dim\n */listProto.getMedian=function(dim/*, stack */){var dimDataArray=[];// map all data of one dimension\nthis.each(dim,function(val,idx){if(!isNaN(val)){dimDataArray.push(val);}});// TODO\n// Use quick select?\n// immutability & sort\nvar sortedDimDataArray=[].concat(dimDataArray).sort(function(a,b){return a-b;});var len=this.count();// calculate median\nreturn len===0?0:len%2===1?sortedDimDataArray[(len-1)/2]:(sortedDimDataArray[len/2]+sortedDimDataArray[len/2-1])/2;};// /**\n//  * Retreive the index with given value\n//  * @param {string} dim Concrete dimension.\n//  * @param {number} value\n//  * @return {number}\n//  */\n// Currently incorrect: should return dataIndex but not rawIndex.\n// Do not fix it until this method is to be used somewhere.\n// FIXME Precision of float value\n// listProto.indexOf = function (dim, value) {\n//     var storage = this._storage;\n//     var dimData = storage[dim];\n//     var chunkSize = this._chunkSize;\n//     if (dimData) {\n//         for (var i = 0, len = this.count(); i < len; i++) {\n//             var chunkIndex = Math.floor(i / chunkSize);\n//             var chunkOffset = i % chunkSize;\n//             if (dimData[chunkIndex][chunkOffset] === value) {\n//                 return i;\n//             }\n//         }\n//     }\n//     return -1;\n// };\n/**\n * Only support the dimension which inverted index created.\n * Do not support other cases until required.\n * @param {string} concrete dim\n * @param {number|string} value\n * @return {number} rawIndex\n */listProto.rawIndexOf=function(dim,value){var invertedIndices=dim&&this._invertedIndicesMap[dim];if(__DEV__){if(!invertedIndices){throw new Error('Do not supported yet');}}var rawIndex=invertedIndices[value];if(rawIndex==null||isNaN(rawIndex)){return INDEX_NOT_FOUND;}return rawIndex;};/**\n * Retreive the index with given name\n * @param {number} idx\n * @param {number} name\n * @return {number}\n */listProto.indexOfName=function(name){for(var i=0,len=this.count();i<len;i++){if(this.getName(i)===name){return i;}}return-1;};/**\n * Retreive the index with given raw data index\n * @param {number} idx\n * @param {number} name\n * @return {number}\n */listProto.indexOfRawIndex=function(rawIndex){if(rawIndex>=this._rawCount||rawIndex<0){return-1;}if(!this._indices){return rawIndex;}// Indices are ascending\nvar indices=this._indices;// If rawIndex === dataIndex\nvar 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;};/**\n * Retreive the index of nearest value\n * @param {string} dim\n * @param {number} value\n * @param {number} [maxDistance=Infinity]\n * @return {Array.<number>} If and only if multiple indices has\n *        the same value, they are put to the result.\n */listProto.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;// Check the test case of `test/ut/spec/data/List.js`.\nfor(var i=0,len=this.count();i<len;i++){var diff=value-this.get(dim,i);var dist=Math.abs(diff);if(dist<=maxDistance){// When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,\n// we'd better not push both of them to `nearestIndices`, otherwise it is easy to\n// get more than one item in `nearestIndices` (more specifically, in `tooltip`).\n// So we chose the one that `diff >= 0` in this csae.\n// But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them\n// should be push to `nearestIndices`.\nif(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;};/**\n * Get raw data index\n * @param {number} idx\n * @return {number}\n */listProto.getRawIndex=getRawIndexWithoutIndices;function getRawIndexWithoutIndices(idx){return idx;}function getRawIndexWithIndices(idx){if(idx<this._count&&idx>=0){return this._indices[idx];}return-1;}/**\n * Get raw data item\n * @param {number} idx\n * @return {number}\n */listProto.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));}};/**\n * @param {number} idx\n * @param {boolean} [notDefaultIdx=false]\n * @return {string}\n */listProto.getName=function(idx){var rawIndex=this.getRawIndex(idx);return this._nameList[rawIndex]||getRawValueFromStore(this,this._nameDimIdx,rawIndex)||'';};/**\n * @param {number} idx\n * @param {boolean} [notDefaultIdx=false]\n * @return {string}\n */listProto.getId=function(idx){return getId(this,this.getRawIndex(idx));};function getId(list,rawIndex){var id=list._idList[rawIndex];if(id==null){id=getRawValueFromStore(list,list._idDimIdx,rawIndex);}if(id==null){// FIXME Check the usage in graph, should not use prefix.\nid=ID_PREFIX+rawIndex;}return id;}function normalizeDimensions(dimensions){if(!isArray(dimensions)){dimensions=[dimensions];}return dimensions;}function validateDimensions(list,dims){for(var i=0;i<dims.length;i++){// stroage may be empty when no data, so use\n// dimensionInfos to check.\nif(!list._dimensionInfos[dims[i]]){console.error('Unkown dimension '+dims[i]);}}}/**\n * Data iteration\n * @param {string|Array.<string>}\n * @param {Function} cb\n * @param {*} [context=this]\n *\n * @example\n *  list.each('x', function (x, idx) {});\n *  list.each(['x', 'y'], function (x, y, idx) {});\n *  list.each(function (idx) {})\n */listProto.each=function(dims,cb,context,contextCompat){'use strict';if(!this._count){return;}if(typeof dims==='function'){contextCompat=context;context=cb;cb=dims;dims=[];}// contextCompat just for compat echarts3\ncontext=context||contextCompat||this;dims=map(normalizeDimensions(dims),this.getDimension,this);if(__DEV__){validateDimensions(this,dims);}var dimSize=dims.length;for(var i=0;i<this.count();i++){// Simple optimization\nswitch(dimSize){case 0:cb.call(context,i);break;case 1:cb.call(context,this.get(dims[0],i),i);break;case 2:cb.call(context,this.get(dims[0],i),this.get(dims[1],i),i);break;default:var k=0;var value=[];for(;k<dimSize;k++){value[k]=this.get(dims[k],i);}// Index\nvalue[k]=i;cb.apply(context,value);}}};/**\n * Data filter\n * @param {string|Array.<string>}\n * @param {Function} cb\n * @param {*} [context=this]\n */listProto.filterSelf=function(dimensions,cb,context,contextCompat){'use strict';if(!this._count){return;}if(typeof dimensions==='function'){contextCompat=context;context=cb;cb=dimensions;dimensions=[];}// contextCompat just for compat echarts3\ncontext=context||contextCompat||this;dimensions=map(normalizeDimensions(dimensions),this.getDimension,this);if(__DEV__){validateDimensions(this,dimensions);}var count=this.count();var Ctor=getIndicesCtor(this);var newIndices=new Ctor(count);var value=[];var dimSize=dimensions.length;var offset=0;var dim0=dimensions[0];for(var i=0;i<count;i++){var keep;var rawIdx=this.getRawIndex(i);// Simple optimization\nif(dimSize===0){keep=cb.call(context,i);}else if(dimSize===1){var val=this._getFast(dim0,rawIdx);keep=cb.call(context,val,i);}else{for(var k=0;k<dimSize;k++){value[k]=this._getFast(dim0,rawIdx);}value[k]=i;keep=cb.apply(context,value);}if(keep){newIndices[offset++]=rawIdx;}}// Set indices after filtered.\nif(offset<count){this._indices=newIndices;}this._count=offset;// Reset data extent\nthis._extent={};this.getRawIndex=this._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;return this;};/**\n * Select data in range. (For optimization of filter)\n * (Manually inline code, support 5 million data filtering in data zoom.)\n */listProto.selectRange=function(range){'use strict';if(!this._count){return;}var dimensions=[];for(var dim in range){if(range.hasOwnProperty(dim)){dimensions.push(dim);}}if(__DEV__){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 min=range[dim0][0];var max=range[dim0][1];var quickFinished=false;if(!this._indices){// Extreme optimization for common case. About 2x faster in chrome.\nvar idx=0;if(dimSize===1){var dimStorage=this._storage[dimensions[0]];for(var k=0;k<this._chunkCount;k++){var chunkStorage=dimStorage[k];var len=Math.min(this._count-k*this._chunkSize,this._chunkSize);for(var i=0;i<len;i++){var val=chunkStorage[i];// NaN will not be filtered. Consider the case, in line chart, empty\n// value indicates the line should be broken. But for the case like\n// scatter plot, a data item with empty value will not be rendered,\n// but the axis extent may be effected if some other dim of the data\n// item has value. Fortunately it is not a significant negative effect.\nif(val>=min&&val<=max||isNaN(val)){newIndices[offset++]=idx;}idx++;}}quickFinished=true;}else if(dimSize===2){var dimStorage=this._storage[dim0];var dimStorage2=this._storage[dimensions[1]];var min2=range[dimensions[1]][0];var max2=range[dimensions[1]][1];for(var k=0;k<this._chunkCount;k++){var chunkStorage=dimStorage[k];var chunkStorage2=dimStorage2[k];var len=Math.min(this._count-k*this._chunkSize,this._chunkSize);for(var i=0;i<len;i++){var val=chunkStorage[i];var val2=chunkStorage2[i];// Do not filter NaN, see comment above.\nif((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=this._getFast(dim0,rawIndex);// Do not filter NaN, see comment above.\nif(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=this._getFast(dim,rawIndex);// Do not filter NaN, see comment above.\nif(val<range[dimk][0]||val>range[dimk][1]){keep=false;}}if(keep){newIndices[offset++]=this.getRawIndex(i);}}}}// Set indices after filtered.\nif(offset<originalCount){this._indices=newIndices;}this._count=offset;// Reset data extent\nthis._extent={};this.getRawIndex=this._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;return this;};/**\n * Data mapping to a plain array\n * @param {string|Array.<string>} [dimensions]\n * @param {Function} cb\n * @param {*} [context=this]\n * @return {Array}\n */listProto.mapArray=function(dimensions,cb,context,contextCompat){'use strict';if(typeof dimensions==='function'){contextCompat=context;context=cb;cb=dimensions;dimensions=[];}// contextCompat just for compat echarts3\ncontext=context||contextCompat||this;var result=[];this.each(dimensions,function(){result.push(cb&&cb.apply(this,arguments));},context);return result;};// Data in excludeDimensions is copied, otherwise transfered.\nfunction cloneListForMapAndSample(original,excludeDimensions){var allDimensions=original.dimensions;var list=new List(map(allDimensions,original.getDimensionInfo,original),original.hostModel);// FIXME If needs stackedOn, value may already been stacked\ntransferProperties(list,original);var storage=list._storage={};var originalStorage=original._storage;// Init storage\nfor(var i=0;i<allDimensions.length;i++){var dim=allDimensions[i];if(originalStorage[dim]){// Notice that we do not reset invertedIndicesMap here, becuase\n// there is no scenario of mapping or sampling ordinal dimension.\nif(indexOf(excludeDimensions,dim)>=0){storage[dim]=cloneDimStore(originalStorage[dim]);list._rawExtent[dim]=getInitialExtent();list._extent[dim]=null;}else{// Direct reference for other dimensions\nstorage[dim]=originalStorage[dim];}}}return list;}function cloneDimStore(originalDimStore){var newDimStore=new Array(originalDimStore.length);for(var j=0;j<originalDimStore.length;j++){newDimStore[j]=cloneChunk(originalDimStore[j]);}return newDimStore;}function getInitialExtent(){return[Infinity,-Infinity];}/**\n * Data mapping to a new List with given dimensions\n * @param {string|Array.<string>} dimensions\n * @param {Function} cb\n * @param {*} [context=this]\n * @return {Array}\n */listProto.map=function(dimensions,cb,context,contextCompat){'use strict';// contextCompat just for compat echarts3\ncontext=context||contextCompat||this;dimensions=map(normalizeDimensions(dimensions),this.getDimension,this);if(__DEV__){validateDimensions(this,dimensions);}var list=cloneListForMapAndSample(this,dimensions);// Following properties are all immutable.\n// So we can reference to the same value\nlist._indices=this._indices;list.getRawIndex=list._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;var storage=list._storage;var tmpRetValue=[];var chunkSize=this._chunkSize;var dimSize=dimensions.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(dimensions[dimIndex],dataIndex/*, stack */);}values[dimSize]=dataIndex;var retValue=cb&&cb.apply(context,values);if(retValue!=null){// a number or string (in oridinal dimension)?\nif(_typeof(retValue)!=='object'){tmpRetValue[0]=retValue;retValue=tmpRetValue;}var rawIndex=this.getRawIndex(dataIndex);var chunkIndex=Math.floor(rawIndex/chunkSize);var chunkOffset=rawIndex%chunkSize;for(var i=0;i<retValue.length;i++){var dim=dimensions[i];var val=retValue[i];var rawExtentOnDim=rawExtent[dim];var dimStore=storage[dim];if(dimStore){dimStore[chunkIndex][chunkOffset]=val;}if(val<rawExtentOnDim[0]){rawExtentOnDim[0]=val;}if(val>rawExtentOnDim[1]){rawExtentOnDim[1]=val;}}}}return list;};/**\n * Large data down sampling on given dimension\n * @param {string} dimension\n * @param {number} rate\n * @param {Function} sampleValue\n * @param {Function} sampleIndex Sample index for name and id\n */listProto.downSample=function(dimension,rate,sampleValue,sampleIndex){var list=cloneListForMapAndSample(this,[dimension]);var targetStorage=list._storage;var frameValues=[];var frameSize=Math.floor(1/rate);var dimStore=targetStorage[dimension];var len=this.count();var chunkSize=this._chunkSize;var rawExtentOnDim=list._rawExtent[dimension];var newIndices=new(getIndicesCtor(this))(len);var offset=0;for(var i=0;i<len;i+=frameSize){// Last frame\nif(frameSize>len-i){frameSize=len-i;frameValues.length=frameSize;}for(var k=0;k<frameSize;k++){var dataIdx=this.getRawIndex(i+k);var originalChunkIndex=Math.floor(dataIdx/chunkSize);var originalChunkOffset=dataIdx%chunkSize;frameValues[k]=dimStore[originalChunkIndex][originalChunkOffset];}var value=sampleValue(frameValues);var sampleFrameIdx=this.getRawIndex(Math.min(i+sampleIndex(frameValues,value)||0,len-1));var sampleChunkIndex=Math.floor(sampleFrameIdx/chunkSize);var sampleChunkOffset=sampleFrameIdx%chunkSize;// Only write value on the filtered data\ndimStore[sampleChunkIndex][sampleChunkOffset]=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;};/**\n * Get model of one data item.\n *\n * @param {number} idx\n */ // FIXME Model proxy ?\nlistProto.getItemModel=function(idx){var hostModel=this.hostModel;return new Model(this.getRawDataItem(idx),hostModel,hostModel&&hostModel.ecModel);};/**\n * Create a data differ\n * @param {module:echarts/data/List} otherList\n * @return {module:echarts/data/DataDiffer}\n */listProto.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);});};/**\n * Get visual property.\n * @param {string} key\n */listProto.getVisual=function(key){var visual=this._visual;return visual&&visual[key];};/**\n * Set visual property\n * @param {string|Object} key\n * @param {*} [value]\n *\n * @example\n *  setVisual('color', color);\n *  setVisual({\n *      'color': color\n *  });\n */listProto.setVisual=function(key,val){if(isObject$4(key)){for(var name in key){if(key.hasOwnProperty(name)){this.setVisual(name,key[name]);}}return;}this._visual=this._visual||{};this._visual[key]=val;};/**\n * Set layout property.\n * @param {string|Object} key\n * @param {*} [val]\n */listProto.setLayout=function(key,val){if(isObject$4(key)){for(var name in key){if(key.hasOwnProperty(name)){this.setLayout(name,key[name]);}}return;}this._layout[key]=val;};/**\n * Get layout property.\n * @param  {string} key.\n * @return {*}\n */listProto.getLayout=function(key){return this._layout[key];};/**\n * Get layout of single data item\n * @param {number} idx\n */listProto.getItemLayout=function(idx){return this._itemLayouts[idx];};/**\n * Set layout of single data item\n * @param {number} idx\n * @param {Object} layout\n * @param {boolean=} [merge=false]\n */listProto.setItemLayout=function(idx,layout,merge$$1){this._itemLayouts[idx]=merge$$1?extend(this._itemLayouts[idx]||{},layout):layout;};/**\n * Clear all layout of single data item\n */listProto.clearItemLayouts=function(){this._itemLayouts.length=0;};/**\n * Get visual property of single data item\n * @param {number} idx\n * @param {string} key\n * @param {boolean} [ignoreParent=false]\n */listProto.getItemVisual=function(idx,key,ignoreParent){var itemVisual=this._itemVisuals[idx];var val=itemVisual&&itemVisual[key];if(val==null&&!ignoreParent){// Use global visual property\nreturn this.getVisual(key);}return val;};/**\n * Set visual property of single data item\n *\n * @param {number} idx\n * @param {string|Object} key\n * @param {*} [value]\n *\n * @example\n *  setItemVisual(0, 'color', color);\n *  setItemVisual(0, {\n *      'color': color\n *  });\n */listProto.setItemVisual=function(idx,key,value){var itemVisual=this._itemVisuals[idx]||{};var hasItemVisual=this.hasItemVisual;this._itemVisuals[idx]=itemVisual;if(isObject$4(key)){for(var name in key){if(key.hasOwnProperty(name)){itemVisual[name]=key[name];hasItemVisual[name]=true;}}return;}itemVisual[key]=value;hasItemVisual[key]=true;};/**\n * Clear itemVisuals and list visual.\n */listProto.clearAllVisual=function(){this._visual={};this._itemVisuals=[];this.hasItemVisual={};};var setItemDataAndSeriesIndex=function setItemDataAndSeriesIndex(child){child.seriesIndex=this.seriesIndex;child.dataIndex=this.dataIndex;child.dataType=this.dataType;};/**\n * Set graphic element relative to data. It can be set as null\n * @param {number} idx\n * @param {module:zrender/Element} [el]\n */listProto.setItemGraphicEl=function(idx,el){var hostModel=this.hostModel;if(el){// Add data index and series index for indexing the data by element\n// Useful in tooltip\nel.dataIndex=idx;el.dataType=this.dataType;el.seriesIndex=hostModel&&hostModel.seriesIndex;if(el.type==='group'){el.traverse(setItemDataAndSeriesIndex,el);}}this._graphicEls[idx]=el;};/**\n * @param {number} idx\n * @return {module:zrender/Element}\n */listProto.getItemGraphicEl=function(idx){return this._graphicEls[idx];};/**\n * @param {Function} cb\n * @param {*} context\n */listProto.eachItemGraphicEl=function(cb,context){each$1(this._graphicEls,function(el,idx){if(el){cb&&cb.call(context,el,idx);}});};/**\n * Shallow clone a new list except visual and layout properties, and graph elements.\n * New list only change the indices.\n */listProto.cloneShallow=function(list){if(!list){var dimensionInfoList=map(this.dimensions,this.getDimensionInfo,this);list=new List(dimensionInfoList,this.hostModel);}// FIXME\nlist._storage=this._storage;transferProperties(list,this);// Clone will not change the data extent and indices\nif(this._indices){var Ctor=this._indices.constructor;list._indices=new Ctor(this._indices);}else{list._indices=null;}list.getRawIndex=list._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;return list;};/**\n * Wrap some method to add more feature\n * @param {string} methodName\n * @param {Function} injectFunction\n */listProto.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)));};};// Methods that create a new list based on this list should be listed here.\n// Notice that those method should `RETURN` the new list.\nlistProto.TRANSFERABLE_METHODS=['cloneShallow','downSample','map'];// Methods that change indices of this list should be listed here.\nlistProto.CHANGABLE_METHODS=['filterSelf','selectRange'];/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @deprecated\n * Use `echarts/data/helper/createDimensions` instead.\n */ /**\n * @see {module:echarts/test/ut/spec/data/completeDimensions}\n *\n * This method builds the relationship between:\n * + \"what the coord sys or series requires (see `sysDims`)\",\n * + \"what the user defines (in `encode` and `dimensions`, see `opt.dimsDef` and `opt.encodeDef`)\"\n * + \"what the data source provids (see `source`)\".\n *\n * Some guess strategy will be adapted if user does not define something.\n * If no 'value' dimension specified, the first no-named dimension will be\n * named as 'value'.\n *\n * @param {Array.<string>} sysDims Necessary dimensions, like ['x', 'y'], which\n *      provides not only dim template, but also default order.\n *      properties: 'name', 'type', 'displayName'.\n *      `name` of each item provides default coord name.\n *      [{dimsDef: [string|Object, ...]}, ...] dimsDef of sysDim item provides default dim name, and\n *                                    provide dims count that the sysDim required.\n *      [{ordinalMeta}] can be specified.\n * @param {module:echarts/data/Source|Array|Object} source or data (for compatibal with pervious)\n * @param {Object} [opt]\n * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions\n *      For example: ['asdf', {name, type}, ...].\n * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}\n * @param {Function} [opt.encodeDefaulter] Called if no `opt.encodeDef` exists.\n *      If not specified, auto find the next available data dim.\n *      param source {module:data/Source}\n *      param dimCount {number}\n *      return {Object} encode Never be `null/undefined`.\n * @param {string} [opt.generateCoord] Generate coord dim with the given name.\n *      If not specified, extra dim names will be:\n *      'value', 'value0', 'value1', ...\n * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`.\n *      If `generateCoordCount` specified, the generated dim names will be:\n *      `generateCoord` + 0, `generateCoord` + 1, ...\n *      can be Infinity, indicate that use all of the remain columns.\n * @param {number} [opt.dimCount] If not specified, guess by the first data item.\n * @return {Array.<module:data/DataDimensionInfo>}\n */function completeDimensions(sysDims,source,opt){if(!Source.isInstance(source)){source=Source.seriesDataToSource(source);}opt=opt||{};sysDims=(sysDims||[]).slice();var dimsDef=(opt.dimsDef||[]).slice();var dataDimNameMap=createHashMap();var coordDimNameMap=createHashMap();// var valueCandidate;\nvar result=[];var dimCount=getDimCount(source,sysDims,dimsDef,opt.dimCount);// Apply user defined dims (`name` and `type`) and init result.\nfor(var i=0;i<dimCount;i++){var dimDefItem=dimsDef[i]=extend({},isObject$1(dimsDef[i])?dimsDef[i]:{name:dimsDef[i]});var userDimName=dimDefItem.name;var resultItem=result[i]=new DataDimensionInfo();// Name will be applied later for avoiding duplication.\nif(userDimName!=null&&dataDimNameMap.get(userDimName)==null){// Only if `series.dimensions` is defined in option\n// displayName, will be set, and dimension will be diplayed vertically in\n// tooltip by default.\nresultItem.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);}encodeDef=createHashMap(encodeDef);// Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.\nencodeDef.each(function(dataDims,coordDim){dataDims=normalizeToArray(dataDims).slice();// Note: It is allowed that `dataDims.length` is `0`, e.g., options is\n// `{encode: {x: -1, y: 1}}`. Should not filter anything in\n// this case.\nif(dataDims.length===1&&!isString(dataDims[0])&&dataDims[0]<0){encodeDef.set(coordDim,false);return;}var validDataDims=encodeDef.set(coordDim,[]);each$1(dataDims,function(resultDimIdx,idx){// The input resultDimIdx can be dim name or index.\nisString(resultDimIdx)&&(resultDimIdx=dataDimNameMap.get(resultDimIdx));if(resultDimIdx!=null&&resultDimIdx<dimCount){validDataDims[idx]=resultDimIdx;applyDim(result[resultDimIdx],coordDim,idx);}});});// Apply templetes and default order from `sysDims`.\nvar availDimIdx=0;each$1(sysDims,function(sysDimItem,sysDimIndex){var coordDim;var sysDimItem;var sysDimItemDimsDef;var sysDimItemOtherDims;if(isString(sysDimItem)){coordDim=sysDimItem;sysDimItem={};}else{coordDim=sysDimItem.name;var ordinalMeta=sysDimItem.ordinalMeta;sysDimItem.ordinalMeta=null;sysDimItem=_clone(sysDimItem);sysDimItem.ordinalMeta=ordinalMeta;// `coordDimIndex` should not be set directly.\nsysDimItemDimsDef=sysDimItem.dimsDef;sysDimItemOtherDims=sysDimItem.otherDims;sysDimItem.name=sysDimItem.coordDim=sysDimItem.coordDimIndex=sysDimItem.dimsDef=sysDimItem.otherDims=null;}var dataDims=encodeDef.get(coordDim);// negative resultDimIdx means no need to mapping.\nif(dataDims===false){return;}var dataDims=normalizeToArray(dataDims);// dimensions provides default dim sequences.\nif(!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++);}}// Apply templates.\neach$1(dataDims,function(resultDimIdx,coordDimIndex){var resultItem=result[resultDimIdx];applyDim(defaults(resultItem,sysDimItem),coordDim,coordDimIndex);if(resultItem.name==null&&sysDimItemDimsDef){var sysDimItemDimsDefItem=sysDimItemDimsDef[coordDimIndex];!isObject$1(sysDimItemDimsDefItem)&&(sysDimItemDimsDefItem={name:sysDimItemDimsDefItem});resultItem.name=resultItem.displayName=sysDimItemDimsDefItem.name;resultItem.defaultTooltip=sysDimItemDimsDefItem.defaultTooltip;}// FIXME refactor, currently only used in case: {otherDims: {tooltip: false}}\nsysDimItemOtherDims&&defaults(resultItem.otherDims,sysDimItemOtherDims);});});function applyDim(resultItem,coordDim,coordDimIndex){if(OTHER_DIMENSIONS.get(coordDim)!=null){resultItem.otherDims[coordDim]=coordDimIndex;}else{resultItem.coordDim=coordDim;resultItem.coordDimIndex=coordDimIndex;coordDimNameMap.set(coordDim,true);}}// Make sure the first extra dim is 'value'.\nvar generateCoord=opt.generateCoord;var generateCoordCount=opt.generateCoordCount;var fromZero=generateCoordCount!=null;generateCoordCount=generateCoord?generateCoordCount||1:0;var extra=generateCoord||'value';// Set dim `name` and other `coordDim` and other props.\nfor(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));if(resultItem.type==null&&(guessOrdinal(source,resultDimIdx,resultItem.name)===BE_ORDINAL.Must// Consider the case:\n// {\n//    dataset: {source: [\n//        ['2001', 123],\n//        ['2002', 456],\n//        ...\n//        ['The others', 987],\n//    ]},\n//    series: {type: 'pie'}\n// }\n// The first colum should better be treated as a \"ordinal\" although it\n// might not able to be detected as an \"ordinal\" by `guessOrdinal`.\n||resultItem.isExtraCoord&&(resultItem.otherDims.itemName!=null||resultItem.otherDims.seriesName!=null))){resultItem.type='ordinal';}}return result;}// ??? TODO\n// Originally detect dimCount by data[0]. Should we\n// optimize it to only by sysDims and dimensions and encode.\n// So only necessary dims will be initialized.\n// But\n// (1) custom series should be considered. where other dims\n// may be visited.\n// (2) sometimes user need to calcualte bubble size or use visualMap\n// on other dimensions besides coordSys needed.\n// So, dims that is not used by system, should be shared in storage?\nfunction getDimCount(source,sysDims,dimsDef,optDimCount){// Note that the result dimCount should not small than columns count\n// of data, otherwise `dataDimNameMap` checking will be incorrect.\nvar dimCount=Math.max(source.dimensionsDetectCount||1,sysDims.length,dimsDef.length,optDimCount||0);each$1(sysDims,function(sysDimItem){var sysDimItemDimsDef=sysDimItem.dimsDef;sysDimItemDimsDef&&(dimCount=Math.max(dimCount,sysDimItemDimsDef.length));});return dimCount;}function genName(name,map$$1,fromZero){if(fromZero||map$$1.get(name)!=null){var i=0;while(map$$1.get(name+i)!=null){i++;}name+=i;}map$$1.set(name,true);return name;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Substitute `completeDimensions`.\n * `completeDimensions` is to be deprecated.\n */ /**\n * @param {module:echarts/data/Source|module:echarts/data/List} source or data.\n * @param {Object|Array} [opt]\n * @param {Array.<string|Object>} [opt.coordDimensions=[]]\n * @param {number} [opt.dimensionsCount]\n * @param {string} [opt.generateCoord]\n * @param {string} [opt.generateCoordCount]\n * @param {Array.<string|Object>} [opt.dimensionsDefine=source.dimensionsDefine] Overwrite source define.\n * @param {Object|HashMap} [opt.encodeDefine=source.encodeDefine] Overwrite source define.\n * @param {Function} [opt.encodeDefaulter] Make default encode if user not specified.\n * @return {Array.<Object>} dimensionsInfo\n */var createDimensions=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});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Helper for model references.\n * There are many manners to refer axis/coordSys.\n */ // TODO\n// merge relevant logic to this file?\n// check: \"modelHelper\" of tooltip and \"BrushTargetManager\".\n/**\n * @class\n * For example:\n * {\n *     coordSysName: 'cartesian2d',\n *     coordSysDims: ['x', 'y', ...],\n *     axisMap: HashMap({\n *         x: xAxisModel,\n *         y: yAxisModel\n *     }),\n *     categoryAxisMap: HashMap({\n *         x: xAxisModel,\n *         y: undefined\n *     }),\n *     // The index of the first category axis in `coordSysDims`.\n *     // `null/undefined` means no category axis exists.\n *     firstCategoryDimIndex: 1,\n *     // To replace user specified encode.\n * }\n */function CoordSysInfo(coordSysName){/**\n     * @type {string}\n     */this.coordSysName=coordSysName;/**\n     * @type {Array.<string>}\n     */this.coordSysDims=[];/**\n     * @type {module:zrender/core/util#HashMap}\n     */this.axisMap=createHashMap();/**\n     * @type {module:zrender/core/util#HashMap}\n     */this.categoryAxisMap=createHashMap();/**\n     * @type {number}\n     */this.firstCategoryDimIndex=null;}/**\n * @return {module:model/referHelper#CoordSysInfo}\n */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 cartesian2d(seriesModel,result,axisMap,categoryAxisMap){var xAxisModel=seriesModel.getReferringComponents('xAxis')[0];var yAxisModel=seriesModel.getReferringComponents('yAxis')[0];if(__DEV__){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 singleAxis(seriesModel,result,axisMap,categoryAxisMap){var singleAxisModel=seriesModel.getReferringComponents('singleAxis')[0];if(__DEV__){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 polar(seriesModel,result,axisMap,categoryAxisMap){var polarModel=seriesModel.getReferringComponents('polar')[0];var radiusAxisModel=polarModel.findAxisModel('radiusAxis');var angleAxisModel=polarModel.findAxisModel('angleAxis');if(__DEV__){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 geo(seriesModel,result,axisMap,categoryAxisMap){result.coordSysDims=['lng','lat'];},parallel:function parallel(seriesModel,result,axisMap,categoryAxisMap){var ecModel=seriesModel.ecModel;var parallelModel=ecModel.getComponent('parallel',seriesModel.get('parallelIndex'));var coordSysDims=result.coordSysDims=parallelModel.dimensions.slice();each$1(parallelModel.parallelAxisIndex,function(axisIndex,index){var axisModel=ecModel.getComponent('parallelAxis',axisIndex);var axisDim=coordSysDims[index];axisMap.set(axisDim,axisModel);if(isCategory(axisModel)&&result.firstCategoryDimIndex==null){categoryAxisMap.set(axisDim,axisModel);result.firstCategoryDimIndex=index;}});}};function isCategory(axisModel){return axisModel.get('type')==='category';}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Note that it is too complicated to support 3d stack by value\n * (have to create two-dimension inverted index), so in 3d case\n * we just support that stacked by index.\n *\n * @param {module:echarts/model/Series} seriesModel\n * @param {Array.<string|Object>} dimensionInfoList The same as the input of <module:echarts/data/List>.\n *        The input dimensionInfoList will be modified.\n * @param {Object} [opt]\n * @param {boolean} [opt.stackedCoordDimension=''] Specify a coord dimension if needed.\n * @param {boolean} [opt.byIndex=false]\n * @return {Object} calculationInfo\n * {\n *     stackedDimension: string\n *     stackedByDimension: string\n *     isStackedByIndex: boolean\n *     stackedOverDimension: string\n *     stackResultDimension: string\n * }\n */function enableDataStack(seriesModel,dimensionInfoList,opt){opt=opt||{};var byIndex=opt.byIndex;var stackedCoordDimension=opt.stackedCoordDimension;// Compatibal: when `stack` is set as '', do not stack.\nvar mayStack=!!(seriesModel&&seriesModel.get('stack'));var stackedByDimInfo;var stackedDimInfo;var stackResultDimension;var stackedOverDimension;each$1(dimensionInfoList,function(dimensionInfo,index){if(isString(dimensionInfo)){dimensionInfoList[index]=dimensionInfo={name:dimensionInfo};}if(mayStack&&!dimensionInfo.isExtraCoord){// Find the first ordinal dimension as the stackedByDimInfo.\nif(!byIndex&&!stackedByDimInfo&&dimensionInfo.ordinalMeta){stackedByDimInfo=dimensionInfo;}// Find the first stackable dimension as the stackedDimInfo.\nif(!stackedDimInfo&&dimensionInfo.type!=='ordinal'&&dimensionInfo.type!=='time'&&(!stackedCoordDimension||stackedCoordDimension===dimensionInfo.coordDim)){stackedDimInfo=dimensionInfo;}}});if(stackedDimInfo&&!byIndex&&!stackedByDimInfo){// Compatible with previous design, value axis (time axis) only stack by index.\n// It may make sense if the user provides elaborately constructed data.\nbyIndex=true;}// Add stack dimension, they can be both calculated by coordinate system in `unionExtent`.\n// That put stack logic in List is for using conveniently in echarts extensions, but it\n// might not be a good way.\nif(stackedDimInfo){// Use a weird name that not duplicated with other names.\nstackResultDimension='__\\0ecstackresult';stackedOverDimension='__\\0ecstackedover';// Create inverted index to fast query index by value.\nif(stackedByDimInfo){stackedByDimInfo.createInvertedIndices=true;}var stackedDimCoordDim=stackedDimInfo.coordDim;var stackedDimType=stackedDimInfo.type;var stackedDimCoordIndex=0;each$1(dimensionInfoList,function(dimensionInfo){if(dimensionInfo.coordDim===stackedDimCoordDim){stackedDimCoordIndex++;}});dimensionInfoList.push({name:stackResultDimension,coordDim:stackedDimCoordDim,coordDimIndex:stackedDimCoordIndex,type:stackedDimType,isExtraCoord:true,isCalculationCoord:true});stackedDimCoordIndex++;dimensionInfoList.push({name:stackedOverDimension,// This dimension contains stack base (generally, 0), so do not set it as\n// `stackedDimCoordDim` to avoid extent calculation, consider log scale.\ncoordDim:stackedOverDimension,coordDimIndex:stackedDimCoordIndex,type:stackedDimType,isExtraCoord:true,isCalculationCoord:true});}return{stackedDimension:stackedDimInfo&&stackedDimInfo.name,stackedByDimension:stackedByDimInfo&&stackedByDimInfo.name,isStackedByIndex:byIndex,stackedOverDimension:stackedOverDimension,stackResultDimension:stackResultDimension};}/**\n * @param {module:echarts/data/List} data\n * @param {string} stackedDim\n */function isDimensionStacked(data,stackedDim/*, stackedByDim*/){// Each single series only maps to one pair of axis. So we do not need to\n// check stackByDim, whatever stacked by a dimension or stacked by index.\nreturn!!stackedDim&&stackedDim===data.getCalculationInfo('stackedDimension');// && (\n//     stackedByDim != null\n//         ? stackedByDim === data.getCalculationInfo('stackedByDimension')\n//         : data.getCalculationInfo('isStackedByIndex')\n// );\n}/**\n * @param {module:echarts/data/List} data\n * @param {string} targetDim\n * @param {string} [stackedByDim] If not input this parameter, check whether\n *                                stacked by index.\n * @return {string} dimension\n */function getStackedDimension(data,targetDim){return isDimensionStacked(data,targetDim)?data.getCalculationInfo('stackResultDimension'):targetDim;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {module:echarts/data/Source|Array} source Or raw data.\n * @param {module:echarts/model/Series} seriesModel\n * @param {Object} [opt]\n * @param {string} [opt.generateCoord]\n * @param {boolean} [opt.useEncodeDefaulter]\n */function createListFromArray(source,seriesModel,opt){opt=opt||{};if(!Source.isInstance(source)){source=Source.seriesDataToSource(source);}var coordSysName=seriesModel.get('coordinateSystem');var registeredCoordSys=CoordinateSystemManager.get(coordSysName);var coordSysInfo=getCoordSysInfoBySeries(seriesModel);var coordSysDimDefs;if(coordSysInfo){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);// dimInfo.stackable = isStackable(axisType);\n}return dimInfo;});}if(!coordSysDimDefs){// Get dimensions from registered coordinate system\ncoordSysDimDefs=registeredCoordSys&&(registeredCoordSys.getDimensionsInfo?registeredCoordSys.getDimensionsInfo():registeredCoordSys.dimensions.slice())||['x','y'];}var dimInfoList=createDimensions(source,{coordDimensions:coordSysDimDefs,generateCoord:opt.generateCoord,encodeDefaulter:opt.useEncodeDefaulter?curry(makeSeriesEncodeForAxisCoordSys,coordSysDimDefs,seriesModel):null});var firstCategoryDimIndex;var hasNameEncode;coordSysInfo&&each$1(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){// Use dataIndex as ordinal value in categoryAxis\nreturn 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];}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * // Scale class management\n * @module echarts/scale/Scale\n */ /**\n * @param {Object} [setting]\n */function Scale(setting){this._setting=setting||{};/**\n     * Extent\n     * @type {Array.<number>}\n     * @protected\n     */this._extent=[Infinity,-Infinity];/**\n     * Step is calculated in adjustExtent\n     * @type {Array.<number>}\n     * @protected\n     */this._interval=0;this.init&&this.init.apply(this,arguments);}/**\n * Parse input val to valid inner number.\n * @param {*} val\n * @return {number}\n */Scale.prototype.parse=function(val){// Notice: This would be a trap here, If the implementation\n// of this method depends on extent, and this method is used\n// before extent set (like in dataZoom), it would be wrong.\n// Nevertheless, parse does not depend on extent generally.\nreturn val;};Scale.prototype.getSetting=function(name){return this._setting[name];};Scale.prototype.contain=function(val){var extent=this._extent;return val>=extent[0]&&val<=extent[1];};/**\n * Normalize value to linear [0, 1], return 0.5 if extent span is 0\n * @param {number} val\n * @return {number}\n */Scale.prototype.normalize=function(val){var extent=this._extent;if(extent[1]===extent[0]){return 0.5;}return(val-extent[0])/(extent[1]-extent[0]);};/**\n * Scale normalized value\n * @param {number} val\n * @return {number}\n */Scale.prototype.scale=function(val){var extent=this._extent;return val*(extent[1]-extent[0])+extent[0];};/**\n * Set extent from data\n * @param {Array.<number>} other\n */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]);// not setExtent because in log axis it may transformed to power\n// this.setExtent(extent[0], extent[1]);\n};/**\n * Set extent from data\n * @param {module:echarts/data/List} data\n * @param {string} dim\n */Scale.prototype.unionExtentFromData=function(data,dim){this.unionExtent(data.getApproximateExtent(dim));};/**\n * Get extent\n * @return {Array.<number>}\n */Scale.prototype.getExtent=function(){return this._extent.slice();};/**\n * Set extent\n * @param {number} start\n * @param {number} end\n */Scale.prototype.setExtent=function(start,end){var thisExtent=this._extent;if(!isNaN(start)){thisExtent[0]=start;}if(!isNaN(end)){thisExtent[1]=end;}};/**\n * When axis extent depends on data and no data exists,\n * axis ticks should not be drawn, which is named 'blank'.\n */Scale.prototype.isBlank=function(){return this._isBlank;},/**\n * When axis extent depends on data and no data exists,\n * axis ticks should not be drawn, which is named 'blank'.\n */Scale.prototype.setBlank=function(isBlank){this._isBlank=isBlank;};/**\n * @abstract\n * @param {*} tick\n * @return {string} label of the tick.\n */Scale.prototype.getLabel=null;enableClassExtend(Scale);enableClassManagement(Scale,{registerWhenExtend:true});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @constructor\n * @param {Object} [opt]\n * @param {Object} [opt.categories=[]]\n * @param {Object} [opt.needCollect=false]\n * @param {Object} [opt.deduplication=false]\n */function OrdinalMeta(opt){/**\n     * @readOnly\n     * @type {Array.<string>}\n     */this.categories=opt.categories||[];/**\n     * @private\n     * @type {boolean}\n     */this._needCollect=opt.needCollect;/**\n     * @private\n     * @type {boolean}\n     */this._deduplication=opt.deduplication;/**\n     * @private\n     * @type {boolean}\n     */this._map;}/**\n * @param {module:echarts/model/Model} axisModel\n * @return {module:echarts/data/OrdinalMeta}\n */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 is default in axis.\ndeduplication:option.dedplication!==false});};var proto$1=OrdinalMeta.prototype;/**\n * @param {string} category\n * @return {number} ordinal\n */proto$1.getOrdinal=function(category){return getOrCreateMap(this).get(category);};/**\n * @param {*} category\n * @return {number} The ordinal. If not found, return NaN.\n */proto$1.parseAndCollect=function(category){var index;var needCollect=this._needCollect;// The value of category dim can be the index of the given category set.\n// This feature is only supported when !needCollect, because we should\n// consider a common case: a value is 2017, which is a number but is\n// expected to be tread as a category. This case usually happen in dataset,\n// where it happent to be no need of the index feature.\nif(typeof category!=='string'&&!needCollect){return category;}// Optimize for the scenario:\n// category is ['2012-01-01', '2012-01-02', ...], where the input\n// data has been ensured not duplicate and is large data.\n// Notice, if a dataset dimension provide categroies, usually echarts\n// should remove duplication except user tell echarts dont do that\n// (set axis.deduplication = false), because echarts do not know whether\n// the values in the category dimension has duplication (consider the\n// parallel-aqi example)\nif(needCollect&&!this._deduplication){index=this.categories.length;this.categories[index]=category;return index;}var map$$1=getOrCreateMap(this);index=map$$1.get(category);if(index==null){if(needCollect){index=this.categories.length;this.categories[index]=category;map$$1.set(category,index);}else{index=NaN;}}return index;};// Consider big data, do not create map until needed.\nfunction getOrCreateMap(ordinalMeta){return ordinalMeta._map||(ordinalMeta._map=createHashMap(ordinalMeta.categories));}function getName(obj){if(isObject$1(obj)&&obj.value!=null){return obj.value;}else{return obj+'';}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Linear continuous scale\n * @module echarts/coord/scale/Ordinal\n *\n * http://en.wikipedia.org/wiki/Level_of_measurement\n */ // FIXME only one data\nvar scaleProto=Scale.prototype;var OrdinalScale=Scale.extend({type:'ordinal',/**\n     * @param {module:echarts/data/OrdianlMeta|Array.<string>} ordinalMeta\n     */init:function init(ordinalMeta,extent){// Caution: Should not use instanceof, consider ec-extensions using\n// import approach to get OrdinalMeta class.\nif(!ordinalMeta||isArray(ordinalMeta)){ordinalMeta=new OrdinalMeta({categories:ordinalMeta});}this._ordinalMeta=ordinalMeta;this._extent=extent||[0,ordinalMeta.categories.length-1];},parse:function parse(val){return typeof val==='string'?this._ordinalMeta.getOrdinal(val)// val might be float.\n:Math.round(val);},contain:function contain(rank){rank=this.parse(rank);return scaleProto.contain.call(this,rank)&&this._ordinalMeta.categories[rank]!=null;},/**\n     * Normalize given rank or name to linear [0, 1]\n     * @param {number|string} [val]\n     * @return {number}\n     */normalize:function normalize(val){return scaleProto.normalize.call(this,this.parse(val));},scale:function scale(val){return Math.round(scaleProto.scale.call(this,val));},/**\n     * @return {Array}\n     */getTicks:function getTicks(){var ticks=[];var extent=this._extent;var rank=extent[0];while(rank<=extent[1]){ticks.push(rank);rank++;}return ticks;},/**\n     * Get item on rank n\n     * @param {number} n\n     * @return {string}\n     */getLabel:function getLabel(n){if(!this.isBlank()){// Note that if no data, ordinalMeta.categories is an empty array.\nreturn this._ordinalMeta.categories[n];}},/**\n     * @return {number}\n     */count:function count(){return this._extent[1]-this._extent[0]+1;},/**\n     * @override\n     */unionExtentFromData:function unionExtentFromData(data,dim){this.unionExtent(data.getApproximateExtent(dim));},getOrdinalMeta:function getOrdinalMeta(){return this._ordinalMeta;},niceTicks:noop,niceExtent:noop});/**\n * @return {module:echarts/scale/Time}\n */OrdinalScale.create=function(){return new OrdinalScale();};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * For testable.\n */var roundNumber$1=round$1;/**\n * @param {Array.<number>} extent Both extent[0] and extent[1] should be valid number.\n *                                Should be extent[0] < extent[1].\n * @param {number} splitNumber splitNumber should be >= 1.\n * @param {number} [minInterval]\n * @param {number} [maxInterval]\n * @return {Object} {interval, intervalPrecision, niceTickExtent}\n */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;}// Tow more digital for tick.\nvar precision=result.intervalPrecision=getIntervalPrecision(interval);// Niced extent inside original extent\nvar niceTickExtent=result.niceTickExtent=[roundNumber$1(Math.ceil(extent[0]/interval)*interval,precision),roundNumber$1(Math.floor(extent[1]/interval)*interval,precision)];fixExtent(niceTickExtent,extent);return result;}/**\n * @param {number} interval\n * @return {number} interval precision\n */function getIntervalPrecision(interval){// Tow more digital for tick.\nreturn getPrecisionSafe(interval)+2;}function clamp(niceTickExtent,idx,extent){niceTickExtent[idx]=Math.max(Math.min(niceTickExtent[idx],extent[1]),extent[0]);}// In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent.\nfunction 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];}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Interval scale\n * @module echarts/scale/Interval\n */var roundNumber=round$1;/**\n * @alias module:echarts/coord/scale/Interval\n * @constructor\n */var IntervalScale=Scale.extend({type:'interval',_interval:0,_intervalPrecision:2,setExtent:function setExtent(start,end){var thisExtent=this._extent;//start,end may be a Number like '25',so...\nif(!isNaN(start)){thisExtent[0]=parseFloat(start);}if(!isNaN(end)){thisExtent[1]=parseFloat(end);}},unionExtent:function unionExtent(other){var extent=this._extent;other[0]<extent[0]&&(extent[0]=other[0]);other[1]>extent[1]&&(extent[1]=other[1]);// unionExtent may called by it's sub classes\nIntervalScale.prototype.setExtent.call(this,extent[0],extent[1]);},/**\n     * Get interval\n     */getInterval:function getInterval(){return this._interval;},/**\n     * Set interval\n     */setInterval:function setInterval(interval){this._interval=interval;// Dropped auto calculated niceExtent and use user setted extent\n// We assume user wan't to set both interval, min, max to get a better result\nthis._niceExtent=this._extent.slice();this._intervalPrecision=getIntervalPrecision(interval);},/**\n     * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.\n     * @return {Array.<number>}\n     */getTicks:function getTicks(expandToNicedExtent){var interval=this._interval;var extent=this._extent;var niceTickExtent=this._niceExtent;var intervalPrecision=this._intervalPrecision;var ticks=[];// If interval is 0, return [];\nif(!interval){return ticks;}// Consider this case: using dataZoom toolbox, zoom and zoom.\nvar safeLimit=10000;if(extent[0]<niceTickExtent[0]){if(expandToNicedExtent){ticks.push(roundNumber(niceTickExtent[0]-interval,intervalPrecision));}else{ticks.push(extent[0]);}}var tick=niceTickExtent[0];while(tick<=niceTickExtent[1]){ticks.push(tick);// Avoid rounding error\ntick=roundNumber(tick+interval,intervalPrecision);if(tick===ticks[ticks.length-1]){// Consider out of safe float point, e.g.,\n// -3711126.9907707 + 2e-10 === -3711126.9907707\nbreak;}if(ticks.length>safeLimit){return[];}}// Consider this case: the last item of ticks is smaller\n// than niceTickExtent[1] and niceTickExtent[1] === extent[1].\nvar lastNiceTick=ticks.length?ticks[ticks.length-1]:niceTickExtent[1];if(extent[1]>lastNiceTick){if(expandToNicedExtent){ticks.push(roundNumber(lastNiceTick+interval,intervalPrecision));}else{ticks.push(extent[1]);}}return ticks;},/**\n     * @param {number} [splitNumber=5]\n     * @return {Array.<Array.<number>>}\n     */getMinorTicks:function getMinorTicks(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-prevTick;var minorInterval=interval/splitNumber;while(count<splitNumber-1){var minorTick=round$1(prevTick+(count+1)*minorInterval);// For the first and last interval. The count may be less than splitNumber.\nif(minorTick>extent[0]&&minorTick<extent[1]){minorTicksGroup.push(minorTick);}count++;}minorTicks.push(minorTicksGroup);}return minorTicks;},/**\n     * @param {number} data\n     * @param {Object} [opt]\n     * @param {number|string} [opt.precision] If 'auto', use nice presision.\n     * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2.\n     * @return {string}\n     */getLabel:function getLabel(data,opt){if(data==null){return'';}var precision=opt&&opt.precision;if(precision==null){precision=getPrecisionSafe(data)||0;}else if(precision==='auto'){// Should be more precise then tick.\nprecision=this._intervalPrecision;}// (1) If `precision` is set, 12.005 should be display as '12.00500'.\n// (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'.\ndata=roundNumber(data,precision,true);return addCommas(data);},/**\n     * Update interval and extent of intervals for nice ticks\n     *\n     * @param {number} [splitNumber = 5] Desired number of ticks\n     * @param {number} [minInterval]\n     * @param {number} [maxInterval]\n     */niceTicks:function niceTicks(splitNumber,minInterval,maxInterval){splitNumber=splitNumber||5;var extent=this._extent;var span=extent[1]-extent[0];if(!isFinite(span)){return;}// User may set axis min 0 and data are all negative\n// FIXME If it needs to reverse ?\nif(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;},/**\n     * Nice extent.\n     * @param {Object} opt\n     * @param {number} [opt.splitNumber = 5] Given approx tick number\n     * @param {boolean} [opt.fixMin=false]\n     * @param {boolean} [opt.fixMax=false]\n     * @param {boolean} [opt.minInterval]\n     * @param {boolean} [opt.maxInterval]\n     */niceExtent:function niceExtent(opt){var extent=this._extent;// If extent start and end are same, expand them\nif(extent[0]===extent[1]){if(extent[0]!==0){// Expand extent\nvar expandSize=extent[0];// In the fowllowing case\n//      Axis has been fixed max 100\n//      Plus data are all 100 and axis extent are [100, 100].\n// Extend to the both side will cause expanded max is larger than fixed max.\n// So only expand to the smaller side.\nif(!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 there are no data and extent are [Infinity, -Infinity]\nif(!isFinite(span)){extent[0]=0;extent[1]=1;}this.niceTicks(opt.splitNumber,opt.minInterval,opt.maxInterval);// var extent = this._extent;\nvar interval=this._interval;if(!opt.fixMin){extent[0]=roundNumber(Math.floor(extent[0]/interval)*interval);}if(!opt.fixMax){extent[1]=roundNumber(Math.ceil(extent[1]/interval)*interval);}}});/**\n * @return {module:echarts/scale/Time}\n */IntervalScale.create=function(){return new IntervalScale();};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /* global Float32Array */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;}/**\n * @param {Object} opt\n * @param {module:echarts/coord/Axis} opt.axis Only support category axis currently.\n * @param {number} opt.count Positive interger.\n * @param {number} [opt.barWidth]\n * @param {number} [opt.barMaxWidth]\n * @param {number} [opt.barMinWidth]\n * @param {number} [opt.barGap]\n * @param {number} [opt.barCategoryGap]\n * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined.\n */function prepareLayoutBarSeries(seriesType,ecModel){var seriesModels=[];ecModel.eachSeriesByType(seriesType,function(seriesModel){// Check series coordinate, do layout for cartesian2d only\nif(isOnCartesian(seriesModel)&&!isInLargeMode(seriesModel)){seriesModels.push(seriesModel);}});return seriesModels;}/**\n * Map from (baseAxis.dim + '_' + baseAxis.index) to min gap of two adjacent\n * values.\n * This works for time axes, value axes, and log axes.\n * For a single time axis, return value is in the form like\n * {'x_0': [1000000]}.\n * The value of 1000000 is in milliseconds.\n */function getValueAxesMinGaps(barSeries){/**\n     * Map from axis.index to values.\n     * For a single time axis, axisValues is in the form like\n     * {'x_0': [1495555200000, 1495641600000, 1495728000000]}.\n     * Items in axisValues[x], e.g. 1495555200000, are time values of all\n     * series.\n     */var axisValues={};each$1(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]){// No previous data for the axis\naxisValues[key]=[value];}else{// No value in previous series\naxisValues[key].push(value);}// Ignore duplicated time values in the same axis\n}});var axisMinGaps=[];for(var key in axisValues){if(axisValues.hasOwnProperty(key)){var valuesInAxis=axisValues[key];if(valuesInAxis){// Sort axis values into ascending order to calculate gaps\nvaluesInAxis.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){// Ignore 0 delta because they are of the same axis value\nmin=min===null?delta:Math.min(min,delta);}}// Set to null if only have one data\naxisMinGaps[key]=min;}}}return axisMinGaps;}function makeColumnLayout(barSeries){var axisMinGaps=getValueAxesMinGaps(barSeries);var seriesInfoList=[];each$1(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;// When there is only one data value\n}else{var data=seriesModel.getData();bandWidth=Math.abs(axisExtent[1]-axisExtent[0])/data.count();}var barWidth=parsePercent$1(seriesModel.get('barWidth'),bandWidth);var barMaxWidth=parsePercent$1(seriesModel.get('barMaxWidth'),bandWidth);var barMinWidth=parsePercent$1(// barMinWidth by default is 1 in cartesian. Because in value axis,\n// the auto-calculated bar width might be less than 1.\nseriesModel.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){// Columns info on each category axis. Key is cartesian name\nvar columnsMap={};each$1(seriesInfoList,function(seriesInfo,idx){var axisKey=seriesInfo.axisKey;var bandWidth=seriesInfo.bandWidth;var columnsOnAxis=columnsMap[axisKey]||{bandWidth:bandWidth,remainedWidth:bandWidth,autoWidthCount:0,categoryGap:'20%',gap:'30%',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};// Caution: In a single coordinate system, these barGrid attributes\n// will be shared by series. Consider that they have default values,\n// only the attributes set on the last series will work.\n// Do not change this fact unless there will be a break change.\nvar barWidth=seriesInfo.barWidth;if(barWidth&&!stacks[stackId].width){// See #6312, do not restrict width.\nstacks[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$1(columnsMap,function(columnsOnAxis,coordSysName){result[coordSysName]={};var stacks=columnsOnAxis.stacks;var bandWidth=columnsOnAxis.bandWidth;var categoryGap=parsePercent$1(columnsOnAxis.categoryGap,bandWidth);var barGapPercent=parsePercent$1(columnsOnAxis.gap,1);var remainedWidth=columnsOnAxis.remainedWidth;var autoWidthCount=columnsOnAxis.autoWidthCount;var autoWidth=(remainedWidth-categoryGap)/(autoWidthCount+(autoWidthCount-1)*barGapPercent);autoWidth=Math.max(autoWidth,0);// Find if any auto calculated bar exceeded maxBarWidth\neach$1(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);}// `minWidth` has higher priority. `minWidth` decide that wheter the\n// bar is able to be visible. So `minWidth` should not be restricted\n// by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In\n// the extreme cases for `value` axis, bars are allowed to overlap\n// with each other if `minWidth` specified.\nif(minWidth&&minWidth>finalWidth){finalWidth=minWidth;}if(finalWidth!==autoWidth){column.width=finalWidth;remainedWidth-=finalWidth+barGapPercent*finalWidth;autoWidthCount--;}}else{// `barMinWidth/barMaxWidth` has higher priority than `barWidth`, as\n// CSS does. Becuase barWidth can be a percent value, where\n// `barMaxWidth` can be used to restrict the final width.\nvar finalWidth=column.width;if(maxWidth){finalWidth=Math.min(finalWidth,maxWidth);}// `minWidth` has higher priority, as described above\nif(minWidth){finalWidth=Math.max(finalWidth,minWidth);}column.width=finalWidth;remainedWidth-=finalWidth+barGapPercent*finalWidth;autoWidthCount--;}});// Recalculate width again\nautoWidth=(remainedWidth-categoryGap)/(autoWidthCount+(autoWidthCount-1)*barGapPercent);autoWidth=Math.max(autoWidth,0);var widthSum=0;var lastColumn;each$1(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$1(stacks,function(column,stackId){result[coordSysName][stackId]=result[coordSysName][stackId]||{bandWidth:bandWidth,offset:offset,width:column.width};offset+=column.width*(1+barGapPercent);});});return result;}/**\n * @param {Object} barWidthAndOffset The result of makeColumnLayout\n * @param {module:echarts/coord/Axis} axis\n * @param {module:echarts/model/Series} [seriesModel] If not provided, return all.\n * @return {Object} {stackId: {offset, width}} or {offset, width} if seriesModel provided.\n */function retrieveColumnLayout(barWidthAndOffset,axis,seriesModel){if(barWidthAndOffset&&axis){var result=barWidthAndOffset[getAxisKey(axis)];if(result!=null&&seriesModel!=null){result=result[getSeriesStackId(seriesModel)];}return result;}}/**\n * @param {string} seriesType\n * @param {module:echarts/model/Global} ecModel\n */function layout(seriesType,ecModel){var seriesModels=prepareLayoutBarSeries(seriesType,ecModel);var barWidthAndOffset=makeColumnLayout(seriesModels);var lastStackCoords={};each$1(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/*, baseDim*/);var isValueAxisH=valueAxis.isHorizontal();var valueAxisStart=getValueAxisStart(baseAxis,valueAxis,stacked);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;// Because of the barMinHeight, we can not use the value in\n// stackResultDimension directly.\nif(stacked){// Only ordinal axis can be stacked.\nif(!lastStackCoords[stackId][baseValue]){lastStackCoords[stackId][baseValue]={p:valueAxisStart,// Positive stack\nn:valueAxisStart// Negative stack\n};}// Should also consider #4243\nbaseCoord=lastStackCoords[stackId][baseValue][sign];}var x;var y;var width;var height;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;}// Ignore stack from NaN value\nif(!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){// Include zero to has a positive bar\nheight=(height<=0?-1:1)*barMinHeight;}// Ignore stack from NaN value\nif(!isNaN(height)){stacked&&(lastStackCoords[stackId][baseValue][sign]+=height);}}data.setItemLayout(idx,{x:x,y:y,width:width,height:height});}},this);}// TODO: Do not support stack in large mode yet.\nvar largeLayout={seriesType:'bar',plan:createRenderPlanner(),reset:function reset(seriesModel){if(!isOnCartesian(seriesModel)||!isInLargeMode(seriesModel)){return;}var data=seriesModel.getData();var cartesian=seriesModel.coordinateSystem;var coordLayout=cartesian.grid.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)){// jshint ignore:line\nbarWidth=LARGE_BAR_MIN_WIDTH;}return{progress:progress};function progress(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);// Data index might not be in order, depends on `progressiveChunkMode`.\nlargeBackgroundPoints[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,false),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;}// See cases in `test/bar-start.html` and `#7412`, `#8747`.\nfunction getValueAxisStart(baseAxis,valueAxis,stacked){return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type==='log'?1:0));}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* A third-party license is embeded for some of the code in this file:\n* The \"scaleLevels\" was originally copied from \"d3.js\" with some\n* modifications made for this project.\n* (See more details in the comment on the definition of \"scaleLevels\" below.)\n* The use of the source code of this file is also subject to the terms\n* and consitions of the license of \"d3.js\" (BSD-3Clause, see\n* </licenses/LICENSE-d3>).\n*/ // [About UTC and local time zone]:\n// In most cases, `number.parseDate` will treat input data string as local time\n// (except time zone is specified in time string). And `format.formateTime` returns\n// local time by default. option.useUTC is false by default. This design have\n// concidered these common case:\n// (1) Time that is persistent in server is in UTC, but it is needed to be diplayed\n// in local time by default.\n// (2) By default, the input data string (e.g., '2011-01-02') should be displayed\n// as its original time, without any time difference.\nvar intervalScaleProto=IntervalScale.prototype;var mathCeil=Math.ceil;var mathFloor=Math.floor;var ONE_SECOND=1000;var ONE_MINUTE=ONE_SECOND*60;var ONE_HOUR=ONE_MINUTE*60;var ONE_DAY=ONE_HOUR*24;// FIXME 公用？\nvar bisect=function bisect(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;};/**\n * @alias module:echarts/coord/scale/Time\n * @constructor\n */var TimeScale=IntervalScale.extend({type:'time',/**\n     * @override\n     */getLabel:function getLabel(val){var stepLvl=this._stepLvl;var date=new Date(val);return formatTime(stepLvl[0],date,this.getSetting('useUTC'));},/**\n     * @override\n     */niceExtent:function niceExtent(opt){var extent=this._extent;// If extent start and end are same, expand them\nif(extent[0]===extent[1]){// Expand extent\nextent[0]-=ONE_DAY;extent[1]+=ONE_DAY;}// If there are no data and extent are [Infinity, -Infinity]\nif(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);// var extent = this._extent;\nvar interval=this._interval;if(!opt.fixMin){extent[0]=round$1(mathFloor(extent[0]/interval)*interval);}if(!opt.fixMax){extent[1]=round$1(mathCeil(extent[1]/interval)*interval);}},/**\n     * @override\n     */niceTicks:function niceTicks(approxTickNum,minInterval,maxInterval){approxTickNum=approxTickNum||10;var extent=this._extent;var span=extent[1]-extent[0];var approxInterval=span/approxTickNum;if(minInterval!=null&&approxInterval<minInterval){approxInterval=minInterval;}if(maxInterval!=null&&approxInterval>maxInterval){approxInterval=maxInterval;}var scaleLevelsLen=scaleLevels.length;var idx=bisect(scaleLevels,approxInterval,0,scaleLevelsLen);var level=scaleLevels[Math.min(idx,scaleLevelsLen-1)];var interval=level[1];// Same with interval scale if span is much larger than 1 year\nif(level[0]==='year'){var yearSpan=span/interval;// From \"Nice Numbers for Graph Labels\" of Graphic Gems\n// var niceYearSpan = numberUtil.nice(yearSpan, false);\nvar yearStep=nice(yearSpan/approxTickNum,true);interval*=yearStep;}var timezoneOffset=this.getSetting('useUTC')?0:new Date(+extent[0]||+extent[1]).getTimezoneOffset()*60*1000;var niceExtent=[Math.round(mathCeil((extent[0]-timezoneOffset)/interval)*interval+timezoneOffset),Math.round(mathFloor((extent[1]-timezoneOffset)/interval)*interval+timezoneOffset)];fixExtent(niceExtent,extent);this._stepLvl=level;// Interval will be used in getTicks\nthis._interval=interval;this._niceExtent=niceExtent;},parse:function parse(val){// val might be float.\nreturn+parseDate(val);}});each$1(['contain','normalize'],function(methodName){TimeScale.prototype[methodName]=function(val){return intervalScaleProto[methodName].call(this,this.parse(val));};});/**\n * This implementation was originally copied from \"d3.js\"\n * <https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/time/scale.js>\n * with some modifications made for this program.\n * See the license statement at the head of this file.\n */var scaleLevels=[// Format              interval\n['hh:mm:ss',ONE_SECOND],// 1s\n['hh:mm:ss',ONE_SECOND*5],// 5s\n['hh:mm:ss',ONE_SECOND*10],// 10s\n['hh:mm:ss',ONE_SECOND*15],// 15s\n['hh:mm:ss',ONE_SECOND*30],// 30s\n['hh:mm\\nMM-dd',ONE_MINUTE],// 1m\n['hh:mm\\nMM-dd',ONE_MINUTE*5],// 5m\n['hh:mm\\nMM-dd',ONE_MINUTE*10],// 10m\n['hh:mm\\nMM-dd',ONE_MINUTE*15],// 15m\n['hh:mm\\nMM-dd',ONE_MINUTE*30],// 30m\n['hh:mm\\nMM-dd',ONE_HOUR],// 1h\n['hh:mm\\nMM-dd',ONE_HOUR*2],// 2h\n['hh:mm\\nMM-dd',ONE_HOUR*6],// 6h\n['hh:mm\\nMM-dd',ONE_HOUR*12],// 12h\n['MM-dd\\nyyyy',ONE_DAY],// 1d\n['MM-dd\\nyyyy',ONE_DAY*2],// 2d\n['MM-dd\\nyyyy',ONE_DAY*3],// 3d\n['MM-dd\\nyyyy',ONE_DAY*4],// 4d\n['MM-dd\\nyyyy',ONE_DAY*5],// 5d\n['MM-dd\\nyyyy',ONE_DAY*6],// 6d\n['week',ONE_DAY*7],// 7d\n['MM-dd\\nyyyy',ONE_DAY*10],// 10d\n['week',ONE_DAY*14],// 2w\n['week',ONE_DAY*21],// 3w\n['month',ONE_DAY*31],// 1M\n['week',ONE_DAY*42],// 6w\n['month',ONE_DAY*62],// 2M\n['week',ONE_DAY*70],// 10w\n['quarter',ONE_DAY*95],// 3M\n['month',ONE_DAY*31*4],// 4M\n['month',ONE_DAY*31*5],// 5M\n['half-year',ONE_DAY*380/2],// 6M\n['month',ONE_DAY*31*8],// 8M\n['month',ONE_DAY*31*10],// 10M\n['year',ONE_DAY*380]// 1Y\n];/**\n * @param {module:echarts/model/Model}\n * @return {module:echarts/scale/Time}\n */TimeScale.create=function(model){return new TimeScale({useUTC:model.ecModel.get('useUTC')});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Log scale\n * @module echarts/scale/Log\n */ // Use some method of IntervalScale\nvar scaleProto$1=Scale.prototype;var intervalScaleProto$1=IntervalScale.prototype;var getPrecisionSafe$1=getPrecisionSafe;var roundingErrorFix=round$1;var mathFloor$1=Math.floor;var mathCeil$1=Math.ceil;var mathPow$1=Math.pow;var mathLog=Math.log;var LogScale=Scale.extend({type:'log',base:10,$constructor:function $constructor(){Scale.apply(this,arguments);this._originalScale=new IntervalScale();},/**\n     * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.\n     * @return {Array.<number>}\n     */getTicks:function getTicks(expandToNicedExtent){var originalScale=this._originalScale;var extent=this._extent;var originalExtent=originalScale.getExtent();return map(intervalScaleProto$1.getTicks.call(this,expandToNicedExtent),function(val){var powVal=round$1(mathPow$1(this.base,val));// Fix #4158\npowVal=val===extent[0]&&originalScale.__fixMin?fixRoundingError(powVal,originalExtent[0]):powVal;powVal=val===extent[1]&&originalScale.__fixMax?fixRoundingError(powVal,originalExtent[1]):powVal;return powVal;},this);},/**\n     * @param {number} splitNumber\n     * @return {Array.<Array.<number>>}\n     */getMinorTicks:intervalScaleProto$1.getMinorTicks,/**\n     * @param {number} val\n     * @return {string}\n     */getLabel:intervalScaleProto$1.getLabel,/**\n     * @param  {number} val\n     * @return {number}\n     */scale:function scale(val){val=scaleProto$1.scale.call(this,val);return mathPow$1(this.base,val);},/**\n     * @param {number} start\n     * @param {number} end\n     */setExtent:function setExtent(start,end){var base=this.base;start=mathLog(start)/mathLog(base);end=mathLog(end)/mathLog(base);intervalScaleProto$1.setExtent.call(this,start,end);},/**\n     * @return {number} end\n     */getExtent:function getExtent(){var base=this.base;var extent=scaleProto$1.getExtent.call(this);extent[0]=mathPow$1(base,extent[0]);extent[1]=mathPow$1(base,extent[1]);// Fix #4158\nvar originalScale=this._originalScale;var originalExtent=originalScale.getExtent();originalScale.__fixMin&&(extent[0]=fixRoundingError(extent[0],originalExtent[0]));originalScale.__fixMax&&(extent[1]=fixRoundingError(extent[1],originalExtent[1]));return extent;},/**\n     * @param  {Array.<number>} extent\n     */unionExtent:function unionExtent(extent){this._originalScale.unionExtent(extent);var base=this.base;extent[0]=mathLog(extent[0])/mathLog(base);extent[1]=mathLog(extent[1])/mathLog(base);scaleProto$1.unionExtent.call(this,extent);},/**\n     * @override\n     */unionExtentFromData:function unionExtentFromData(data,dim){// TODO\n// filter value that <= 0\nthis.unionExtent(data.getApproximateExtent(dim));},/**\n     * Update interval and extent of intervals for nice ticks\n     * @param  {number} [approxTickNum = 10] Given approx tick number\n     */niceTicks:function niceTicks(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;// Filter ticks to get closer to the desired count.\nif(err<=0.5){interval*=10;}// Interval should be integer\nwhile(!isNaN(interval)&&Math.abs(interval)<1&&Math.abs(interval)>0){interval*=10;}var niceExtent=[round$1(mathCeil$1(extent[0]/interval)*interval),round$1(mathFloor$1(extent[1]/interval)*interval)];this._interval=interval;this._niceExtent=niceExtent;},/**\n     * Nice extent.\n     * @override\n     */niceExtent:function niceExtent(opt){intervalScaleProto$1.niceExtent.call(this,opt);var originalScale=this._originalScale;originalScale.__fixMin=opt.fixMin;originalScale.__fixMax=opt.fixMax;}});each$1(['contain','normalize'],function(methodName){LogScale.prototype[methodName]=function(val){val=mathLog(val)/mathLog(this.base);return scaleProto$1[methodName].call(this,val);};});LogScale.create=function(){return new LogScale();};function fixRoundingError(val,originalVal){return roundingErrorFix(val,getPrecisionSafe$1(originalVal));}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Get axis scale extent before niced.\n * Item of returned array can only be number (including Infinity and NaN).\n */function getScaleExtent(scale,model){var scaleType=scale.type;var min=model.getMin();var max=model.getMax();var originalExtent=scale.getExtent();var axisDataLen;var boundaryGap;var span;if(scaleType==='ordinal'){axisDataLen=model.getCategories().length;}else{boundaryGap=model.get('boundaryGap');if(!isArray(boundaryGap)){boundaryGap=[boundaryGap||0,boundaryGap||0];}if(typeof boundaryGap[0]==='boolean'){if(__DEV__){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.');}boundaryGap=[0,0];}boundaryGap[0]=parsePercent$1(boundaryGap[0],1);boundaryGap[1]=parsePercent$1(boundaryGap[1],1);span=originalExtent[1]-originalExtent[0]||Math.abs(originalExtent[0]);}// Notice: When min/max is not set (that is, when there are null/undefined,\n// which is the most common case), these cases should be ensured:\n// (1) For 'ordinal', show all axis.data.\n// (2) For others:\n//      + `boundaryGap` is applied (if min/max set, boundaryGap is\n//      disabled).\n//      + If `needCrossZero`, min/max should be zero, otherwise, min/max should\n//      be the result that originalExtent enlarged by boundaryGap.\n// (3) If no data, it should be ensured that `scale.setBlank` is set.\n// FIXME\n// (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used?\n// (2) When `needCrossZero` and all data is positive/negative, should it be ensured\n// that the results processed by boundaryGap are positive/negative?\nif(min==='dataMin'){min=originalExtent[0];}else if(typeof min==='function'){min=min({min:originalExtent[0],max:originalExtent[1]});}if(max==='dataMax'){max=originalExtent[1];}else if(typeof max==='function'){max=max({min:originalExtent[0],max:originalExtent[1]});}var fixMin=min!=null;var fixMax=max!=null;if(min==null){min=scaleType==='ordinal'?axisDataLen?0:NaN:originalExtent[0]-boundaryGap[0]*span;}if(max==null){max=scaleType==='ordinal'?axisDataLen?axisDataLen-1:NaN:originalExtent[1]+boundaryGap[1]*span;}(min==null||!isFinite(min))&&(min=NaN);(max==null||!isFinite(max))&&(max=NaN);scale.setBlank(eqNaN(min)||eqNaN(max)||scaleType==='ordinal'&&!scale.getOrdinalMeta().categories.length);// Evaluate if axis needs cross zero\nif(model.getNeedCrossZero()){// Axis is over zero and min is not set\nif(min>0&&max>0&&!fixMin){min=0;}// Axis is under zero and max is not set\nif(min<0&&max<0&&!fixMax){max=0;}}// If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis\n// is base axis\n// FIXME\n// (1) Consider support value axis, where below zero and axis `onZero` should be handled properly.\n// (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent?\n//     Should not depend on series type `bar`?\n// (3) Fix that might overlap when using dataZoom.\n// (4) Consider other chart types using `barGrid`?\n// See #6728, #4862, `test/bar-overflow-time-plot.html`\nvar ecModel=model.ecModel;if(ecModel&&scaleType==='time'/*|| scaleType === 'interval' */){var barSeriesModels=prepareLayoutBarSeries('bar',ecModel);var isBaseAxisAndHasBarSeries;each$1(barSeriesModels,function(seriesModel){isBaseAxisAndHasBarSeries|=seriesModel.getBaseAxis()===model.axis;});if(isBaseAxisAndHasBarSeries){// Calculate placement of bars on axis\nvar barWidthAndOffset=makeColumnLayout(barSeriesModels);// Adjust axis min and max to account for overflow\nvar adjustedScale=adjustScaleForOverflow(min,max,model,barWidthAndOffset);min=adjustedScale.min;max=adjustedScale.max;}}return{extent:[min,max],// \"fix\" means \"fixed\", the value should not be\n// changed in the subsequent steps.\nfixMin:fixMin,fixMax:fixMax};}function adjustScaleForOverflow(min,max,model,barWidthAndOffset){// Get Axis Length\nvar axisExtent=model.axis.getExtent();var axisLength=axisExtent[1]-axisExtent[0];// Get bars on current base axis and calculate min and max overflow\nvar barsOnCurrentAxis=retrieveColumnLayout(barWidthAndOffset,model.axis);if(barsOnCurrentAxis===undefined){return{min:min,max:max};}var minOverflow=Infinity;each$1(barsOnCurrentAxis,function(item){minOverflow=Math.min(item.offset,minOverflow);});var maxOverflow=-Infinity;each$1(barsOnCurrentAxis,function(item){maxOverflow=Math.max(item.offset+item.width,maxOverflow);});minOverflow=Math.abs(minOverflow);maxOverflow=Math.abs(maxOverflow);var totalOverFlow=minOverflow+maxOverflow;// Calulate required buffer based on old range and overflow\nvar 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.type==='log'){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});// If some one specified the min, max. And the default calculated interval\n// is not good enough. He can specify the interval. It is often appeared\n// in angle axis with angle 0 - 360. Interval calculated in interval scale is hard\n// to be 60.\n// FIXME\nvar interval=model.get('interval');if(interval!=null){scale.setInterval&&scale.setInterval(interval);}}/**\n * @param {module:echarts/model/Model} model\n * @param {string} [axisType] Default retrieve from model.type\n * @return {module:echarts/scale/*}\n */function createScaleByModel(model,axisType){axisType=axisType||model.get('type');if(axisType){switch(axisType){// Buildin scale\ncase'category':return new OrdinalScale(model.getOrdinalMeta?model.getOrdinalMeta():model.getCategories(),[Infinity,-Infinity]);case'value':return new IntervalScale();// Extended scale, like time and log\ndefault:return(Scale.getClass(axisType)||IntervalScale).create(model);}}}/**\n * Check if the axis corss 0\n */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);}/**\n * @param {module:echarts/coord/Axis} axis\n * @return {Function} Label formatter function.\n *         param: {number} tickValue,\n *         param: {number} idx, the index in all ticks.\n *                         If category axis, this param is not requied.\n *         return: {string} label string.\n */function makeLabelFormatter(axis){var labelFormatter=axis.getLabelModel().get('formatter');var categoryTickStart=axis.type==='category'?axis.scale.getExtent()[0]:null;if(typeof labelFormatter==='string'){labelFormatter=function(tpl){return function(val){// For category axis, get raw value; for numeric axis,\n// get foramtted label like '1,333,444'.\nval=axis.scale.getLabel(val);return tpl.replace('{value}',val!=null?val:'');};}(labelFormatter);// Consider empty array\nreturn labelFormatter;}else if(typeof labelFormatter==='function'){return function(tickValue,idx){// The original intention of `idx` is \"the index of the tick in all ticks\".\n// But the previous implementation of category axis do not consider the\n// `axisLabel.interval`, which cause that, for example, the `interval` is\n// `1`, then the ticks \"name5\", \"name7\", \"name9\" are displayed, where the\n// corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep\n// the definition here for back compatibility.\nif(categoryTickStart!=null){idx=tickValue-categoryTickStart;}return labelFormatter(getAxisRawValue(axis,tickValue),idx);};}else{return function(tick){return axis.scale.getLabel(tick);};}}function getAxisRawValue(axis,value){// In category axis with data zoom, tick is not the original\n// index of axis.data. So tick should not be exposed to user\n// in category axis.\nreturn axis.type==='category'?axis.scale.getLabel(value):value;}/**\n * @param {module:echarts/coord/Axis} axis\n * @return {module:zrender/core/BoundingRect} Be null/undefined if no labels.\n */function estimateLabelUnionRect(axis){var axisModel=axis.model;var scale=axis.scale;if(!axisModel.get('axisLabel.show')||scale.isBlank()){return;}var isCategory=axis.type==='category';var realNumberScaleTicks;var tickCount;var categoryScaleExtent=scale.getExtent();// Optimize for large category data, avoid call `getTicks()`.\nif(isCategory){tickCount=scale.count();}else{realNumberScaleTicks=scale.getTicks();tickCount=realNumberScaleTicks.length;}var axisLabelModel=axis.getLabelModel();var labelFormatter=makeLabelFormatter(axis);var rect;var step=1;// Simple optimization for large amount of labels\nif(tickCount>40){step=Math.ceil(tickCount/40);}for(var i=0;i<tickCount;i+=step){var tickValue=realNumberScaleTicks?realNumberScaleTicks[i]:categoryScaleExtent[0]+i;var label=labelFormatter(tickValue);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 boundingBox=textRect.plain();var beforeWidth=boundingBox.width;var beforeHeight=boundingBox.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(boundingBox.x,boundingBox.y,afterWidth,afterHeight);return rotatedRect;}/**\n * @param {module:echarts/src/model/Model} model axisLabelModel or axisTickModel\n * @return {number|String} Can be null|'auto'|number|function\n */function getOptionCategoryInterval(model){var interval=model.get('interval');return interval==null?'auto':interval;}/**\n * Set `categoryInterval` as 0 implicitly indicates that\n * show all labels reguardless of overlap.\n * @param {Object} axis axisModel.axis\n * @return {boolean}\n */function shouldShowAllLabels(axis){return axis.type==='category'&&getOptionCategoryInterval(axis.getLabelModel())===0;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // import * as axisHelper from './axisHelper';\nvar axisModelCommonMixin={/**\n     * @param {boolean} origin\n     * @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN\n     */getMin:function getMin(origin){var option=this.option;var min=!origin&&option.rangeStart!=null?option.rangeStart:option.min;if(this.axis&&min!=null&&min!=='dataMin'&&typeof min!=='function'&&!eqNaN(min)){min=this.axis.scale.parse(min);}return min;},/**\n     * @param {boolean} origin\n     * @return {number|string} max value or 'dataMax' or null/undefined (means auto) or NaN\n     */getMax:function getMax(origin){var option=this.option;var max=!origin&&option.rangeEnd!=null?option.rangeEnd:option.max;if(this.axis&&max!=null&&max!=='dataMax'&&typeof max!=='function'&&!eqNaN(max)){max=this.axis.scale.parse(max);}return max;},/**\n     * @return {boolean}\n     */getNeedCrossZero:function getNeedCrossZero(){var option=this.option;return option.rangeStart!=null||option.rangeEnd!=null?false:!option.scale;},/**\n     * Should be implemented by each axis model if necessary.\n     * @return {module:echarts/model/Component} coordinate system model\n     */getCoordSysModel:noop,/**\n     * @param {number} rangeStart Can only be finite number or null/undefined or NaN.\n     * @param {number} rangeEnd Can only be finite number or null/undefined or NaN.\n     */setRange:function setRange(rangeStart,rangeEnd){this.option.rangeStart=rangeStart;this.option.rangeEnd=rangeEnd;},/**\n     * Reset range\n     */resetRange:function resetRange(){// rangeStart and rangeEnd is readonly.\nthis.option.rangeStart=this.option.rangeEnd=null;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Symbol factory\n/**\n * Triangle shape\n * @inner\n */var Triangle=extendShape({type:'triangle',shape:{cx:0,cy:0,width:0,height:0},buildPath:function buildPath(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();}});/**\n * Diamond shape\n * @inner\n */var Diamond=extendShape({type:'diamond',shape:{cx:0,cy:0,width:0,height:0},buildPath:function buildPath(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();}});/**\n * Pin shape\n * @inner\n */var Pin=extendShape({type:'pin',shape:{// x, y on the cusp\nx:0,y:0,width:0,height:0},buildPath:function buildPath(path,shape){var x=shape.x;var y=shape.y;var w=shape.width/5*3;// Height must be larger than width\nvar h=Math.max(w,shape.height);var r=w/2;// Dist on y with tangent point and circle center\nvar dy=r*r/(h-r);var cy=y-h+r+dy;var angle=Math.asin(dy/r);// Dist on x with tangent point and circle center\nvar 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();}});/**\n * Arrow shape\n * @inner\n */var Arrow=extendShape({type:'arrow',shape:{x:0,y:0,width:0,height:0},buildPath:function buildPath(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();}});/**\n * Map of path contructors\n * @type {Object.<string, module:zrender/graphic/Path>}\n */var symbolCtors={line:Line,rect:Rect,roundRect:Rect,square:Rect,circle:Circle,diamond:Diamond,pin:Pin,arrow:Arrow,triangle:Triangle};var symbolShapeMakers={line:function line(x,y,w,h,shape){// FIXME\nshape.x1=x;shape.y1=y+h/2;shape.x2=x+w;shape.y2=y+h/2;},rect:function rect(x,y,w,h,shape){shape.x=x;shape.y=y;shape.width=w;shape.height=h;},roundRect:function roundRect(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 square(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 circle(x,y,w,h,shape){// Put circle in the center of square\nshape.cx=x+w/2;shape.cy=y+h/2;shape.r=Math.min(w,h)/2;},diamond:function diamond(x,y,w,h,shape){shape.cx=x+w/2;shape.cy=y+h/2;shape.width=w;shape.height=h;},pin:function pin(x,y,w,h,shape){shape.x=x+w/2;shape.y=y+h/2;shape.width=w;shape.height=h;},arrow:function arrow(x,y,w,h,shape){shape.x=x+w/2;shape.y=y+h/2;shape.width=w;shape.height=h;},triangle:function triangle(x,y,w,h,shape){shape.cx=x+w/2;shape.cy=y+h/2;shape.width=w;shape.height=h;}};var symbolBuildProxies={};each$1(symbolCtors,function(Ctor,name){symbolBuildProxies[name]=new Ctor();});var SymbolClz=extendShape({type:'symbol',shape:{symbolType:'',x:0,y:0,width:0,height:0},calculateTextPosition:function calculateTextPosition(out,style,rect){var res=_calculateTextPosition(out,style,rect);var shape=this.shape;if(shape&&shape.symbolType==='pin'&&style.textPosition==='inside'){res.y=rect.y+rect.height*0.4;}return res;},buildPath:function buildPath(ctx,shape,inBundle){var symbolType=shape.symbolType;if(symbolType!=='none'){var proxySymbol=symbolBuildProxies[symbolType];if(!proxySymbol){// Default rect\nsymbolType='rect';proxySymbol=symbolBuildProxies[symbolType];}symbolShapeMakers[symbolType](shape.x,shape.y,shape.width,shape.height,proxySymbol.shape);proxySymbol.buildPath(ctx,proxySymbol.shape,inBundle);}}});// Provide setColor helper method to avoid determine if set the fill or stroke outside\nfunction symbolPathSetColor(color,innerColor){if(this.type!=='image'){var symbolStyle=this.style;var symbolShape=this.shape;if(symbolShape&&symbolShape.symbolType==='line'){symbolStyle.stroke=color;}else if(this.__isEmptyBrush){symbolStyle.stroke=color;symbolStyle.fill=innerColor||'#fff';}else{// FIXME 判断图形默认是填充还是描边，使用 onlyStroke ?\nsymbolStyle.fill&&(symbolStyle.fill=color);symbolStyle.stroke&&(symbolStyle.stroke=color);}this.dirty(false);}}/**\n * Create a symbol element with given symbol configuration: shape, x, y, width, height, color\n * @param {string} symbolType\n * @param {number} x\n * @param {number} y\n * @param {number} w\n * @param {number} h\n * @param {string} color\n * @param {boolean} [keepAspect=false] whether to keep the ratio of w/h,\n *                            for path and image only.\n */function createSymbol(symbolType,x,y,w,h,color,keepAspect){// TODO Support image object, DynamicImage.\nvar 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;symbolPath.setColor(color);return symbolPath;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // import createGraphFromNodeEdge from './chart/helper/createGraphFromNodeEdge';\n/**\n * Create a muti dimension List structure from seriesModel.\n * @param  {module:echarts/model/Model} seriesModel\n * @return {module:echarts/data/List} list\n */function createList(seriesModel){return createListFromArray(seriesModel.getSource(),seriesModel);}var dataStack$1={isDimensionStacked:isDimensionStacked,enableDataStack:enableDataStack,getStackedDimension:getStackedDimension};/**\n * Create scale\n * @param {Array.<number>} dataExtent\n * @param {Object|module:echarts/Model} option\n */function createScale(dataExtent,option){var axisModel=option;if(!Model.isInstance(option)){axisModel=new Model(option);mixin(axisModel,axisModelCommonMixin);}var scale=createScaleByModel(axisModel);scale.setExtent(dataExtent[0],dataExtent[1]);niceScaleExtent(scale,axisModel);return scale;}/**\n * Mixin common methods to axis model,\n *\n * Inlcude methods\n * `getFormattedLabels() => Array.<string>`\n * `getCategories() => Array.<string>`\n * `getMin(origin: boolean) => number`\n * `getMax(origin: boolean) => number`\n * `getNeedCrossZero() => boolean`\n * `setRange(start: number, end: number)`\n * `resetRange()`\n */function mixinAxisModelCommonMethods(Model$$1){mixin(Model$$1,axisModelCommonMixin);}var helper=(Object.freeze||Object)({createList:createList,getLayoutRect:getLayoutRect,dataStack:dataStack$1,createScale:createScale,mixinAxisModelCommonMethods:mixinAxisModelCommonMethods,completeDimensions:completeDimensions,createDimensions:createDimensions,createSymbol:createSymbol});var EPSILON$3=1e-8;function isAroundEqual$1(a,b){return Math.abs(a-b)<EPSILON$3;}function contain$1(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;}// Close polygon\nvar 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;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/coord/geo/Region\n */ /**\n * @param {string|Region} name\n * @param {Array} geometries\n * @param {Array.<number>} cp\n */function Region(name,geometries,cp){/**\n     * @type {string}\n     * @readOnly\n     */this.name=name;/**\n     * @type {Array.<Array>}\n     * @readOnly\n     */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]];}/**\n     * @type {Array.<number>}\n     */this.center=cp;}Region.prototype={constructor:Region,properties:null,/**\n     * @return {module:zrender/core/BoundingRect}\n     */getBoundingRect:function getBoundingRect(){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;for(var i=0;i<geometries.length;i++){// Only support polygon\nif(geometries[i].type!=='polygon'){continue;}// Doesn't consider hole\nvar exterior=geometries[i].exterior;fromPoints(exterior,min2,max2);min(min$$1,min$$1,min2);max(max$$1,max$$1,max2);}// No data\nif(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]);},/**\n     * @param {<Array.<number>} coord\n     * @return {boolean}\n     */contain:function contain(coord){var rect=this.getBoundingRect();var geometries=this.geometries;if(!rect.contain(coord[0],coord[1])){return false;}loopGeo:for(var i=0,len$$1=geometries.length;i<len$$1;i++){// Only support polygon.\nif(geometries[i].type!=='polygon'){continue;}var exterior=geometries[i].exterior;var interiors=geometries[i].interiors;if(contain$1(exterior,coord[0],coord[1])){// Not in the region if point is in the hole.\nfor(var k=0;k<(interiors?interiors.length:0);k++){if(contain$1(interiors[k])){continue loopGeo;}}return true;}}return false;},transformTo:function transformTo(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++){// Only support polygon.\nif(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);// Update center\nthis.center=[rect.x+rect.width/2,rect.y+rect.height/2];},cloneShallow:function cloneShallow(name){name==null&&(name=this.name);var newRegion=new Region(name,this.geometries,this.center);newRegion._rect=this._rect;newRegion.transformTo=null;// Simply avoid to be called.\nreturn newRegion;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Parse and decode geo json\n * @module echarts/coord/geo/parseGeoJson\n */function decode(json){if(!json.UTF8Encoding){return json;}var encodeScale=json.UTF8Scale;if(encodeScale==null){encodeScale=1024;}var features=json.features;for(var f=0;f<features.length;f++){var feature=features[f];var geometry=feature.geometry;var coordinates=geometry.coordinates;var encodeOffsets=geometry.encodeOffsets;for(var c=0;c<coordinates.length;c++){var coordinate=coordinates[c];if(geometry.type==='Polygon'){coordinates[c]=decodePolygon(coordinate,encodeOffsets[c],encodeScale);}else if(geometry.type==='MultiPolygon'){for(var c2=0;c2<coordinate.length;c2++){var polygon=coordinate[c2];coordinate[c2]=decodePolygon(polygon,encodeOffsets[c][c2],encodeScale);}}}}// Has been decoded\njson.UTF8Encoding=false;return json;}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;// ZigZag decoding\nx=x>>1^-(x&1);y=y>>1^-(y&1);// Delta deocding\nx+=prevX;y+=prevY;prevX=x;prevY=y;// Dequantize\nresult.push([x/encodeScale,y/encodeScale]);}return result;}/**\n * @alias module:echarts/coord/geo/parseGeoJson\n * @param {Object} geoJson\n * @param {string} nameProperty\n * @return {module:zrender/container/Group}\n */var parseGeoJSON=function parseGeoJSON(geoJson,nameProperty){decode(geoJson);return map(filter(geoJson.features,function(featureObj){// Output of mapshaper may have geometry null\nreturn featureObj.geometry&&featureObj.properties&&featureObj.geometry.coordinates.length>0;}),function(featureObj){var properties=featureObj.properties;var geo=featureObj.geometry;var coordinates=geo.coordinates;var geometries=[];if(geo.type==='Polygon'){geometries.push({type:'polygon',// According to the GeoJSON specification.\n// First must be exterior, and the rest are all interior(holes).\nexterior:coordinates[0],interiors:coordinates.slice(1)});}if(geo.type==='MultiPolygon'){each$1(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;});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$6=makeInner();/**\n * @param {module:echats/coord/Axis} axis\n * @return {Object} {\n *     labels: [{\n *         formattedLabel: string,\n *         rawLabel: string,\n *         tickValue: number\n *     }, ...],\n *     labelCategoryInterval: number\n * }\n */function createAxisLabels(axis){// Only ordinal scale support tick interval\nreturn axis.type==='category'?makeCategoryLabels(axis):makeRealNumberLabels(axis);}/**\n * @param {module:echats/coord/Axis} axis\n * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea.\n * @return {Object} {\n *     ticks: Array.<number>\n *     tickCategoryInterval: number\n * }\n */function createAxisTicks(axis,tickModel){// Only ordinal scale support tick interval\nreturn axis.type==='category'?makeCategoryTicks(axis,tickModel):{ticks:axis.scale.getTicks()};}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$1(optionLabelInterval)){labels=makeLabelsByCustomizedCategoryInterval(axis,optionLabelInterval);}else{numericLabelInterval=optionLabelInterval==='auto'?makeAutoCategoryInterval(axis):optionLabelInterval;labels=makeLabelsByNumericCategoryInterval(axis,numericLabelInterval);}// Cache to avoid calling interval function repeatly.\nreturn 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;// Optimize for the case that large category data and no label displayed,\n// we should not return all ticks.\nif(!tickModel.get('show')||axis.scale.isBlank()){ticks=[];}if(isFunction$1(optionTickInterval)){ticks=makeLabelsByCustomizedCategoryInterval(axis,optionTickInterval,true);}// Always use label interval by default despite label show. Consider this\n// scenario, Use multiple grid with the xAxis sync, and only one xAxis shows\n// labels. `splitLine` and `axisTick` should be consistent in this case.\nelse 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);}// Cache to avoid calling interval function repeatly.\nreturn listCacheSet(ticksCache,optionTickInterval,{ticks:ticks,tickCategoryInterval:tickCategoryInterval});}function makeRealNumberLabels(axis){var ticks=axis.scale.getTicks();var labelFormatter=makeLabelFormatter(axis);return{labels:map(ticks,function(tickValue,idx){return{formattedLabel:labelFormatter(tickValue,idx),rawLabel:axis.scale.getLabel(tickValue),tickValue:tickValue};})};}// Large category data calculation is performence sensitive, and ticks and label\n// probably be fetched by multiple times. So we cache the result.\n// axis is created each time during a ec process, so we do not need to clear cache.\nfunction getListCache(axis,prop){// Because key can be funciton, and cache size always be small, we use array cache.\nreturn inner$6(axis)[prop]||(inner$6(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$6(axis).autoInterval;return result!=null?result:inner$6(axis).autoInterval=axis.calculateCategoryInterval();}/**\n * Calculate interval for category axis ticks and labels.\n * To get precise result, at least one of `getRotate` and `isHorizontal`\n * should be implemented in axis.\n */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();// Providing this method is for optimization:\n// avoid generating a long array by `getTicks`\n// in large category data case.\nvar tickCount=ordinalScale.count();if(ordinalExtent[1]-ordinalExtent[0]<1){return 0;}var step=1;// Simple optimization. Empirical value: tick count should less than 40.\nif(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;// Caution: Performance sensitive for large category data.\n// Consider dataZoom, we should make appropriate step to avoid O(n) loop.\nfor(;tickValue<=ordinalExtent[1];tickValue+=step){var width=0;var height=0;// Not precise, do not consider align and vertical align\n// and each distance from axis line yet.\nvar rect=_getBoundingRect(labelFormatter(tickValue),params.font,'center','top');// Magic number\nwidth=rect.width*1.3;height=rect.height*1.3;// Min size, void long loop.\nmaxW=Math.max(maxW,width,7);maxH=Math.max(maxH,height,7);}var dw=maxW/unitW;var dh=maxH/unitH;// 0/0 is NaN, 1/0 is Infinity.\nisNaN(dw)&&(dw=Infinity);isNaN(dh)&&(dh=Infinity);var interval=Math.max(0,Math.floor(Math.min(dw,dh)));var cache=inner$6(axis.model);var axisExtent=axis.getExtent();var lastAutoInterval=cache.lastAutoInterval;var lastTickCount=cache.lastTickCount;// Use cache to keep interval stable while moving zoom window,\n// otherwise the calculated interval might jitter when the zoom\n// window size is close to the interval-changing size.\n// For example, if all of the axis labels are `a, b, c, d, e, f, g`.\n// The jitter will cause that sometimes the displayed labels are\n// `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1).\nif(lastAutoInterval!=null&&lastTickCount!=null&&Math.abs(lastAutoInterval-interval)<=1&&Math.abs(lastTickCount-tickCount)<=1// Always choose the bigger one, otherwise the critical\n// point is not the same when zooming in or zooming out.\n&&lastAutoInterval>interval// If the axis change is caused by chart resize, the cache should not\n// be used. Otherwise some hiden labels might not be shown again.\n&&cache.axisExtend0===axisExtent[0]&&cache.axisExtend1===axisExtent[1]){interval=lastAutoInterval;}// Only update cache if cache not used, otherwise the\n// changing of interval is too insensitive.\nelse{cache.lastTickCount=tickCount;cache.lastAutoInterval=interval;cache.axisExtend0=axisExtent[0];cache.axisExtend1=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=[];// TODO: axisType: ordinalTime, pick the tick from each month/day/year/...\nvar step=Math.max((categoryInterval||0)+1,1);var startTick=ordinalExtent[0];var tickCount=ordinalScale.count();// Calculate start tick based on zero if possible to keep label consistent\n// while zooming and moving while interval > 0. Otherwise the selection\n// of displayable ticks and symbols probably keep changing.\n// 3 is empirical value.\nif(startTick!==0&&step>1&&tickCount/step>2){startTick=Math.round(Math.ceil(startTick/step)*step);}// (1) Only add min max label here but leave overlap checking\n// to render stage, which also ensure the returned list\n// suitable for splitLine and splitArea rendering.\n// (2) Scales except category always contain min max label so\n// do not need to perform this process.\nvar showAllLabel=shouldShowAllLabels(axis);var includeMinLabel=labelModel.get('showMinLabel')||showAllLabel;var includeMaxLabel=labelModel.get('showMaxLabel')||showAllLabel;if(includeMinLabel&&startTick!==ordinalExtent[0]){addItem(ordinalExtent[0]);}// Optimize: avoid generating large array by `ordinalScale.getTicks()`.\nvar tickValue=startTick;for(;tickValue<=ordinalExtent[1];tickValue+=step){addItem(tickValue);}if(includeMaxLabel&&tickValue-step!==ordinalExtent[1]){addItem(ordinalExtent[1]);}function addItem(tVal){result.push(onlyTick?tVal:{formattedLabel:labelFormatter(tVal),rawLabel:ordinalScale.getLabel(tVal),tickValue:tVal});}return result;}// When interval is function, the result `false` means ignore the tick.\n// It is time consuming for large category data.\nfunction makeLabelsByCustomizedCategoryInterval(axis,categoryInterval,onlyTick){var ordinalScale=axis.scale;var labelFormatter=makeLabelFormatter(axis);var result=[];each$1(ordinalScale.getTicks(),function(tickValue){var rawLabel=ordinalScale.getLabel(tickValue);if(categoryInterval(tickValue,rawLabel)){result.push(onlyTick?tickValue:{formattedLabel:labelFormatter(tickValue),rawLabel:rawLabel,tickValue:tickValue});}});return result;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var NORMALIZED_EXTENT=[0,1];/**\n * Base class of Axis.\n * @constructor\n */var Axis=function Axis(dim,scale,extent){/**\n     * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'.\n     * @type {string}\n     */this.dim=dim;/**\n     * Axis scale\n     * @type {module:echarts/coord/scale/*}\n     */this.scale=scale;/**\n     * @type {Array.<number>}\n     * @private\n     */this._extent=extent||[0,0];/**\n     * @type {boolean}\n     */this.inverse=false;/**\n     * Usually true when axis has a ordinal scale\n     * @type {boolean}\n     */this.onBand=false;};Axis.prototype={constructor:Axis,/**\n     * If axis extent contain given coord\n     * @param {number} coord\n     * @return {boolean}\n     */contain:function contain(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;},/**\n     * If axis extent contain given data\n     * @param {number} data\n     * @return {boolean}\n     */containData:function containData(data){return this.scale.contain(data);},/**\n     * Get coord extent.\n     * @return {Array.<number>}\n     */getExtent:function getExtent(){return this._extent.slice();},/**\n     * Get precision used for formatting\n     * @param {Array.<number>} [dataExtent]\n     * @return {number}\n     */getPixelPrecision:function getPixelPrecision(dataExtent){return _getPixelPrecision(dataExtent||this.scale.getExtent(),this._extent);},/**\n     * Set coord extent\n     * @param {number} start\n     * @param {number} end\n     */setExtent:function setExtent(start,end){var extent=this._extent;extent[0]=start;extent[1]=end;},/**\n     * Convert data to coord. Data is the rank if it has an ordinal scale\n     * @param {number} data\n     * @param  {boolean} clamp\n     * @return {number}\n     */dataToCoord:function dataToCoord(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);},/**\n     * Convert coord to data. Data is the rank if it has an ordinal scale\n     * @param {number} coord\n     * @param  {boolean} clamp\n     * @return {number}\n     */coordToData:function coordToData(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);},/**\n     * Convert pixel point to data in axis\n     * @param {Array.<number>} point\n     * @param  {boolean} clamp\n     * @return {number} data\n     */pointToData:function pointToData(point,clamp){// Should be implemented in derived class if necessary.\n},/**\n     * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,\n     * `axis.getTicksCoords` considers `onBand`, which is used by\n     * `boundaryGap:true` of category axis and splitLine and splitArea.\n     * @param {Object} [opt]\n     * @param {Model} [opt.tickModel=axis.model.getModel('axisTick')]\n     * @param {boolean} [opt.clamp] If `true`, the first and the last\n     *        tick must be at the axis end points. Otherwise, clip ticks\n     *        that outside the axis extent.\n     * @return {Array.<Object>} [{\n     *     coord: ...,\n     *     tickValue: ...\n     * }, ...]\n     */getTicksCoords:function getTicksCoords(opt){opt=opt||{};var tickModel=opt.tickModel||this.getTickModel();var result=createAxisTicks(this,tickModel);var ticks=result.ticks;var ticksCoords=map(ticks,function(tickValue){return{coord:this.dataToCoord(tickValue),tickValue:tickValue};},this);var alignWithLabel=tickModel.get('alignWithLabel');fixOnBandTicksCoords(this,ticksCoords,alignWithLabel,opt.clamp);return ticksCoords;},/**\n     * @return {Array.<Array.<Object>>} [{ coord: ..., tickValue: ...}]\n     */getMinorTicksCoords:function getMinorTicksCoords(){if(this.scale.type==='ordinal'){// Category axis doesn't support minor ticks\nreturn[];}var minorTickModel=this.model.getModel('minorTick');var splitNumber=minorTickModel.get('splitNumber');// Protection.\nif(!(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;},/**\n     * @return {Array.<Object>} [{\n     *     formattedLabel: string,\n     *     rawLabel: axis.scale.getLabel(tickValue)\n     *     tickValue: number\n     * }, ...]\n     */getViewLabels:function getViewLabels(){return createAxisLabels(this).labels;},/**\n     * @return {module:echarts/coord/model/Model}\n     */getLabelModel:function getLabelModel(){return this.model.getModel('axisLabel');},/**\n     * Notice here we only get the default tick model. For splitLine\n     * or splitArea, we should pass the splitLineModel or splitAreaModel\n     * manually when calling `getTicksCoords`.\n     * In GL, this method may be overrided to:\n     * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));`\n     * @return {module:echarts/coord/model/Model}\n     */getTickModel:function getTickModel(){return this.model.getModel('axisTick');},/**\n     * Get width of band\n     * @return {number}\n     */getBandWidth:function getBandWidth(){var axisExtent=this._extent;var dataExtent=this.scale.getExtent();var len=dataExtent[1]-dataExtent[0]+(this.onBand?1:0);// Fix #2728, avoid NaN when only one data.\nlen===0&&(len=1);var size=Math.abs(axisExtent[1]-axisExtent[0]);return Math.abs(size)/len;},/**\n     * @abstract\n     * @return {boolean} Is horizontal\n     */isHorizontal:null,/**\n     * @abstract\n     * @return {number} Get axis rotate, by degree.\n     */getRotate:null,/**\n     * Only be called in category axis.\n     * Can be overrided, consider other axes like in 3D.\n     * @return {number} Auto interval for cateogry axis tick and label\n     */calculateCategoryInterval:function calculateCategoryInterval(){return _calculateCategoryInterval(this);}};function fixExtentWithBands(extent,nTick){var size=extent[1]-extent[0];var len=nTick;var margin=size/len/2;extent[0]+=margin;extent[1]-=margin;}// If axis has labels [1, 2, 3, 4]. Bands on the axis are\n// |---1---|---2---|---3---|---4---|.\n// So the displayed ticks and splitLine/splitArea should between\n// each data item, otherwise cause misleading (e.g., split tow bars\n// of a single data item when there are two bar series).\n// Also consider if tickCategoryInterval > 0 and onBand, ticks and\n// splitLine/spliteArea should layout appropriately corresponding\n// to displayed labels. (So we should not use `getBandWidth` in this\n// case).\nfunction 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=(ticksCoords[ticksLen-1].coord-ticksCoords[0].coord)/crossLen;each$1(ticksCoords,function(ticksItem){ticksItem.coord-=shift/2;});var dataExtent=axis.scale.getExtent();diffSize=1+dataExtent[1]-ticksCoords[ticksLen-1].tickValue;last={coord:ticksCoords[ticksLen-1].coord+shift*diffSize};ticksCoords.push(last);}var inverse=axisExtent[0]>axisExtent[1];// Handling clamp.\nif(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){// Avoid rounding error cause calculated tick coord different with extent.\n// It may cause an extra unecessary tick added.\na=round$1(a);b=round$1(b);return inverse?a>b:a<b;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Do not mount those modules on 'src/echarts' for better tree shaking.\n */var parseGeoJson=parseGeoJSON;var ecUtil={};each$1(['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$1={};each$1(['extendShape','extendPath','makePath','makeImage','mergePath','resizePath','createIcon','setHoverStyle','setLabelStyle','setTextStyle','setText','getFont','updateProps','initProps','getTransform','clipPointsByRect','clipRectByRect','registerShape','getShapeClass','Group','Image','Text','Circle','Sector','Ring','Polygon','Polyline','Rect','Line','BezierCurve','Arc','IncrementalDisplayable','CompoundPath','LinearGradient','RadialGradient','BoundingRect'],function(name){graphic$1[name]=graphic[name];});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/SeriesModel.extend({type:'series.line',dependencies:['grid','polar'],getInitialData:function getInitialData(option,ecModel){if(__DEV__){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});},defaultOption:{zlevel:0,z:2,coordinateSystem:'cartesian2d',legendHoverLink:true,hoverAnimation:true,// stack: null\n// xAxisIndex: 0,\n// yAxisIndex: 0,\n// polarIndex: 0,\n// If clip the overflow value\nclip:true,// cursor: null,\nlabel:{position:'top'},// itemStyle: {\n// },\nlineStyle:{width:2,type:'solid'},// areaStyle: {\n// origin of areaStyle. Valid values:\n// `'auto'/null/undefined`: from axisLine to data\n// `'start'`: from min to data\n// `'end'`: from data to max\n// origin: 'auto'\n// },\n// false, 'start', 'end', 'middle'\nstep:false,// Disabled if step is true\nsmooth:false,smoothMonotone:null,symbol:'emptyCircle',symbolSize:4,symbolRotate:null,showSymbol:true,// `false`: follow the label interval strategy.\n// `true`: show all symbols.\n// `'auto'`: If possible, show all symbols, otherwise\n//           follow the label interval strategy.\nshowAllSymbol:'auto',// Whether to connect break point.\nconnectNulls:false,// Sampling for large data. Can be: 'average', 'max', 'min', 'sum'.\nsampling:'none',animationEasing:'linear',// Disable progressive\nprogressive:0,hoverLayerThreshold:Infinity}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {module:echarts/data/List} data\n * @param {number} dataIndex\n * @return {string} label string. Not null/undefined\n */function getDefaultLabel(data,dataIndex){var labelDims=data.mapDimension('defaultedLabel',true);var len=labelDims.length;// Simple optimization (in lots of cases, label dims length is 1)\nif(len===1){return retrieveRawValue(data,dataIndex,labelDims[0]);}else if(len){var vals=[];for(var i=0;i<labelDims.length;i++){var val=retrieveRawValue(data,dataIndex,labelDims[i]);vals.push(val);}return vals.join(' ');}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/chart/helper/Symbol\n */ /**\n * @constructor\n * @alias {module:echarts/chart/helper/Symbol}\n * @param {module:echarts/data/List} data\n * @param {number} idx\n * @extends {module:zrender/graphic/Group}\n */function SymbolClz$1(data,idx,seriesScope){Group.call(this);this.updateData(data,idx,seriesScope);}var symbolProto=SymbolClz$1.prototype;/**\n * @public\n * @static\n * @param {module:echarts/data/List} data\n * @param {number} dataIndex\n * @return {Array.<number>} [width, height]\n */var getSymbolSize=SymbolClz$1.getSymbolSize=function(data,idx){var symbolSize=data.getItemVisual(idx,'symbolSize');return symbolSize instanceof Array?symbolSize.slice():[+symbolSize,+symbolSize];};function getScale(symbolSize){return[symbolSize[0]/2,symbolSize[1]/2];}function driftSymbol(dx,dy){this.parent.drift(dx,dy);}symbolProto._createSymbol=function(symbolType,data,idx,symbolSize,keepAspect){// Remove paths created before\nthis.removeAll();var color=data.getItemVisual(idx,'color');// var symbolPath = createSymbol(\n//     symbolType, -0.5, -0.5, 1, 1, color\n// );\n// If width/height are set too small (e.g., set to 1) on ios10\n// and macOS Sierra, a circle stroke become a rect, no matter what\n// the scale is set. So we set width/height as 2. See #4150.\nvar symbolPath=createSymbol(symbolType,-1,-1,2,2,color,keepAspect);symbolPath.attr({z2:100,culling:true,scale:getScale(symbolSize)});// Rewrite drift method\nsymbolPath.drift=driftSymbol;this._symbolType=symbolType;this.add(symbolPath);};/**\n * Stop animation\n * @param {boolean} toLastFrame\n */symbolProto.stopSymbolAnimation=function(toLastFrame){this.childAt(0).stopAnimation(toLastFrame);};/**\n * FIXME:\n * Caution: This method breaks the encapsulation of this module,\n * but it indeed brings convenience. So do not use the method\n * unless you detailedly know all the implements of `Symbol`,\n * especially animation.\n *\n * Get symbol path element.\n */symbolProto.getSymbolPath=function(){return this.childAt(0);};/**\n * Get scale(aka, current symbol size).\n * Including the change caused by animation\n */symbolProto.getScale=function(){return this.childAt(0).scale;};/**\n * Highlight symbol\n */symbolProto.highlight=function(){this.childAt(0).trigger('emphasis');};/**\n * Downplay symbol\n */symbolProto.downplay=function(){this.childAt(0).trigger('normal');};/**\n * @param {number} zlevel\n * @param {number} z\n */symbolProto.setZ=function(zlevel,z){var symbolPath=this.childAt(0);symbolPath.zlevel=zlevel;symbolPath.z=z;};symbolProto.setDraggable=function(draggable){var symbolPath=this.childAt(0);symbolPath.draggable=draggable;symbolPath.cursor=draggable?'move':symbolPath.cursor;};/**\n * Update symbol properties\n * @param {module:echarts/data/List} data\n * @param {number} idx\n * @param {Object} [seriesScope]\n * @param {Object} [seriesScope.itemStyle]\n * @param {Object} [seriesScope.hoverItemStyle]\n * @param {Object} [seriesScope.symbolRotate]\n * @param {Object} [seriesScope.symbolOffset]\n * @param {module:echarts/model/Model} [seriesScope.labelModel]\n * @param {module:echarts/model/Model} [seriesScope.hoverLabelModel]\n * @param {boolean} [seriesScope.hoverAnimation]\n * @param {Object} [seriesScope.cursorStyle]\n * @param {module:echarts/model/Model} [seriesScope.itemModel]\n * @param {string} [seriesScope.symbolInnerColor]\n * @param {Object} [seriesScope.fadeIn=false]\n */symbolProto.updateData=function(data,idx,seriesScope){this.silent=false;var symbolType=data.getItemVisual(idx,'symbol')||'circle';var seriesModel=data.hostModel;var symbolSize=getSymbolSize(data,idx);var isInit=symbolType!==this._symbolType;if(isInit){var keepAspect=data.getItemVisual(idx,'symbolKeepAspect');this._createSymbol(symbolType,data,idx,symbolSize,keepAspect);}else{var symbolPath=this.childAt(0);symbolPath.silent=false;updateProps(symbolPath,{scale:getScale(symbolSize)},seriesModel,idx);}this._updateCommon(data,idx,symbolSize,seriesScope);if(isInit){var symbolPath=this.childAt(0);var fadeIn=seriesScope&&seriesScope.fadeIn;var target={scale:symbolPath.scale.slice()};fadeIn&&(target.style={opacity:symbolPath.style.opacity});symbolPath.scale=[0,0];fadeIn&&(symbolPath.style.opacity=0);initProps(symbolPath,target,seriesModel,idx);}this._seriesModel=seriesModel;};// Update common properties\nvar normalStyleAccessPath=['itemStyle'];var emphasisStyleAccessPath=['emphasis','itemStyle'];var normalLabelAccessPath=['label'];var emphasisLabelAccessPath=['emphasis','label'];/**\n * @param {module:echarts/data/List} data\n * @param {number} idx\n * @param {Array.<number>} symbolSize\n * @param {Object} [seriesScope]\n */symbolProto._updateCommon=function(data,idx,symbolSize,seriesScope){var symbolPath=this.childAt(0);var seriesModel=data.hostModel;var color=data.getItemVisual(idx,'color');// Reset style\nif(symbolPath.type!=='image'){symbolPath.useStyle({strokeNoScale:true});}else{symbolPath.setStyle({opacity:1,shadowBlur:null,shadowOffsetX:null,shadowOffsetY:null,shadowColor:null});}var itemStyle=seriesScope&&seriesScope.itemStyle;var hoverItemStyle=seriesScope&&seriesScope.hoverItemStyle;var symbolOffset=seriesScope&&seriesScope.symbolOffset;var labelModel=seriesScope&&seriesScope.labelModel;var hoverLabelModel=seriesScope&&seriesScope.hoverLabelModel;var hoverAnimation=seriesScope&&seriesScope.hoverAnimation;var cursorStyle=seriesScope&&seriesScope.cursorStyle;if(!seriesScope||data.hasItemOption){var itemModel=seriesScope&&seriesScope.itemModel?seriesScope.itemModel:data.getItemModel(idx);// Color must be excluded.\n// Because symbol provide setColor individually to set fill and stroke\nitemStyle=itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']);hoverItemStyle=itemModel.getModel(emphasisStyleAccessPath).getItemStyle();symbolOffset=itemModel.getShallow('symbolOffset');labelModel=itemModel.getModel(normalLabelAccessPath);hoverLabelModel=itemModel.getModel(emphasisLabelAccessPath);hoverAnimation=itemModel.getShallow('hoverAnimation');cursorStyle=itemModel.getShallow('cursor');}else{hoverItemStyle=extend({},hoverItemStyle);}var elStyle=symbolPath.style;var symbolRotate=data.getItemVisual(idx,'symbolRotate');symbolPath.attr('rotation',(symbolRotate||0)*Math.PI/180||0);if(symbolOffset){symbolPath.attr('position',[parsePercent$1(symbolOffset[0],symbolSize[0]),parsePercent$1(symbolOffset[1],symbolSize[1])]);}cursorStyle&&symbolPath.attr('cursor',cursorStyle);// PENDING setColor before setStyle!!!\nsymbolPath.setColor(color,seriesScope&&seriesScope.symbolInnerColor);symbolPath.setStyle(itemStyle);var opacity=data.getItemVisual(idx,'opacity');if(opacity!=null){elStyle.opacity=opacity;}var liftZ=data.getItemVisual(idx,'liftZ');var z2Origin=symbolPath.__z2Origin;if(liftZ!=null){if(z2Origin==null){symbolPath.__z2Origin=symbolPath.z2;symbolPath.z2+=liftZ;}}else if(z2Origin!=null){symbolPath.z2=z2Origin;symbolPath.__z2Origin=null;}var useNameLabel=seriesScope&&seriesScope.useNameLabel;setLabelStyle(elStyle,hoverItemStyle,labelModel,hoverLabelModel,{labelFetcher:seriesModel,labelDataIndex:idx,defaultText:getLabelDefaultText,isRectText:true,autoColor:color});// Do not execute util needed.\nfunction getLabelDefaultText(idx,opt){return useNameLabel?data.getName(idx):getDefaultLabel(data,idx);}symbolPath.__symbolOriginalScale=getScale(symbolSize);symbolPath.hoverStyle=hoverItemStyle;symbolPath.highDownOnUpdate=hoverAnimation&&seriesModel.isAnimationEnabled()?highDownOnUpdate:null;setHoverStyle(symbolPath);};function highDownOnUpdate(fromState,toState){// Do not support this hover animation util some scenario required.\n// Animation can only be supported in hover layer when using `el.incremetal`.\nif(this.incremental||this.useHoverLayer){return;}if(toState==='emphasis'){var scale=this.__symbolOriginalScale;var ratio=scale[1]/scale[0];var emphasisOpt={scale:[Math.max(scale[0]*1.1,scale[0]+3),Math.max(scale[1]*1.1,scale[1]+3*ratio)]};// FIXME\n// modify it after support stop specified animation.\n// toState === fromState\n//     ? (this.stopAnimation(), this.attr(emphasisOpt))\nthis.animateTo(emphasisOpt,400,'elasticOut');}else if(toState==='normal'){this.animateTo({scale:this.__symbolOriginalScale},400,'elasticOut');}}/**\n * @param {Function} cb\n * @param {Object} [opt]\n * @param {Object} [opt.keepLabel=true]\n */symbolProto.fadeOut=function(cb,opt){var symbolPath=this.childAt(0);// Avoid mistaken hover when fading out\nthis.silent=symbolPath.silent=true;// Not show text when animating\n!(opt&&opt.keepLabel)&&(symbolPath.style.text=null);updateProps(symbolPath,{style:{opacity:0},scale:[0,0]},this._seriesModel,this.dataIndex,cb);};inherits(SymbolClz$1,Group);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/chart/helper/SymbolDraw\n */ /**\n * @constructor\n * @alias module:echarts/chart/helper/SymbolDraw\n * @param {module:zrender/graphic/Group} [symbolCtor]\n */function SymbolDraw(symbolCtor){this.group=new Group();this._symbolCtor=symbolCtor||SymbolClz$1;}var symbolDrawProto=SymbolDraw.prototype;function symbolNeedsDraw(data,point,idx,opt){return point&&!isNaN(point[0])&&!isNaN(point[1])&&!(opt.isIgnore&&opt.isIgnore(idx))// We do not set clipShape on group, because it will cut part of\n// the symbol element shape. We use the same clip shape here as\n// the line clip.\n&&!(opt.clipShape&&!opt.clipShape.contain(point[0],point[1]))&&data.getItemVisual(idx,'symbol')!=='none';}/**\n * Update symbols draw by new data\n * @param {module:echarts/data/List} data\n * @param {Object} [opt] Or isIgnore\n * @param {Function} [opt.isIgnore]\n * @param {Object} [opt.clipShape]\n */symbolDrawProto.updateData=function(data,opt){opt=normalizeUpdateOpt(opt);var group=this.group;var seriesModel=data.hostModel;var oldData=this._data;var SymbolCtor=this._symbolCtor;var seriesScope=makeSeriesScope(data);// There is no oldLineData only when first rendering or switching from\n// stream mode to normal mode, where previous elements should be removed.\nif(!oldData){group.removeAll();}data.diff(oldData).add(function(newIdx){var point=data.getItemLayout(newIdx);if(symbolNeedsDraw(data,point,newIdx,opt)){var symbolEl=new SymbolCtor(data,newIdx,seriesScope);symbolEl.attr('position',point);data.setItemGraphicEl(newIdx,symbolEl);group.add(symbolEl);}}).update(function(newIdx,oldIdx){var symbolEl=oldData.getItemGraphicEl(oldIdx);var point=data.getItemLayout(newIdx);if(!symbolNeedsDraw(data,point,newIdx,opt)){group.remove(symbolEl);return;}if(!symbolEl){symbolEl=new SymbolCtor(data,newIdx);symbolEl.attr('position',point);}else{symbolEl.updateData(data,newIdx,seriesScope);updateProps(symbolEl,{position:point},seriesModel);}// Add back\ngroup.add(symbolEl);data.setItemGraphicEl(newIdx,symbolEl);}).remove(function(oldIdx){var el=oldData.getItemGraphicEl(oldIdx);el&&el.fadeOut(function(){group.remove(el);});}).execute();this._data=data;};symbolDrawProto.isPersistent=function(){return true;};symbolDrawProto.updateLayout=function(){var data=this._data;if(data){// Not use animation\ndata.eachItemGraphicEl(function(el,idx){var point=data.getItemLayout(idx);el.attr('position',point);});}};symbolDrawProto.incrementalPrepareUpdate=function(data){this._seriesScope=makeSeriesScope(data);this._data=null;this.group.removeAll();};/**\n * Update symbols draw by new data\n * @param {module:echarts/data/List} data\n * @param {Object} [opt] Or isIgnore\n * @param {Function} [opt.isIgnore]\n * @param {Object} [opt.clipShape]\n */symbolDrawProto.incrementalUpdate=function(taskParams,data,opt){opt=normalizeUpdateOpt(opt);function updateIncrementalAndHover(el){if(!el.isGroup){el.incremental=el.useHoverLayer=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.attr('position',point);this.group.add(el);data.setItemGraphicEl(idx,el);}}};function normalizeUpdateOpt(opt){if(opt!=null&&!isObject$1(opt)){opt={isIgnore:opt};}return opt||{};}symbolDrawProto.remove=function(enableAnimation){var group=this.group;var data=this._data;// Incremental model do not have this._data.\nif(data&&enableAnimation){data.eachItemGraphicEl(function(el){el.fadeOut(function(){group.remove(el);});});}else{group.removeAll();}};function makeSeriesScope(data){var seriesModel=data.hostModel;return{itemStyle:seriesModel.getModel('itemStyle').getItemStyle(['color']),hoverItemStyle:seriesModel.getModel('emphasis.itemStyle').getItemStyle(),symbolRotate:seriesModel.get('symbolRotate'),symbolOffset:seriesModel.get('symbolOffset'),hoverAnimation:seriesModel.get('hoverAnimation'),labelModel:seriesModel.getModel('label'),hoverLabelModel:seriesModel.getModel('emphasis.label'),cursorStyle:seriesModel.get('cursor')};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {Object} coordSys\n * @param {module:echarts/data/List} data\n * @param {string} valueOrigin lineSeries.option.areaStyle.origin\n */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;var stackResultDim=data.getCalculationInfo('stackResultDimension');if(stacked|=isDimensionStacked(data,dims[0]/*, dims[1]*/)){// jshint ignore:line\ndims[0]=stackResultDim;}if(stacked|=isDimensionStacked(data,dims[1]/*, dims[0]*/)){// jshint ignore:line\ndims[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];}// auto\nelse{// Both positive\nif(extent[0]>0){valueStart=extent[0];}// Both negative\nelse if(extent[1]<0){valueStart=extent[1];}// If is one positive, and one negative, onZero shall be true\n}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);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // var arrayDiff = require('zrender/src/core/arrayDiff');\n// 'zrender/src/core/arrayDiff' has been used before, but it did\n// not do well in performance when roam with fixed dataZoom window.\n// function convertToIntId(newIdList, oldIdList) {\n//     // Generate int id instead of string id.\n//     // Compare string maybe slow in score function of arrDiff\n//     // Assume id in idList are all unique\n//     var idIndicesMap = {};\n//     var idx = 0;\n//     for (var i = 0; i < newIdList.length; i++) {\n//         idIndicesMap[newIdList[i]] = idx;\n//         newIdList[i] = idx++;\n//     }\n//     for (var i = 0; i < oldIdList.length; i++) {\n//         var oldId = oldIdList[i];\n//         // Same with newIdList\n//         if (idIndicesMap[oldId]) {\n//             oldIdList[i] = idIndicesMap[oldId];\n//         }\n//         else {\n//             oldIdList[i] = idx++;\n//         }\n//     }\n// }\nfunction 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;}var lineAnimationDiff=function lineAnimationDiff(oldData,newData,oldStackedOnPoints,newStackedOnPoints,oldCoordSys,newCoordSys,oldValueOrigin,newValueOrigin){var diff=diffData(oldData,newData);// var newIdList = newData.mapArray(newData.getId);\n// var oldIdList = oldData.mapArray(oldData.getId);\n// convertToIntId(newIdList, oldIdList);\n// // FIXME One data ?\n// diff = arrayDiff(oldIdList, newIdList);\nvar currPoints=[];var nextPoints=[];// Points for stacking base line\nvar currStackedPoints=[];var nextStackedPoints=[];var status=[];var sortedIndices=[];var rawIndices=[];var newDataOldCoordInfo=prepareDataCoordInfo(oldCoordSys,newData,oldValueOrigin);var oldDataNewCoordInfo=prepareDataCoordInfo(newCoordSys,oldData,newValueOrigin);for(var i=0;i<diff.length;i++){var diffItem=diff[i];var pointAdded=true;// FIXME, animation is not so perfect when dataZoom window moves fast\n// Which is in case remvoing or add more than one data in the tail or head\nswitch(diffItem.cmd){case'=':var currentPt=oldData.getItemLayout(diffItem.idx);var nextPt=newData.getItemLayout(diffItem.idx1);// If previous data is NaN, use next point directly\nif(isNaN(currentPt[0])||isNaN(currentPt[1])){currentPt=nextPt.slice();}currPoints.push(currentPt);nextPoints.push(nextPt);currStackedPoints.push(oldStackedOnPoints[diffItem.idx]);nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]);rawIndices.push(newData.getRawIndex(diffItem.idx1));break;case'+':var idx=diffItem.idx;currPoints.push(oldCoordSys.dataToPoint([newData.get(newDataOldCoordInfo.dataDimsForPoint[0],idx),newData.get(newDataOldCoordInfo.dataDimsForPoint[1],idx)]));nextPoints.push(newData.getItemLayout(idx).slice());currStackedPoints.push(getStackedOnPoint(newDataOldCoordInfo,oldCoordSys,newData,idx));nextStackedPoints.push(newStackedOnPoints[idx]);rawIndices.push(newData.getRawIndex(idx));break;case'-':var idx=diffItem.idx;var rawIndex=oldData.getRawIndex(idx);// Data is replaced. In the case of dynamic data queue\n// FIXME FIXME FIXME\nif(rawIndex!==idx){currPoints.push(oldData.getItemLayout(idx));nextPoints.push(newCoordSys.dataToPoint([oldData.get(oldDataNewCoordInfo.dataDimsForPoint[0],idx),oldData.get(oldDataNewCoordInfo.dataDimsForPoint[1],idx)]));currStackedPoints.push(oldStackedOnPoints[idx]);nextStackedPoints.push(getStackedOnPoint(oldDataNewCoordInfo,newCoordSys,oldData,idx));rawIndices.push(rawIndex);}else{pointAdded=false;}}// Original indices\nif(pointAdded){status.push(diffItem);sortedIndices.push(sortedIndices.length);}}// Diff result may be crossed if all items are changed\n// Sort by data index\nsortedIndices.sort(function(a,b){return rawIndices[a]-rawIndices[b];});var sortedCurrPoints=[];var sortedNextPoints=[];var sortedCurrStackedPoints=[];var sortedNextStackedPoints=[];var sortedStatus=[];for(var i=0;i<sortedIndices.length;i++){var idx=sortedIndices[i];sortedCurrPoints[i]=currPoints[idx];sortedNextPoints[i]=nextPoints[idx];sortedCurrStackedPoints[i]=currStackedPoints[idx];sortedNextStackedPoints[i]=nextStackedPoints[idx];sortedStatus[i]=status[idx];}return{current:sortedCurrPoints,next:sortedNextPoints,stackedOnCurrent:sortedCurrStackedPoints,stackedOnNext:sortedNextStackedPoints,status:sortedStatus};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Poly path support NaN point\nvar vec2Min=min;var vec2Max=max;var scaleAndAdd$1=scaleAndAdd;var v2Copy=copy;// Temporary variable\nvar v=[];var cp0=[];var cp1=[];function isPointNull(p){return isNaN(p[0])||isNaN(p[1]);}function drawSegment(ctx,points,start,segLen,allLen,dir,smoothMin,smoothMax,smooth,smoothMonotone,connectNulls){// if (smoothMonotone == null) {\n//     if (isMono(points, 'x')) {\n//         return drawMono(ctx, points, start, segLen, allLen,\n//             dir, smoothMin, smoothMax, smooth, 'x', connectNulls);\n//     }\n//     else if (isMono(points, 'y')) {\n//         return drawMono(ctx, points, start, segLen, allLen,\n//             dir, smoothMin, smoothMax, smooth, 'y', connectNulls);\n//     }\n//     else {\n//         return drawNonMono.apply(this, arguments);\n//     }\n// }\n// else if (smoothMonotone !== 'none' && isMono(points, smoothMonotone)) {\n//     return drawMono.apply(this, arguments);\n// }\n// else {\n//     return drawNonMono.apply(this, arguments);\n// }\nif(smoothMonotone==='none'||!smoothMonotone){return drawNonMono.apply(this,arguments);}else{return drawMono.apply(this,arguments);}}/**\n * Check if points is in monotone.\n *\n * @param {number[][]} points         Array of points which is in [x, y] form\n * @param {string}     smoothMonotone 'x', 'y', or 'none', stating for which\n *                                    dimension that is checking.\n *                                    If is 'none', `drawNonMono` should be\n *                                    called.\n *                                    If is undefined, either being monotone\n *                                    in 'x' or 'y' will call `drawMono`.\n */ // function isMono(points, smoothMonotone) {\n//     if (points.length <= 1) {\n//         return true;\n//     }\n//     var dim = smoothMonotone === 'x' ? 0 : 1;\n//     var last = points[0][dim];\n//     var lastDiff = 0;\n//     for (var i = 1; i < points.length; ++i) {\n//         var diff = points[i][dim] - last;\n//         if (!isNaN(diff) && !isNaN(lastDiff)\n//             && diff !== 0 && lastDiff !== 0\n//             && ((diff >= 0) !== (lastDiff >= 0))\n//         ) {\n//             return false;\n//         }\n//         if (!isNaN(diff) && diff !== 0) {\n//             lastDiff = diff;\n//             last = points[i][dim];\n//         }\n//     }\n//     return true;\n// }\n/**\n * Draw smoothed line in monotone, in which only vertical or horizontal bezier\n * control points will be used. This should be used when points are monotone\n * either in x or y dimension.\n */function drawMono(ctx,points,start,segLen,allLen,dir,smoothMin,smoothMax,smooth,smoothMonotone,connectNulls){var prevIdx=0;var idx=start;for(var k=0;k<segLen;k++){var p=points[idx];if(idx>=allLen||idx<0){break;}if(isPointNull(p)){if(connectNulls){idx+=dir;continue;}break;}if(idx===start){ctx[dir>0?'moveTo':'lineTo'](p[0],p[1]);}else{if(smooth>0){var prevP=points[prevIdx];var dim=smoothMonotone==='y'?1:0;// Length of control point to p, either in x or y, but not both\nvar ctrlLen=(p[dim]-prevP[dim])*smooth;v2Copy(cp0,prevP);cp0[dim]=prevP[dim]+ctrlLen;v2Copy(cp1,p);cp1[dim]=p[dim]-ctrlLen;ctx.bezierCurveTo(cp0[0],cp0[1],cp1[0],cp1[1],p[0],p[1]);}else{ctx.lineTo(p[0],p[1]);}}prevIdx=idx;idx+=dir;}return k;}/**\n * Draw smoothed line in non-monotone, in may cause undesired curve in extreme\n * situations. This should be used when points are non-monotone neither in x or\n * y dimension.\n */function drawNonMono(ctx,points,start,segLen,allLen,dir,smoothMin,smoothMax,smooth,smoothMonotone,connectNulls){var prevIdx=0;var idx=start;for(var k=0;k<segLen;k++){var p=points[idx];if(idx>=allLen||idx<0){break;}if(isPointNull(p)){if(connectNulls){idx+=dir;continue;}break;}if(idx===start){ctx[dir>0?'moveTo':'lineTo'](p[0],p[1]);v2Copy(cp0,p);}else{if(smooth>0){var nextIdx=idx+dir;var nextP=points[nextIdx];if(connectNulls){// Find next point not null\nwhile(nextP&&isPointNull(points[nextIdx])){nextIdx+=dir;nextP=points[nextIdx];}}var ratioNextSeg=0.5;var prevP=points[prevIdx];var nextP=points[nextIdx];// Last point\nif(!nextP||isPointNull(nextP)){v2Copy(cp1,p);}else{// If next data is null in not connect case\nif(isPointNull(nextP)&&!connectNulls){nextP=p;}sub(v,nextP,prevP);var lenPrevSeg;var lenNextSeg;if(smoothMonotone==='x'||smoothMonotone==='y'){var dim=smoothMonotone==='x'?0:1;lenPrevSeg=Math.abs(p[dim]-prevP[dim]);lenNextSeg=Math.abs(p[dim]-nextP[dim]);}else{lenPrevSeg=dist(p,prevP);lenNextSeg=dist(p,nextP);}// Use ratio of seg length\nratioNextSeg=lenNextSeg/(lenNextSeg+lenPrevSeg);scaleAndAdd$1(cp1,p,v,-smooth*(1-ratioNextSeg));}// Smooth constraint\nvec2Min(cp0,cp0,smoothMax);vec2Max(cp0,cp0,smoothMin);vec2Min(cp1,cp1,smoothMax);vec2Max(cp1,cp1,smoothMin);ctx.bezierCurveTo(cp0[0],cp0[1],cp1[0],cp1[1],p[0],p[1]);// cp0 of next segment\nscaleAndAdd$1(cp0,p,v,smooth*ratioNextSeg);}else{ctx.lineTo(p[0],p[1]);}}prevIdx=idx;idx+=dir;}return k;}function getBoundingBox(points,smoothConstraint){var ptMin=[Infinity,Infinity];var ptMax=[-Infinity,-Infinity];if(smoothConstraint){for(var i=0;i<points.length;i++){var pt=points[i];if(pt[0]<ptMin[0]){ptMin[0]=pt[0];}if(pt[1]<ptMin[1]){ptMin[1]=pt[1];}if(pt[0]>ptMax[0]){ptMax[0]=pt[0];}if(pt[1]>ptMax[1]){ptMax[1]=pt[1];}}}return{min:smoothConstraint?ptMin:ptMax,max:smoothConstraint?ptMax:ptMin};}var Polyline$1=Path.extend({type:'ec-polyline',shape:{points:[],smooth:0,smoothConstraint:true,smoothMonotone:null,connectNulls:false},style:{fill:null,stroke:'#000'},brush:fixClipWithShadow(Path.prototype.brush),buildPath:function buildPath(ctx,shape){var points=shape.points;var i=0;var len$$1=points.length;var result=getBoundingBox(points,shape.smoothConstraint);if(shape.connectNulls){// Must remove first and last null values avoid draw error in polygon\nfor(;len$$1>0;len$$1--){if(!isPointNull(points[len$$1-1])){break;}}for(;i<len$$1;i++){if(!isPointNull(points[i])){break;}}}while(i<len$$1){i+=drawSegment(ctx,points,i,len$$1,len$$1,1,result.min,result.max,shape.smooth,shape.smoothMonotone,shape.connectNulls)+1;}}});var Polygon$1=Path.extend({type:'ec-polygon',shape:{points:[],// Offset between stacked base points and points\nstackedOnPoints:[],smooth:0,stackedOnSmooth:0,smoothConstraint:true,smoothMonotone:null,connectNulls:false},brush:fixClipWithShadow(Path.prototype.brush),buildPath:function buildPath(ctx,shape){var points=shape.points;var stackedOnPoints=shape.stackedOnPoints;var i=0;var len$$1=points.length;var smoothMonotone=shape.smoothMonotone;var bbox=getBoundingBox(points,shape.smoothConstraint);var stackedOnBBox=getBoundingBox(stackedOnPoints,shape.smoothConstraint);if(shape.connectNulls){// Must remove first and last null values avoid draw error in polygon\nfor(;len$$1>0;len$$1--){if(!isPointNull(points[len$$1-1])){break;}}for(;i<len$$1;i++){if(!isPointNull(points[i])){break;}}}while(i<len$$1){var k=drawSegment(ctx,points,i,len$$1,len$$1,1,bbox.min,bbox.max,shape.smooth,smoothMonotone,shape.connectNulls);drawSegment(ctx,stackedOnPoints,i+k-1,k,len$$1,-1,stackedOnBBox.min,stackedOnBBox.max,shape.stackedOnSmooth,smoothMonotone,shape.connectNulls);i+=k+1;ctx.closePath();}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function createGridClipPath(cartesian,hasAnimation,seriesModel){var rect=cartesian.getArea();var isHorizontal=cartesian.getBaseAxis().isHorizontal();var x=rect.x;var y=rect.y;var width=rect.width;var height=rect.height;var lineWidth=seriesModel.get('lineStyle.width')||2;// Expand the clip path a bit to avoid the border is clipped and looks thinner\nx-=lineWidth/2;y-=lineWidth/2;width+=lineWidth;height+=lineWidth;// fix: https://github.com/apache/incubator-echarts/issues/11369\nx=Math.floor(x);width=Math.round(width);var clipPath=new Rect({shape:{x:x,y:y,width:width,height:height}});if(hasAnimation){clipPath.shape[isHorizontal?'width':'height']=0;initProps(clipPath,{shape:{width:width,height:height}},seriesModel);}return clipPath;}function createPolarClipPath(polar,hasAnimation,seriesModel){var sectorArea=polar.getArea();// Avoid float number rounding error for symbol on the edge of axis extent.\nvar clipPath=new Sector({shape:{cx:round$1(polar.cx,1),cy:round$1(polar.cy,1),r0:round$1(sectorArea.r0,1),r:round$1(sectorArea.r,1),startAngle:sectorArea.startAngle,endAngle:sectorArea.endAngle,clockwise:sectorArea.clockwise}});if(hasAnimation){clipPath.shape.endAngle=sectorArea.startAngle;initProps(clipPath,{shape:{endAngle:sectorArea.endAngle}},seriesModel);}return clipPath;}function createClipPath(coordSys,hasAnimation,seriesModel){if(!coordSys){return null;}else if(coordSys.type==='polar'){return createPolarClipPath(coordSys,hasAnimation,seriesModel);}else if(coordSys.type==='cartesian2d'){return createGridClipPath(coordSys,hasAnimation,seriesModel);}return null;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // FIXME step not support polar\nfunction isPointsSame(points1,points2){if(points1.length!==points2.length){return;}for(var i=0;i<points1.length;i++){var p1=points1[i];var p2=points2[i];if(p1[0]!==p2[0]||p1[1]!==p2[1]){return;}}return true;}function getBoundingDiff(points1,points2){var min1=[];var max1=[];var min2=[];var max2=[];fromPoints(points1,min1,max1);fromPoints(points2,min2,max2);// Get a max value from each corner of two boundings.\nreturn 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;}/**\n * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys\n * @param {module:echarts/data/List} data\n * @param {Object} dataCoordInfo\n * @param {Array.<Array.<number>>} points\n */function getStackedOnPoints(coordSys,data,dataCoordInfo){if(!dataCoordInfo.valueDim){return[];}var points=[];for(var idx=0,len=data.count();idx<len;idx++){points.push(getStackedOnPoint(dataCoordInfo,coordSys,data,idx));}return points;}function turnPointsIntoStep(points,coordSys,stepTurnAt){var baseAxis=coordSys.getBaseAxis();var baseIndex=baseAxis.dim==='x'||baseAxis.dim==='radius'?0:1;var stepPoints=[];for(var i=0;i<points.length-1;i++){var nextPt=points[i+1];var pt=points[i];stepPoints.push(pt);var stepPt=[];switch(stepTurnAt){case'end':stepPt[baseIndex]=nextPt[baseIndex];stepPt[1-baseIndex]=pt[1-baseIndex];// default is start\nstepPoints.push(stepPt);break;case'middle':// default is start\nvar 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);stepPoints.push(stepPt2);break;default:stepPt[baseIndex]=pt[baseIndex];stepPt[1-baseIndex]=nextPt[1-baseIndex];// default is start\nstepPoints.push(stepPt);}}// Last points\npoints[i]&&stepPoints.push(points[i]);return stepPoints;}function getVisualGradient(data,coordSys){var visualMetaList=data.getVisual('visualMeta');if(!visualMetaList||!visualMetaList.length||!data.count()){// When data.count() is 0, gradient range can not be calculated.\nreturn;}if(coordSys.type!=='cartesian2d'){if(__DEV__){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;// Can only be x or y\nif(coordDim==='x'||coordDim==='y'){visualMeta=visualMetaList[i];break;}}if(!visualMeta){if(__DEV__){console.warn('Visual map on line style only support x or y dimension.');}return;}// If the area to be rendered is bigger than area defined by LinearGradient,\n// the canvas spec prescribes that the color of the first stop and the last\n// stop should be used. But if two stops are added at offset 0, in effect\n// browsers use the color of the second stop to render area outside\n// LinearGradient. So we can only infinitesimally extend area defined in\n// LinearGradient to render `outerColors`.\nvar axis=coordSys.getAxis(coordDim);// dataToCoor mapping may not be linear, but must be monotonic.\nvar colorStops=map(visualMeta.stops,function(stop){return{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;// Arbitrary value: 10px\nvar minCoord=colorStops[0].coord-tinyExtent;var maxCoord=colorStops[stopLen-1].coord+tinyExtent;var coordSpan=maxCoord-minCoord;if(coordSpan<1e-3){return'transparent';}each$1(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({// notice colorStops.length have been changed.\noffset:stopLen?colorStops[0].offset:0.5,color:outerColors[0]||'transparent'});// zrUtil.each(colorStops, function (colorStop) {\n//     // Make sure each offset has rounded px to avoid not sharp edge\n//     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);\n// });\nvar 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;}// Note that category label interval strategy might bring some weird effect\n// in some scenario: users may wonder why some of the symbols are not\n// displayed. So we show all symbols as possible as we can.\nif(isAuto// Simplify the logic, do not determine label overlap here.\n&&canShowAllSymbolForCategory(categoryAxis,data)){return;}// Otherwise follow the label interval strategy on category axis.\nvar categoryDataDim=data.mapDimension(categoryAxis.dim);var labelMap={};each$1(categoryAxis.getViewLabels(),function(labelItem){labelMap[labelItem.tickValue]=1;});return function(dataIndex){return!labelMap.hasOwnProperty(data.get(categoryDataDim,dataIndex));};}function canShowAllSymbolForCategory(categoryAxis,data){// In mose cases, line is monotonous on category axis, and the label size\n// is close with each other. So we check the symbol size and some of the\n// label size alone with the category axis to estimate whether all symbol\n// can be shown without overlap.\nvar axisExtent=categoryAxis.getExtent();var availSize=Math.abs(axisExtent[1]-axisExtent[0])/categoryAxis.scale.count();isNaN(availSize)&&(availSize=0);// 0/0 is NaN.\n// Sampling some points, max 5.\nvar dataLen=data.count();var step=Math.max(1,Math.round(dataLen/5));for(var dataIndex=0;dataIndex<dataLen;dataIndex+=step){if(SymbolClz$1.getSymbolSize(data,dataIndex// Only for cartesian, where `isHorizontal` exists.\n)[categoryAxis.isHorizontal()?1:0]// Empirical number\n*1.5>availSize){return false;}}return true;}function createLineClipPath(coordSys,hasAnimation,seriesModel){if(coordSys.type==='cartesian2d'){var isHorizontal=coordSys.getBaseAxis().isHorizontal();var clipPath=createGridClipPath(coordSys,hasAnimation,seriesModel);// Expand clip shape to avoid clipping when line value exceeds axis\nif(!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;}}return clipPath;}else{return createPolarClipPath(coordSys,hasAnimation,seriesModel);}}Chart.extend({type:'line',init:function init(){var lineGroup=new Group();var symbolDraw=new SymbolDraw();this.group.add(symbolDraw.group);this._symbolDraw=symbolDraw;this._lineGroup=lineGroup;},render:function render(seriesModel,ecModel,api){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.mapArray(data.getItemLayout);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=getStackedOnPoints(coordSys,data,dataCoordInfo);var showSymbol=seriesModel.get('showSymbol');var isIgnoreFunc=showSymbol&&!isCoordSysPolar&&getIsIgnoreFunc(seriesModel,data,coordSys);// Remove temporary symbols\nvar oldData=this._data;oldData&&oldData.eachItemGraphicEl(function(el,idx){if(el.__temp){group.remove(el);oldData.setItemGraphicEl(idx,null);}});// Remove previous created symbols if showSymbol changed to false\nif(!showSymbol){symbolDraw.remove();}group.add(lineGroup);// FIXME step not support polar\nvar step=!isCoordSysPolar&&seriesModel.get('step');var clipShapeForSymbol;if(coordSys&&coordSys.getArea&&seriesModel.get('clip',true)){clipShapeForSymbol=coordSys.getArea();// Avoid float number rounding error for symbol on the edge of axis extent.\n// See #7913 and `test/dataZoom-clip.html`.\nif(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.r1+=0.5;}}this._clipShapeForSymbol=clipShapeForSymbol;// Initialization animation or coordinate system changed\nif(!(polyline&&prevCoordSys.type===coordSys.type&&step===this._step)){showSymbol&&symbolDraw.updateData(data,{isIgnore:isIgnoreFunc,clipShape:clipShapeForSymbol});if(step){// TODO If stacked series is not step\npoints=turnPointsIntoStep(points,coordSys,step);stackedOnPoints=turnPointsIntoStep(stackedOnPoints,coordSys,step);}polyline=this._newPolyline(points,coordSys,hasAnimation);if(isAreaChart){polygon=this._newPolygon(points,stackedOnPoints,coordSys,hasAnimation);}lineGroup.setClipPath(createLineClipPath(coordSys,true,seriesModel));}else{if(isAreaChart&&!polygon){// If areaStyle is added\npolygon=this._newPolygon(points,stackedOnPoints,coordSys,hasAnimation);}else if(polygon&&!isAreaChart){// If areaStyle is removed\nlineGroup.remove(polygon);polygon=this._polygon=null;}// Update clipPath\nlineGroup.setClipPath(createLineClipPath(coordSys,false,seriesModel));// Always update, or it is wrong in the case turning on legend\n// because points are not changed\nshowSymbol&&symbolDraw.updateData(data,{isIgnore:isIgnoreFunc,clipShape:clipShapeForSymbol});// Stop symbol animation and sync with line points\n// FIXME performance?\ndata.eachItemGraphicEl(function(el){el.stopAnimation(true);});// In the case data zoom triggerred refreshing frequently\n// Data may not change if line has a category axis. So it should animate nothing\nif(!isPointsSame(this._stackedOnPoints,stackedOnPoints)||!isPointsSame(this._points,points)){if(hasAnimation){this._updateAnimation(data,stackedOnPoints,coordSys,api,step,valueOrigin);}else{// Not do it in update with animation\nif(step){// TODO If stacked series is not step\npoints=turnPointsIntoStep(points,coordSys,step);stackedOnPoints=turnPointsIntoStep(stackedOnPoints,coordSys,step);}polyline.setShape({points:points});polygon&&polygon.setShape({points:points,stackedOnPoints:stackedOnPoints});}}}var visualColor=getVisualGradient(data,coordSys)||data.getVisual('color');polyline.useStyle(defaults(// Use color in lineStyle first\nlineStyleModel.getLineStyle(),{fill:'none',stroke:visualColor,lineJoin:'bevel'}));var smooth=seriesModel.get('smooth');smooth=getSmooth(seriesModel.get('smooth'));polyline.setShape({smooth:smooth,smoothMonotone:seriesModel.get('smoothMonotone'),connectNulls:seriesModel.get('connectNulls')});if(polygon){var stackedOnSeries=data.getCalculationInfo('stackedOnSeries');var stackedOnSmooth=0;polygon.useStyle(defaults(areaStyleModel.getAreaStyle(),{fill:visualColor,opacity:0.7,lineJoin:'bevel'}));if(stackedOnSeries){stackedOnSmooth=getSmooth(stackedOnSeries.get('smooth'));}polygon.setShape({smooth:smooth,stackedOnSmooth:stackedOnSmooth,smoothMonotone:seriesModel.get('smoothMonotone'),connectNulls:seriesModel.get('connectNulls')});}this._data=data;// Save the coordinate system for transition animation when data changed\nthis._coordSys=coordSys;this._stackedOnPoints=stackedOnPoints;this._points=points;this._step=step;this._valueOrigin=valueOrigin;},dispose:function dispose(){},highlight:function highlight(seriesModel,ecModel,api,payload){var data=seriesModel.getData();var dataIndex=queryDataIndex(data,payload);if(!(dataIndex instanceof Array)&&dataIndex!=null&&dataIndex>=0){var symbol=data.getItemGraphicEl(dataIndex);if(!symbol){// Create a temporary symbol if it is not exists\nvar pt=data.getItemLayout(dataIndex);if(!pt){// Null data\nreturn;}// fix #11360: should't draw symbol outside clipShapeForSymbol\nif(this._clipShapeForSymbol&&!this._clipShapeForSymbol.contain(pt[0],pt[1])){return;}symbol=new SymbolClz$1(data,dataIndex);symbol.position=pt;symbol.setZ(seriesModel.get('zlevel'),seriesModel.get('z'));symbol.ignore=isNaN(pt[0])||isNaN(pt[1]);symbol.__temp=true;data.setItemGraphicEl(dataIndex,symbol);// Stop scale animation\nsymbol.stopSymbolAnimation(true);this.group.add(symbol);}symbol.highlight();}else{// Highlight whole series\nChart.prototype.highlight.call(this,seriesModel,ecModel,api,payload);}},downplay:function downplay(seriesModel,ecModel,api,payload){var data=seriesModel.getData();var dataIndex=queryDataIndex(data,payload);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{// FIXME\n// can not downplay completely.\n// Downplay whole series\nChart.prototype.downplay.call(this,seriesModel,ecModel,api,payload);}},/**\n     * @param {module:zrender/container/Group} group\n     * @param {Array.<Array.<number>>} points\n     * @private\n     */_newPolyline:function _newPolyline(points){var polyline=this._polyline;// Remove previous created polyline\nif(polyline){this._lineGroup.remove(polyline);}polyline=new Polyline$1({shape:{points:points},silent:true,z2:10});this._lineGroup.add(polyline);this._polyline=polyline;return polyline;},/**\n     * @param {module:zrender/container/Group} group\n     * @param {Array.<Array.<number>>} stackedOnPoints\n     * @param {Array.<Array.<number>>} points\n     * @private\n     */_newPolygon:function _newPolygon(points,stackedOnPoints){var polygon=this._polygon;// Remove previous created polygon\nif(polygon){this._lineGroup.remove(polygon);}polygon=new Polygon$1({shape:{points:points,stackedOnPoints:stackedOnPoints},silent:true});this._lineGroup.add(polygon);this._polygon=polygon;return polygon;},/**\n     * @private\n     */ // FIXME Two value axis\n_updateAnimation:function _updateAnimation(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){// TODO If stacked series is not step\ncurrent=turnPointsIntoStep(diff.current,coordSys,step);stackedOnCurrent=turnPointsIntoStep(diff.stackedOnCurrent,coordSys,step);next=turnPointsIntoStep(diff.next,coordSys,step);stackedOnNext=turnPointsIntoStep(diff.stackedOnNext,coordSys,step);}// Don't apply animation if diff is large.\n// For better result and avoid memory explosion problems like\n// https://github.com/apache/incubator-echarts/issues/12229\nif(getBoundingDiff(current,next)>3000||polygon&&getBoundingDiff(stackedOnCurrent,stackedOnNext)>3000){polyline.setShape({points:next});if(polygon){polygon.setShape({points:next,stackedOnPoints:stackedOnNext});}return;}// `diff.current` is subset of `current` (which should be ensured by\n// turnPointsIntoStep), so points in `__points` can be updated when\n// points in `current` are update during animation.\npolyline.shape.__points=diff.current;polyline.shape.points=current;updateProps(polyline,{shape:{points:next}},seriesModel);if(polygon){polygon.setShape({points:current,stackedOnPoints:stackedOnCurrent});updateProps(polygon,{shape:{points:next,stackedOnPoints:stackedOnNext}},seriesModel);}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// Index of points\n});}}}if(polyline.animators&&polyline.animators.length){polyline.animators[0].during(function(){for(var i=0;i<updatedDataInfo.length;i++){var el=updatedDataInfo[i].el;el.attr('position',polyline.shape.__points[updatedDataInfo[i].ptIdx]);}});}},remove:function remove(ecModel){var group=this.group;var oldData=this._data;this._lineGroup.removeAll();this._symbolDraw.remove(true);// Remove temporary created elements when highlighting\noldData&&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._data=null;}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var visualSymbol=function visualSymbol(seriesType,defaultSymbolType,legendSymbol){// Encoding visual for all series include which is filtered for legend drawing\nreturn{seriesType:seriesType,// For legend.\nperformRawSeries:true,reset:function reset(seriesModel,ecModel,api){var data=seriesModel.getData();var symbolType=seriesModel.get('symbol');var symbolSize=seriesModel.get('symbolSize');var keepAspect=seriesModel.get('symbolKeepAspect');var symbolRotate=seriesModel.get('symbolRotate');var hasSymbolTypeCallback=isFunction$1(symbolType);var hasSymbolSizeCallback=isFunction$1(symbolSize);var hasSymbolRotateCallback=isFunction$1(symbolRotate);var hasCallback=hasSymbolTypeCallback||hasSymbolSizeCallback||hasSymbolRotateCallback;var seriesSymbol=!hasSymbolTypeCallback&&symbolType?symbolType:defaultSymbolType;var seriesSymbolSize=!hasSymbolSizeCallback?symbolSize:null;data.setVisual({legendSymbol:legendSymbol||seriesSymbol,// If seting callback functions on `symbol` or `symbolSize`, for simplicity and avoiding\n// to bring trouble, we do not pick a reuslt from one of its calling on data item here,\n// but just use the default value. Callback on `symbol` or `symbolSize` is convenient in\n// some cases but generally it is not recommanded.\nsymbol:seriesSymbol,symbolSize:seriesSymbolSize,symbolKeepAspect:keepAspect,symbolRotate:symbolRotate});// Only visible series has each data be visual encoded\nif(ecModel.isSeriesFiltered(seriesModel)){return;}function dataEach(data,idx){if(hasCallback){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));}if(data.hasItemOption){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 has item symbol\nif(itemSymbolType!=null){data.setItemVisual(idx,'symbol',itemSymbolType);}if(itemSymbolSize!=null){// PENDING Transform symbolSize ?\ndata.setItemVisual(idx,'symbolSize',itemSymbolSize);}if(itemSymbolRotate!=null){data.setItemVisual(idx,'symbolRotate',itemSymbolRotate);}if(itemSymbolKeepAspect!=null){data.setItemVisual(idx,'symbolKeepAspect',itemSymbolKeepAspect);}}}return{dataEach:data.hasItemOption||hasCallback?dataEach:null};}};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /* global Float32Array */var pointsLayout=function pointsLayout(seriesType){return{seriesType:seriesType,plan:createRenderPlanner(),reset:function reset(seriesModel){var data=seriesModel.getData();var coordSys=seriesModel.coordinateSystem;var pipelineContext=seriesModel.pipelineContext;var isLargeRender=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[1]*/)){dims[0]=stackResultDim;}if(isDimensionStacked(data,dims[1]/*, dims[0]*/)){dims[1]=stackResultDim;}function progress(params,data){var segCount=params.end-params.start;var points=isLargeRender&&new Float32Array(segCount*dimLen);for(var i=params.start,offset=0,tmpIn=[],tmpOut=[];i<params.end;i++){var point;if(dimLen===1){var x=data.get(dims[0],i);point=!isNaN(x)&&coordSys.dataToPoint(x,null,tmpOut);}else{var x=tmpIn[0]=data.get(dims[0],i);var y=tmpIn[1]=data.get(dims[1],i);// Also {Array.<number>}, not undefined to avoid if...else... statement\npoint=!isNaN(x)&&!isNaN(y)&&coordSys.dataToPoint(tmpIn,null,tmpOut);}if(isLargeRender){points[offset++]=point?point[0]:NaN;points[offset++]=point?point[1]:NaN;}else{data.setItemLayout(i,point&&point.slice()||[NaN,NaN]);}}isLargeRender&&data.setLayout('symbolPoints',points);}return dimLen&&{progress:progress};}};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var samplers={average:function average(frame){var sum=0;var count=0;for(var i=0;i<frame.length;i++){if(!isNaN(frame[i])){sum+=frame[i];count++;}}// Return NaN if count is 0\nreturn count===0?NaN:sum/count;},sum:function sum(frame){var sum=0;for(var i=0;i<frame.length;i++){// Ignore NaN\nsum+=frame[i]||0;}return sum;},max:function max(frame){var max=-Infinity;for(var i=0;i<frame.length;i++){frame[i]>max&&(max=frame[i]);}// NaN will cause illegal axis extent.\nreturn isFinite(max)?max:NaN;},min:function min(frame){var min=Infinity;for(var i=0;i<frame.length;i++){frame[i]<min&&(min=frame[i]);}// NaN will cause illegal axis extent.\nreturn isFinite(min)?min:NaN;},// TODO\n// Median\nnearest:function nearest(frame){return frame[0];}};var indexSampler=function indexSampler(frame,value){return Math.round(frame.length/2);};var dataSample=function dataSample(seriesType){return{seriesType:seriesType,modifyOutputEnd:true,reset:function reset(seriesModel,ecModel,api){var data=seriesModel.getData();var sampling=seriesModel.get('sampling');var coordSys=seriesModel.coordinateSystem;// Only cartesian2d support down sampling\nif(coordSys.type==='cartesian2d'&&sampling){var baseAxis=coordSys.getBaseAxis();var valueAxis=coordSys.getOtherAxis(baseAxis);var extent=baseAxis.getExtent();// Coordinste system has been resized\nvar size=Math.abs(extent[1]-extent[0]);var rate=Math.round(data.count()/size);if(rate>1){var sampler;if(typeof sampling==='string'){sampler=samplers[sampling];}else if(typeof sampling==='function'){sampler=sampling;}if(sampler){// Only support sample the first dim mapped from value axis.\nseriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim),1/rate,sampler,indexSampler));}}}}};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Cartesian coordinate system\n * @module  echarts/coord/Cartesian\n *\n */function dimAxisMapper(dim){return this._axes[dim];}/**\n * @alias module:echarts/coord/Cartesian\n * @constructor\n */var Cartesian=function Cartesian(name){this._axes={};this._dimList=[];/**\n     * @type {string}\n     */this.name=name||'';};Cartesian.prototype={constructor:Cartesian,type:'cartesian',/**\n     * Get axis\n     * @param  {number|string} dim\n     * @return {module:echarts/coord/Cartesian~Axis}\n     */getAxis:function getAxis(dim){return this._axes[dim];},/**\n     * Get axes list\n     * @return {Array.<module:echarts/coord/Cartesian~Axis>}\n     */getAxes:function getAxes(){return map(this._dimList,dimAxisMapper,this);},/**\n     * Get axes list by given scale type\n     */getAxesByScale:function getAxesByScale(scaleType){scaleType=scaleType.toLowerCase();return filter(this.getAxes(),function(axis){return axis.scale.type===scaleType;});},/**\n     * Add axis\n     * @param {module:echarts/coord/Cartesian.Axis}\n     */addAxis:function addAxis(axis){var dim=axis.dim;this._axes[dim]=axis;this._dimList.push(dim);},/**\n     * Convert data to coord in nd space\n     * @param {Array.<number>|Object.<string, number>} val\n     * @return {Array.<number>|Object.<string, number>}\n     */dataToCoord:function dataToCoord(val){return this._dataCoordConvert(val,'dataToCoord');},/**\n     * Convert coord in nd space to data\n     * @param  {Array.<number>|Object.<string, number>} val\n     * @return {Array.<number>|Object.<string, number>}\n     */coordToData:function coordToData(val){return this._dataCoordConvert(val,'coordToData');},_dataCoordConvert:function _dataCoordConvert(input,method){var dimList=this._dimList;var output=input instanceof Array?[]:{};for(var i=0;i<dimList.length;i++){var dim=dimList[i];var axis=this._axes[dim];output[dim]=axis[method](input[dim]);}return output;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function Cartesian2D(name){Cartesian.call(this,name);}Cartesian2D.prototype={constructor:Cartesian2D,type:'cartesian2d',/**\n     * @type {Array.<string>}\n     * @readOnly\n     */dimensions:['x','y'],/**\n     * Base axis will be used on stacking.\n     *\n     * @return {module:echarts/coord/cartesian/Axis2D}\n     */getBaseAxis:function getBaseAxis(){return this.getAxesByScale('ordinal')[0]||this.getAxesByScale('time')[0]||this.getAxis('x');},/**\n     * If contain point\n     * @param {Array.<number>} point\n     * @return {boolean}\n     */containPoint:function containPoint(point){var axisX=this.getAxis('x');var axisY=this.getAxis('y');return axisX.contain(axisX.toLocalCoord(point[0]))&&axisY.contain(axisY.toLocalCoord(point[1]));},/**\n     * If contain data\n     * @param {Array.<number>} data\n     * @return {boolean}\n     */containData:function containData(data){return this.getAxis('x').containData(data[0])&&this.getAxis('y').containData(data[1]);},/**\n     * @param {Array.<number>} data\n     * @param {Array.<number>} out\n     * @return {Array.<number>}\n     */dataToPoint:function dataToPoint(data,reserved,out){var xAxis=this.getAxis('x');var yAxis=this.getAxis('y');out=out||[];out[0]=xAxis.toGlobalCoord(xAxis.dataToCoord(data[0]));out[1]=yAxis.toGlobalCoord(yAxis.dataToCoord(data[1]));return out;},/**\n     * @param {Array.<number>} data\n     * @param {Array.<number>} out\n     * @return {Array.<number>}\n     */clampData:function clampData(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;},/**\n     * @param {Array.<number>} point\n     * @param {Array.<number>} out\n     * @return {Array.<number>}\n     */pointToData:function pointToData(point,out){var xAxis=this.getAxis('x');var yAxis=this.getAxis('y');out=out||[];out[0]=xAxis.coordToData(xAxis.toLocalCoord(point[0]));out[1]=yAxis.coordToData(yAxis.toLocalCoord(point[1]));return out;},/**\n     * Get other axis\n     * @param {module:echarts/coord/cartesian/Axis2D} axis\n     */getOtherAxis:function getOtherAxis(axis){return this.getAxis(axis.dim==='x'?'y':'x');},/**\n     * Get rect area of cartesian.\n     * Area will have a contain function to determine if a point is in the coordinate system.\n     * @return {BoundingRect}\n     */getArea:function getArea(){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;var rect=new BoundingRect(x,y,width,height);return rect;}};inherits(Cartesian2D,Cartesian);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Extend axis 2d\n * @constructor module:echarts/coord/cartesian/Axis2D\n * @extends {module:echarts/coord/cartesian/Axis}\n * @param {string} dim\n * @param {*} scale\n * @param {Array.<number>} coordExtent\n * @param {string} axisType\n * @param {string} position\n */var Axis2D=function Axis2D(dim,scale,coordExtent,axisType,position){Axis.call(this,dim,scale,coordExtent);/**\n     * Axis type\n     *  - 'category'\n     *  - 'value'\n     *  - 'time'\n     *  - 'log'\n     * @type {string}\n     */this.type=axisType||'value';/**\n     * Axis position\n     *  - 'top'\n     *  - 'bottom'\n     *  - 'left'\n     *  - 'right'\n     */this.position=position||'bottom';};Axis2D.prototype={constructor:Axis2D,/**\n     * Index of axis, can be used as key\n     */index:0,/**\n     * Implemented in <module:echarts/coord/cartesian/Grid>.\n     * @return {Array.<module:echarts/coord/cartesian/Axis2D>}\n     *         If not on zero of other axis, return null/undefined.\n     *         If no axes, return an empty array.\n     */getAxesOnZeroOf:null,/**\n     * Axis model\n     * @param {module:echarts/coord/cartesian/AxisModel}\n     */model:null,isHorizontal:function isHorizontal(){var position=this.position;return position==='top'||position==='bottom';},/**\n     * Each item cooresponds to this.getExtent(), which\n     * means globalExtent[0] may greater than globalExtent[1],\n     * unless `asc` is input.\n     *\n     * @param {boolean} [asc]\n     * @return {Array.<number>}\n     */getGlobalExtent:function getGlobalExtent(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;},getOtherAxis:function getOtherAxis(){this.grid.getOtherAxis();},/**\n     * @override\n     */pointToData:function pointToData(point,clamp){return this.coordToData(this.toLocalCoord(point[this.dim==='x'?0:1]),clamp);},/**\n     * Transform global coord to local coord,\n     * i.e. var localCoord = axis.toLocalCoord(80);\n     * designate by module:echarts/coord/cartesian/Grid.\n     * @type {Function}\n     */toLocalCoord:null,/**\n     * Transform global coord to local coord,\n     * i.e. var globalCoord = axis.toLocalCoord(40);\n     * designate by module:echarts/coord/cartesian/Grid.\n     * @type {Function}\n     */toGlobalCoord:null};inherits(Axis2D,Axis);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var defaultOption={show:true,zlevel:0,z:0,// Inverse the axis.\ninverse:false,// Axis name displayed.\nname:'',// 'start' | 'middle' | 'end'\nnameLocation:'end',// By degree. By default auto rotate by nameLocation.\nnameRotate:null,nameTruncate:{maxWidth:null,ellipsis:'...',placeholder:'.'},// Use global text style by default.\nnameTextStyle:{},// The gap between axisName and axisLine.\nnameGap:15,// Default `false` to support tooltip.\nsilent:false,// Default `false` to avoid legacy user event listener fail.\ntriggerEvent:false,tooltip:{show:false},axisPointer:{},axisLine:{show:true,onZero:true,onZeroAxisIndex:null,lineStyle:{color:'#333',width:1,type:'solid'},// The arrow at both ends the the axis.\nsymbol:['none','none'],symbolSize:[10,15]},axisTick:{show:true,// Whether axisTick is inside the grid or outside the grid.\ninside:false,// The length of axisTick.\nlength:5,lineStyle:{width:1}},axisLabel:{show:true,// Whether axisLabel is inside the grid or outside the grid.\ninside:false,rotate:0,// true | false | null/undefined (auto)\nshowMinLabel:null,// true | false | null/undefined (auto)\nshowMaxLabel:null,margin:8,// formatter: null,\nfontSize:12},splitLine:{show:true,lineStyle:{color:['#ccc'],width:1,type:'solid'}},splitArea:{show:false,areaStyle:{color:['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)']}}};var axisDefault={};axisDefault.categoryAxis=merge({// The gap at both ends of the axis. For categoryAxis, boolean.\nboundaryGap:true,// Set false to faster category collection.\n// Only usefull in the case like: category is\n// ['2012-01-01', '2012-01-02', ...], where the input\n// data has been ensured not duplicate and is large data.\n// null means \"auto\":\n// if axis.data provided, do not deduplication,\n// else do deduplication.\ndeduplication:null,// splitArea: {\n// show: false\n// },\nsplitLine:{show:false},axisTick:{// If tick is align with label when boundaryGap is true\nalignWithLabel:false,interval:'auto'},axisLabel:{interval:'auto'}},defaultOption);axisDefault.valueAxis=merge({// The gap at both ends of the axis. For value axis, [GAP, GAP], where\n// `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`)\nboundaryGap:[0,0],// TODO\n// min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60]\n// Min value of the axis. can be:\n// + a number\n// + 'dataMin': use the min value in data.\n// + null/undefined: auto decide min value (consider pretty look and boundaryGap).\n// min: null,\n// Max value of the axis. can be:\n// + a number\n// + 'dataMax': use the max value in data.\n// + null/undefined: auto decide max value (consider pretty look and boundaryGap).\n// max: null,\n// Readonly prop, specifies start value of the range when using data zoom.\n// rangeStart: null\n// Readonly prop, specifies end value of the range when using data zoom.\n// rangeEnd: null\n// Optional value can be:\n// + `false`: always include value 0.\n// + `true`: the extent do not consider value 0.\n// scale: false,\n// AxisTick and axisLabel and splitLine are caculated based on splitNumber.\nsplitNumber:5,// Interval specifies the span of the ticks is mandatorily.\n// interval: null\n// Specify min interval when auto calculate tick interval.\n// minInterval: null\n// Specify max interval when auto calculate tick interval.\n// maxInterval: null\nminorTick:{// Minor tick, not available for cateogry axis.\nshow:false,// Split number of minor ticks. The value should be in range of (0, 100)\nsplitNumber:5,// Lenght of minor tick\nlength:3,// Same inside with axisTick\n// Line style\nlineStyle:{// Default to be same with axisTick\n}},minorSplitLine:{show:false,lineStyle:{color:'#eee',width:1}}},defaultOption);axisDefault.timeAxis=defaults({scale:true,min:'dataMin',max:'dataMax'},axisDefault.valueAxis);axisDefault.logAxis=defaults({scale:true,logBase:10},axisDefault.valueAxis);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // FIXME axisType is fixed ?\nvar AXIS_TYPES=['value','category','time','log'];/**\n * Generate sub axis model class\n * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel'\n * @param {module:echarts/model/Component} BaseAxisModelClass\n * @param {Function} axisTypeDefaulter\n * @param {Object} [extraDefaultOption]\n */var axisModelCreator=function axisModelCreator(axisName,BaseAxisModelClass,axisTypeDefaulter,extraDefaultOption){each$1(AXIS_TYPES,function(axisType){BaseAxisModelClass.extend({/**\n             * @readOnly\n             */type:axisName+'Axis.'+axisType,mergeDefaultAndTheme:function mergeDefaultAndTheme(option,ecModel){var layoutMode=this.layoutMode;var inputPositionParams=layoutMode?getLayoutParams(option):{};var themeModel=ecModel.getTheme();merge(option,themeModel.get(axisType+'Axis'));merge(option,this.getDefaultOption());option.type=axisTypeDefaulter(axisName,option);if(layoutMode){mergeLayoutParam(option,inputPositionParams,layoutMode);}},/**\n             * @override\n             */optionUpdated:function optionUpdated(){var thisOption=this.option;if(thisOption.type==='category'){this.__ordinalMeta=OrdinalMeta.createByAxisModel(this);}},/**\n             * Should not be called before all of 'getInitailData' finished.\n             * Because categories are collected during initializing data.\n             */getCategories:function getCategories(rawData){var option=this.option;// FIXME\n// warning if called before all of 'getInitailData' finished.\nif(option.type==='category'){if(rawData){return option.data;}return this.__ordinalMeta.categories;}},getOrdinalMeta:function getOrdinalMeta(){return this.__ordinalMeta;},defaultOption:mergeAll([{},axisDefault[axisType+'Axis'],extraDefaultOption],true)});});ComponentModel.registerSubTypeDefaulter(axisName+'Axis',curry(axisTypeDefaulter,axisName));};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var AxisModel=ComponentModel.extend({type:'cartesian2dAxis',/**\n     * @type {module:echarts/coord/cartesian/Axis2D}\n     */axis:null,/**\n     * @override\n     */init:function init(){AxisModel.superApply(this,'init',arguments);this.resetRange();},/**\n     * @override\n     */mergeOption:function mergeOption(){AxisModel.superApply(this,'mergeOption',arguments);this.resetRange();},/**\n     * @override\n     */restoreData:function restoreData(){AxisModel.superApply(this,'restoreData',arguments);this.resetRange();},/**\n     * @override\n     * @return {module:echarts/model/Component}\n     */getCoordSysModel:function getCoordSysModel(){return this.ecModel.queryComponents({mainType:'grid',index:this.option.gridIndex,id:this.option.gridId})[0];}});function getAxisType(axisDim,option){// Default axis with data is category axis\nreturn option.type||(option.data?'category':'value');}merge(AxisModel.prototype,axisModelCommonMixin);var extraOption={// gridIndex: 0,\n// gridId: '',\n// Offset is for multiple axis on the same position\noffset:0};axisModelCreator('x',AxisModel,getAxisType,extraOption);axisModelCreator('y',AxisModel,getAxisType,extraOption);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Grid 是在有直角坐标系的时候必须要存在的\n// 所以这里也要被 Cartesian2D 依赖\nComponentModel.extend({type:'grid',dependencies:['xAxis','yAxis'],layoutMode:'box',/**\n     * @type {module:echarts/coord/cartesian/Grid}\n     */coordinateSystem:null,defaultOption:{show:false,zlevel:0,z:0,left:'10%',top:60,right:'10%',bottom:60,// If grid size contain label\ncontainLabel:false,// width: {totalWidth} - left - right,\n// height: {totalHeight} - top - bottom,\nbackgroundColor:'rgba(0,0,0,0)',borderWidth:1,borderColor:'#ccc'}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Grid is a region which contains at most 4 cartesian systems\n *\n * TODO Default cartesian\n */ // Depends on GridModel, AxisModel, which performs preprocess.\n/**\n * Check if the axis is used in the specified grid\n * @inner\n */function isAxisUsedInTheGrid(axisModel,gridModel,ecModel){return axisModel.getCoordSysModel()===gridModel;}function Grid(gridModel,ecModel,api){/**\n     * @type {Object.<string, module:echarts/coord/cartesian/Cartesian2D>}\n     * @private\n     */this._coordsMap={};/**\n     * @type {Array.<module:echarts/coord/cartesian/Cartesian>}\n     * @private\n     */this._coordsList=[];/**\n     * @type {Object.<string, Array.<module:echarts/coord/cartesian/Axis2D>>}\n     * @private\n     */this._axesMap={};/**\n     * @type {Array.<module:echarts/coord/cartesian/Axis2D>}\n     * @private\n     */this._axesList=[];this._initCartesian(gridModel,ecModel,api);this.model=gridModel;}var gridProto=Grid.prototype;gridProto.type='grid';gridProto.axisPointerEnabled=true;gridProto.getRect=function(){return this._rect;};gridProto.update=function(ecModel,api){var axesMap=this._axesMap;this._updateScale(ecModel,this.model);each$1(axesMap.x,function(xAxis){niceScaleExtent(xAxis.scale,xAxis.model);});each$1(axesMap.y,function(yAxis){niceScaleExtent(yAxis.scale,yAxis.model);});// Key: axisDim_axisIndex, value: boolean, whether onZero target.\nvar onZeroRecords={};each$1(axesMap.x,function(xAxis){fixAxisOnZero(axesMap,'y',xAxis,onZeroRecords);});each$1(axesMap.y,function(yAxis){fixAxisOnZero(axesMap,'x',yAxis,onZeroRecords);});// Resize again if containLabel is enabled\n// FIXME It may cause getting wrong grid size in data processing stage\nthis.resize(this.model,api);};function fixAxisOnZero(axesMap,otherAxisDim,axis,onZeroRecords){axis.getAxesOnZeroOf=function(){// TODO: onZero of multiple axes.\nreturn otherAxisOnZeroOf?[otherAxisOnZeroOf]:[];};// onZero can not be enabled in these two situations:\n// 1. When any other axis is a category axis.\n// 2. When no axis is cross 0 point.\nvar 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 target axis is specified.\nif(onZeroAxisIndex!=null){if(canOnZeroToAxis(otherAxes[onZeroAxisIndex])){otherAxisOnZeroOf=otherAxes[onZeroAxisIndex];}}else{// Find the first available other axis.\nfor(var idx in otherAxes){if(otherAxes.hasOwnProperty(idx)&&canOnZeroToAxis(otherAxes[idx])// Consider that two Y axes on one value axis,\n// if both onZero, the two Y axes overlap.\n&&!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);}/**\n * Resize the grid\n * @param {module:echarts/coord/cartesian/GridModel} gridModel\n * @param {module:echarts/ExtensionAPI} api\n */gridProto.resize=function(gridModel,api,ignoreContainLabel){var gridRect=getLayoutRect(gridModel.getBoxLayoutParams(),{width:api.getWidth(),height:api.getHeight()});this._rect=gridRect;var axesList=this._axesList;adjustAxes();// Minus label size\nif(!ignoreContainLabel&&gridModel.get('containLabel')){each$1(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();}function adjustAxes(){each$1(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);});}};/**\n * @param {string} axisType\n * @param {number} [axisIndex]\n */gridProto.getAxis=function(axisType,axisIndex){var axesMapOnDim=this._axesMap[axisType];if(axesMapOnDim!=null){if(axisIndex==null){// Find first axis\nfor(var name in axesMapOnDim){if(axesMapOnDim.hasOwnProperty(name)){return axesMapOnDim[name];}}}return axesMapOnDim[axisIndex];}};/**\n * @return {Array.<module:echarts/coord/Axis>}\n */gridProto.getAxes=function(){return this._axesList.slice();};/**\n * Usage:\n *      grid.getCartesian(xAxisIndex, yAxisIndex);\n *      grid.getCartesian(xAxisIndex);\n *      grid.getCartesian(null, yAxisIndex);\n *      grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...});\n *\n * @param {number|Object} [xAxisIndex]\n * @param {number} [yAxisIndex]\n */gridProto.getCartesian=function(xAxisIndex,yAxisIndex){if(xAxisIndex!=null&&yAxisIndex!=null){var key='x'+xAxisIndex+'y'+yAxisIndex;return this._coordsMap[key];}if(isObject$1(xAxisIndex)){yAxisIndex=xAxisIndex.yAxisIndex;xAxisIndex=xAxisIndex.xAxisIndex;}// When only xAxisIndex or yAxisIndex given, find its first cartesian.\nfor(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];}}};gridProto.getCartesians=function(){return this._coordsList.slice();};/**\n * @implements\n * see {module:echarts/CoodinateSystem}\n */gridProto.convertToPixel=function(ecModel,finder,value){var target=this._findConvertTarget(ecModel,finder);return target.cartesian?target.cartesian.dataToPoint(value):target.axis?target.axis.toGlobalCoord(target.axis.dataToCoord(value)):null;};/**\n * @implements\n * see {module:echarts/CoodinateSystem}\n */gridProto.convertFromPixel=function(ecModel,finder,value){var target=this._findConvertTarget(ecModel,finder);return target.cartesian?target.cartesian.pointToData(value):target.axis?target.axis.coordToData(target.axis.toLocalCoord(value)):null;};/**\n * @inner\n */gridProto._findConvertTarget=function(ecModel,finder){var seriesModel=finder.seriesModel;var xAxisModel=finder.xAxisModel||seriesModel&&seriesModel.getReferringComponents('xAxis')[0];var yAxisModel=finder.yAxisModel||seriesModel&&seriesModel.getReferringComponents('yAxis')[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);}// Lowest priority.\nelse if(gridModel){var grid=gridModel.coordinateSystem;if(grid===this){cartesian=this._coordsList[0];}}return{cartesian:cartesian,axis:axis};};/**\n * @implements\n * see {module:echarts/CoodinateSystem}\n */gridProto.containPoint=function(point){var coord=this._coordsList[0];if(coord){return coord.containPoint(point);}};/**\n * Initialize cartesian coordinate systems\n * @private\n */gridProto._initCartesian=function(gridModel,ecModel,api){var axisPositionUsed={left:false,right:false,top:false,bottom:false};var axesMap={x:{},y:{}};var axesCount={x:0,y:0};/// Create axis\necModel.eachComponent('xAxis',createAxisCreator('x'),this);ecModel.eachComponent('yAxis',createAxisCreator('y'),this);if(!axesCount.x||!axesCount.y){// Roll back when there no either x or y axis\nthis._axesMap={};this._axesList=[];return;}this._axesMap=axesMap;/// Create cartesian2d\neach$1(axesMap.x,function(xAxis,xAxisIndex){each$1(axesMap.y,function(yAxis,yAxisIndex){var key='x'+xAxisIndex+'y'+yAxisIndex;var cartesian=new Cartesian2D(key);cartesian.grid=this;cartesian.model=gridModel;this._coordsMap[key]=cartesian;this._coordsList.push(cartesian);cartesian.addAxis(xAxis);cartesian.addAxis(yAxis);},this);},this);function createAxisCreator(axisType){return function(axisModel,idx){if(!isAxisUsedInTheGrid(axisModel,gridModel,ecModel)){return;}var axisPosition=axisModel.get('position');if(axisType==='x'){// Fix position\nif(axisPosition!=='top'&&axisPosition!=='bottom'){// Default bottom of X\naxisPosition=axisPositionUsed.bottom?'top':'bottom';}}else{// Fix position\nif(axisPosition!=='left'&&axisPosition!=='right'){// Default left of Y\naxisPosition=axisPositionUsed.left?'right':'left';}}axisPositionUsed[axisPosition]=true;var axis=new Axis2D(axisType,createScaleByModel(axisModel),[0,0],axisModel.get('type'),axisPosition);var isCategory=axis.type==='category';axis.onBand=isCategory&&axisModel.get('boundaryGap');axis.inverse=axisModel.get('inverse');// Inject axis into axisModel\naxisModel.axis=axis;// Inject axisModel into axis\naxis.model=axisModel;// Inject grid info axis\naxis.grid=this;// Index of axis, can be used as key\naxis.index=idx;this._axesList.push(axis);axesMap[axisType][idx]=axis;axesCount[axisType]++;};}};/**\n * Update cartesian properties from series\n * @param  {module:echarts/model/Option} option\n * @private\n */gridProto._updateScale=function(ecModel,gridModel){// Reset scale\neach$1(this._axesList,function(axis){axis.scale.setExtent(Infinity,-Infinity);});ecModel.eachSeries(function(seriesModel){if(isCartesian2D(seriesModel)){var axesModels=findAxesModels(seriesModel,ecModel);var xAxisModel=axesModels[0];var yAxisModel=axesModels[1];if(!isAxisUsedInTheGrid(xAxisModel,gridModel,ecModel)||!isAxisUsedInTheGrid(yAxisModel,gridModel,ecModel)){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,seriesModel);unionExtent(data,yAxis,seriesModel);}}},this);function unionExtent(data,axis,seriesModel){each$1(data.mapDimension(axis.dim,true),function(dim){axis.scale.unionExtentFromData(// For example, the extent of the orginal dimension\n// is [0.1, 0.5], the extent of the `stackResultDimension`\n// is [7, 9], the final extent should not include [0.1, 0.5].\ndata,getStackedDimension(data,dim));});}};/**\n * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined\n * @return {Object} {baseAxes: [], otherAxes: []}\n */gridProto.getTooltipAxes=function(dim){var baseAxes=[];var otherAxes=[];each$1(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};};/**\n * @inner\n */function updateAxisTransform(axis,coordBase){var axisExtent=axis.getExtent();var axisExtentSum=axisExtent[0]+axisExtent[1];// Fast transform\naxis.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;};}var axesTypes=['xAxis','yAxis'];/**\n * @inner\n */function findAxesModels(seriesModel,ecModel){return map(axesTypes,function(axisType){var axisModel=seriesModel.getReferringComponents(axisType)[0];if(__DEV__){if(!axisModel){throw new Error(axisType+' \"'+retrieve(seriesModel.get(axisType+'Index'),seriesModel.get(axisType+'Id'),0)+'\" not found');}}return axisModel;});}/**\n * @inner\n */function isCartesian2D(seriesModel){return seriesModel.get('coordinateSystem')==='cartesian2d';}Grid.create=function(ecModel,api){var grids=[];ecModel.eachComponent('grid',function(gridModel,idx){var grid=new Grid(gridModel,ecModel,api);grid.name='grid_'+idx;// dataSampling requires axis extent, so resize\n// should be performed in create stage.\ngrid.resize(gridModel,api,true);gridModel.coordinateSystem=grid;grids.push(grid);});// Inject the coordinateSystems into seriesModel\necModel.eachSeries(function(seriesModel){if(!isCartesian2D(seriesModel)){return;}var axesModels=findAxesModels(seriesModel,ecModel);var xAxisModel=axesModels[0];var yAxisModel=axesModels[1];var gridModel=xAxisModel.getCoordSysModel();if(__DEV__){if(!gridModel){throw new Error('Grid \"'+retrieve(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;};// For deciding which dimensions to use when creating list data\nGrid.dimensions=Grid.prototype.dimensions=Cartesian2D.prototype.dimensions;CoordinateSystemManager.register('cartesian2d',Grid);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var PI$2=Math.PI;/**\n * A final axis is translated and rotated from a \"standard axis\".\n * So opt.position and opt.rotation is required.\n *\n * A standard axis is and axis from [0, 0] to [0, axisExtent[1]],\n * for example: (0, 0) ------------> (0, 50)\n *\n * nameDirection or tickDirection or labelDirection is 1 means tick\n * or label is below the standard axis, whereas is -1 means above\n * the standard axis. labelOffset means offset between label and axis,\n * which is useful when 'onZero', where axisLabel is in the grid and\n * label in outside grid.\n *\n * Tips: like always,\n * positive rotation represents anticlockwise, and negative rotation\n * represents clockwise.\n * The direction of position coordinate is the same as the direction\n * of screen coordinate.\n *\n * Do not need to consider axis 'inverse', which is auto processed by\n * axis extent.\n *\n * @param {module:zrender/container/Group} group\n * @param {Object} axisModel\n * @param {Object} opt Standard axis parameters.\n * @param {Array.<number>} opt.position [x, y]\n * @param {number} opt.rotation by radian\n * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle' or 'center'.\n * @param {number} [opt.tickDirection=1] 1 or -1\n * @param {number} [opt.labelDirection=1] 1 or -1\n * @param {number} [opt.labelOffset=0] Usefull when onZero.\n * @param {string} [opt.axisLabelShow] default get from axisModel.\n * @param {string} [opt.axisName] default get from axisModel.\n * @param {number} [opt.axisNameAvailableWidth]\n * @param {number} [opt.labelRotate] by degree, default get from axisModel.\n * @param {number} [opt.strokeContainThreshold] Default label interval when label\n * @param {number} [opt.nameTruncateMaxWidth]\n */var AxisBuilder=function AxisBuilder(axisModel,opt){/**\n     * @readOnly\n     */this.opt=opt;/**\n     * @readOnly\n     */this.axisModel=axisModel;// Default value\ndefaults(opt,{labelOffset:0,nameDirection:1,tickDirection:1,labelDirection:1,silent:true});/**\n     * @readOnly\n     */this.group=new Group();// FIXME Not use a seperate text group?\nvar dumbGroup=new Group({position:opt.position.slice(),rotation:opt.rotation});// this.group.add(dumbGroup);\n// this._dumbGroup = dumbGroup;\ndumbGroup.updateTransform();this._transform=dumbGroup.transform;this._dumbGroup=dumbGroup;};AxisBuilder.prototype={constructor:AxisBuilder,hasBuilder:function hasBuilder(name){return!!builders[name];},add:function add(name){builders[name].call(this);},getGroup:function getGroup(){return this.group;}};var builders={/**\n     * @private\n     */axisLine:function axisLine(){var opt=this.opt;var axisModel=this.axisModel;if(!axisModel.get('axisLine.show')){return;}var extent=this.axisModel.axis.getExtent();var matrix=this._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());this.group.add(new Line({// Id for animation\nanid:'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}));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'){// Use the same arrow for start and end point\narrows=[arrows,arrows];}if(typeof arrowSize==='string'||typeof arrowSize==='number'){// Use the same size for width and height\narrowSize=[arrowSize,arrowSize];}var symbolWidth=arrowSize[0];var symbolHeight=arrowSize[1];each$1([{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/2,-symbolHeight/2,symbolWidth,symbolHeight,lineStyle.stroke,true);// Calculate arrow position with offset\nvar r=point.r+point.offset;var pos=[pt1[0]+r*Math.cos(opt.rotation),pt1[1]-r*Math.sin(opt.rotation)];symbol.attr({rotation:point.rotate,position:pos,silent:true,z2:11});this.group.add(symbol);}},this);}},/**\n     * @private\n     */axisTickLabel:function axisTickLabel(){var axisModel=this.axisModel;var opt=this.opt;var ticksEls=buildAxisMajorTicks(this,axisModel,opt);var labelEls=buildAxisLabel(this,axisModel,opt);fixMinMaxLabelShow(axisModel,labelEls,ticksEls);buildAxisMinorTicks(this,axisModel,opt);},/**\n     * @private\n     */axisName:function axisName(){var opt=this.opt;var axisModel=this.axisModel;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=this.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,// 'middle'\n// Reuse labelOffset.\nisNameLocationCenter(nameLocation)?opt.labelOffset+nameDirection*gap:0];var labelLayout;var nameRotation=axisModel.get('nameRotate');if(nameRotation!=null){nameRotation=nameRotation*PI$2/180;// To radian.\n}var axisNameAvailableWidth;if(isNameLocationCenter(nameLocation)){labelLayout=innerTextLayout(opt.rotation,nameRotation!=null?nameRotation:opt.rotation,// Adapt to axis.\nnameDirection);}else{labelLayout=endTextLayout(opt,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);// FIXME\n// truncate rich text? (consider performance)\nvar truncatedText=ellipsis!=null&&maxWidth!=null?truncateText$1(name,maxWidth,textFont,ellipsis,{minChar:2,placeholder:truncateOpt.placeholder}):name;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 Text({// Id for animation\nanid:'name',__fullText:name,__truncatedText:truncatedText,position:pos,rotation:labelLayout.rotation,silent:isLabelSilent(axisModel),z2:1,tooltip:tooltipOpt&&tooltipOpt.show?extend({content:name,formatter:function formatter(){return name;},formatterParams:formatterParams},tooltipOpt):null});setTextStyle(textEl.style,textStyleModel,{text:truncatedText,textFont:textFont,textFill:textStyleModel.getTextColor()||axisModel.get('axisLine.lineStyle.color'),textAlign:textStyleModel.get('align')||labelLayout.textAlign,textVerticalAlign:textStyleModel.get('verticalAlign')||labelLayout.textVerticalAlign});if(axisModel.get('triggerEvent')){textEl.eventData=makeAxisEventDataBase(axisModel);textEl.eventData.targetType='axisName';textEl.eventData.name=name;}// FIXME\nthis._dumbGroup.add(textEl);textEl.updateTransform();this.group.add(textEl);textEl.decomposeTransform();}};var makeAxisEventDataBase=AxisBuilder.makeAxisEventDataBase=function(axisModel){var eventData={componentType:axisModel.mainType,componentIndex:axisModel.componentIndex};eventData[axisModel.mainType+'Index']=axisModel.componentIndex;return eventData;};/**\n * @public\n * @static\n * @param {Object} opt\n * @param {number} axisRotation in radian\n * @param {number} textRotation in radian\n * @param {number} direction\n * @return {Object} {\n *  rotation, // according to axis\n *  textAlign,\n *  textVerticalAlign\n * }\n */var innerTextLayout=AxisBuilder.innerTextLayout=function(axisRotation,textRotation,direction){var rotationDiff=remRadian(textRotation-axisRotation);var textAlign;var textVerticalAlign;if(isRadianAroundZero(rotationDiff)){// Label is parallel with axis line.\ntextVerticalAlign=direction>0?'top':'bottom';textAlign='center';}else if(isRadianAroundZero(rotationDiff-PI$2)){// Label is inverse parallel with axis line.\ntextVerticalAlign=direction>0?'bottom':'top';textAlign='center';}else{textVerticalAlign='middle';if(rotationDiff>0&&rotationDiff<PI$2){textAlign=direction>0?'right':'left';}else{textAlign=direction>0?'left':'right';}}return{rotation:rotationDiff,textAlign:textAlign,textVerticalAlign:textVerticalAlign};};function endTextLayout(opt,textPosition,textRotate,extent){var rotationDiff=remRadian(textRotate-opt.rotation);var textAlign;var textVerticalAlign;var inverse=extent[0]>extent[1];var onLeft=textPosition==='start'&&!inverse||textPosition!=='start'&&inverse;if(isRadianAroundZero(rotationDiff-PI$2/2)){textVerticalAlign=onLeft?'bottom':'top';textAlign='center';}else if(isRadianAroundZero(rotationDiff-PI$2*1.5)){textVerticalAlign=onLeft?'top':'bottom';textAlign='center';}else{textVerticalAlign='middle';if(rotationDiff<PI$2*1.5&&rotationDiff>PI$2/2){textAlign=onLeft?'left':'right';}else{textAlign=onLeft?'right':'left';}}return{rotation:rotationDiff,textAlign:textAlign,textVerticalAlign:textVerticalAlign};}var isLabelSilent=AxisBuilder.isLabelSilent=function(axisModel){var tooltipOpt=axisModel.get('tooltip');return axisModel.get('silent')// Consider mouse cursor, add these restrictions.\n||!(axisModel.get('triggerEvent')||tooltipOpt&&tooltipOpt.show);};function fixMinMaxLabelShow(axisModel,labelEls,tickEls){if(shouldShowAllLabels(axisModel.axis)){return;}// If min or max are user set, we need to check\n// If the tick on min(max) are overlap on their neighbour tick\n// If they are overlapped, we need to hide the min(max) tick label\nvar showMinLabel=axisModel.get('axisLabel.showMinLabel');var showMaxLabel=axisModel.get('axisLabel.showMaxLabel');// FIXME\n// Have not consider onBand yet, where tick els is more than label els.\nlabelEls=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,labelLayout){// current and next has the same rotation.\nvar firstRect=current&&current.getBoundingRect().clone();var nextRect=next&&next.getBoundingRect().clone();if(!firstRect||!nextRect){return;}// When checking intersect of two rotated labels, we use mRotationBack\n// to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.\nvar 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,aniid){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);}// Tick line, Not use group transform to have better line draw\nvar tickEl=new Line({// Id for animation\nanid:aniid+'_'+ticksCoords[i].tickValue,subPixelOptimize:true,shape:{x1:pt1[0],y1:pt1[1],x2:pt2[0],y2:pt2[1]},style:tickLineStyle,z2:2,silent:true});tickEls.push(tickEl);}return tickEls;}function buildAxisMajorTicks(axisBuilder,axisModel,opt){var axis=axisModel.axis;var tickModel=axisModel.getModel('axisTick');if(!tickModel.get('show')||axis.scale.isBlank()){return;}var lineStyleModel=tickModel.getModel('lineStyle');var tickEndCoord=opt.tickDirection*tickModel.get('length');var ticksCoords=axis.getTicksCoords();var ticksEls=createTicks(ticksCoords,axisBuilder._transform,tickEndCoord,defaults(lineStyleModel.getLineStyle(),{stroke:axisModel.get('axisLine.lineStyle.color')}),'ticks');for(var i=0;i<ticksEls.length;i++){axisBuilder.group.add(ticksEls[i]);}return ticksEls;}function buildAxisMinorTicks(axisBuilder,axisModel,opt){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=opt.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],axisBuilder._transform,tickEndCoord,minorTickLineStyle,'minorticks_'+i);for(var k=0;k<minorTicksEls.length;k++){axisBuilder.group.add(minorTicksEls[k]);}}}function buildAxisLabel(axisBuilder,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();// Special label rotate.\nvar labelRotation=(retrieve(opt.labelRotate,labelModel.get('rotate'))||0)*PI$2/180;var labelLayout=innerTextLayout(opt.rotation,labelRotation,opt.labelDirection);var rawCategoryData=axisModel.getCategories&&axisModel.getCategories(true);var labelEls=[];var silent=isLabelSilent(axisModel);var triggerEvent=axisModel.get('triggerEvent');each$1(labels,function(labelItem,index){var tickValue=labelItem.tickValue;var formattedLabel=labelItem.formattedLabel;var rawLabel=labelItem.rawLabel;var itemLabelModel=labelModel;if(rawCategoryData&&rawCategoryData[tickValue]&&rawCategoryData[tickValue].textStyle){itemLabelModel=new Model(rawCategoryData[tickValue].textStyle,labelModel,axisModel.ecModel);}var textColor=itemLabelModel.getTextColor()||axisModel.get('axisLine.lineStyle.color');var tickCoord=axis.dataToCoord(tickValue);var pos=[tickCoord,opt.labelOffset+opt.labelDirection*labelMargin];var textEl=new Text({// Id for animation\nanid:'label_'+tickValue,position:pos,rotation:labelLayout.rotation,silent:silent,z2:10});setTextStyle(textEl.style,itemLabelModel,{text:formattedLabel,textAlign:itemLabelModel.getShallow('align',true)||labelLayout.textAlign,textVerticalAlign:itemLabelModel.getShallow('verticalAlign',true)||itemLabelModel.getShallow('baseline',true)||labelLayout.textVerticalAlign,textFill:typeof textColor==='function'?textColor(// (1) In category axis with data zoom, tick is not the original\n// index of axis.data. So tick should not be exposed to user\n// in category axis.\n// (2) Compatible with previous version, which always use formatted label as\n// input. But in interval scale the formatted label is like '223,445', which\n// maked user repalce ','. So we modify it to return original val but remain\n// it as 'string' to avoid error in replacing.\naxis.type==='category'?rawLabel:axis.type==='value'?tickValue+'':tickValue,index):textColor});// Pack data for mouse event\nif(triggerEvent){textEl.eventData=makeAxisEventDataBase(axisModel);textEl.eventData.targetType='axisLabel';textEl.eventData.value=rawLabel;}// FIXME\naxisBuilder._dumbGroup.add(textEl);textEl.updateTransform();labelEls.push(textEl);axisBuilder.group.add(textEl);textEl.decomposeTransform();});return labelEls;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$6=each$1;var curry$1=curry;// Build axisPointerModel, mergin tooltip.axisPointer model for each axis.\n// allAxesInfo should be updated when setOption performed.\nfunction collect(ecModel,api){var result={/**\n         * key: makeKey(axis.model)\n         * value: {\n         *      axis,\n         *      coordSys,\n         *      axisPointerModel,\n         *      triggerTooltip,\n         *      involveSeries,\n         *      snap,\n         *      seriesModels,\n         *      seriesDataCount\n         * }\n         */axesInfo:{},seriesInvolved:false,/**\n         * key: makeKey(coordSys.model)\n         * value: Object: key makeKey(axis.model), value: axisInfo\n         */coordSysAxesInfo:{},coordSysMap:{}};collectAxesInfo(result,ecModel,api);// Check seriesInvolved for performance, in case too many series in some chart.\nresult.seriesInvolved&&collectSeriesInfo(result,ecModel);return result;}function collectAxesInfo(result,ecModel,api){var globalTooltipModel=ecModel.getComponent('tooltip');var globalAxisPointerModel=ecModel.getComponent('axisPointer');// links can only be set on global.\nvar linksOption=globalAxisPointerModel.get('link',true)||[];var linkGroups=[];// Collect axes info.\neach$6(api.getCoordinateSystems(),function(coordSys){// Some coordinate system do not support axes, like geo.\nif(!coordSys.axisPointerEnabled){return;}var coordSysKey=makeKey(coordSys.model);var axesInfoInCoordSys=result.coordSysAxesInfo[coordSysKey]={};result.coordSysMap[coordSysKey]=coordSys;// Set tooltip (like 'cross') is a convienent way to show axisPointer\n// for user. So we enable seting tooltip on coordSys model.\nvar coordSysModel=coordSys.model;var baseTooltipModel=coordSysModel.getModel('tooltip',globalTooltipModel);each$6(coordSys.getAxes(),curry$1(saveTooltipAxisInfo,false,null));// If axis tooltip used, choose tooltip axis for each coordSys.\n// Notice this case: coordSys is `grid` but not `cartesian2D` here.\nif(coordSys.getTooltipAxes&&globalTooltipModel// If tooltip.showContent is set as false, tooltip will not\n// show but axisPointer will show as normal.\n&&baseTooltipModel.get('show')){// Compatible with previous logic. But series.tooltip.trigger: 'axis'\n// or series.data[n].tooltip.trigger: 'axis' are not support any more.\nvar triggerAxis=baseTooltipModel.get('trigger')==='axis';var cross=baseTooltipModel.get('axisPointer.type')==='cross';var tooltipAxes=coordSys.getTooltipAxes(baseTooltipModel.get('axisPointer.axis'));if(triggerAxis||cross){each$6(tooltipAxes.baseAxes,curry$1(saveTooltipAxisInfo,cross?'cross':true,triggerAxis));}if(cross){each$6(tooltipAxes.otherAxes,curry$1(saveTooltipAxisInfo,'cross',false));}}// fromTooltip: true | false | 'cross'\n// triggerTooltip: true | false | null\nfunction 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 key=makeKey(axis.model);var involveSeries=triggerTooltip||snap||axis.type==='category';// If result.axesInfo[key] exist, override it (tooltip has higher priority).\nvar axisInfo=result.axesInfo[key]={key:key,axis:axis,coordSys:coordSys,axisPointerModel:axisPointerModel,triggerTooltip:triggerTooltip,involveSeries:involveSeries,snap:snap,useHandle:isHandleTrigger(axisPointerModel),seriesModels:[]};axesInfoInCoordSys[key]=axisInfo;result.seriesInvolved|=involveSeries;var groupIndex=getLinkGroupIndex(linksOption,axis);if(groupIndex!=null){var linkGroup=linkGroups[groupIndex]||(linkGroups[groupIndex]={axesInfo:{}});linkGroup.axesInfo[key]=axisInfo;linkGroup.mapper=linksOption[groupIndex].mapper;axisInfo.linkGroup=linkGroup;}}});}function makeAxisPointerModel(axis,baseTooltipModel,globalAxisPointerModel,ecModel,fromTooltip,triggerTooltip){var tooltipAxisPointerModel=baseTooltipModel.getModel('axisPointer');var volatileOption={};each$6(['type','snap','lineStyle','shadowStyle','label','animation','animationDurationUpdate','animationEasingUpdate','z'],function(field){volatileOption[field]=_clone(tooltipAxisPointerModel.get(field));});// category axis do not auto snap, otherwise some tick that do not\n// has value can not be hovered. value/time/log axis default snap if\n// triggered from tooltip and trigger tooltip.\nvolatileOption.snap=axis.type!=='category'&&!!triggerTooltip;// Compatibel with previous behavior, tooltip axis do not show label by default.\n// Only these properties can be overrided from tooltip to axisPointer.\nif(tooltipAxisPointerModel.get('type')==='cross'){volatileOption.type='line';}var labelOption=volatileOption.label||(volatileOption.label={});// Follow the convention, do not show label when triggered by tooltip by default.\nlabelOption.show==null&&(labelOption.show=false);if(fromTooltip==='cross'){// When 'cross', both axes show labels.\nvar tooltipAxisPointerLabelShow=tooltipAxisPointerModel.get('label.show');labelOption.show=tooltipAxisPointerLabelShow!=null?tooltipAxisPointerLabelShow:true;// If triggerTooltip, this is a base axis, which should better not use cross style\n// (cross style is dashed by default)\nif(!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){// Prepare data for axis trigger\necModel.eachSeries(function(seriesModel){// Notice this case: this coordSys is `cartesian2D` but not `grid`.\nvar 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$6(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();}});},this);}/**\n * For example:\n * {\n *     axisPointer: {\n *         links: [{\n *             xAxisIndex: [2, 4],\n *             yAxisIndex: 'all'\n *         }, {\n *             xAxisId: ['a5', 'a7'],\n *             xAxisName: 'xxx'\n *         }]\n *     }\n * }\n */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');// Parse init value for category and time axis.\nif(value!=null){value=scale.parse(value);}var useHandle=isHandleTrigger(axisPointerModel);// If `handle` used, `axisPointer` will always be displayed, so value\n// and status should be initialized.\nif(status==null){option.status=useHandle?'show':'hide';}var extent=scale.getExtent().slice();extent[0]>extent[1]&&extent.reverse();if(// Pick a value on axis when initializing.\nvalue==null// If both `handle` and `dataZoom` are used, value may be out of axis extent,\n// where we should re-pick a value to keep `handle` displaying normally.\n||value>extent[1]){// Make handle displayed on the end of the axis when init, which looks better.\nvalue=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');}/**\n * @param {module:echarts/model/Model} model\n * @return {string} unique key\n */function makeKey(model){return model.type+'||'+model.id;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Base class of AxisView.\n */var AxisView=extendComponentView({type:'axis',/**\n     * @private\n     */_axisPointer:null,/**\n     * @protected\n     * @type {string}\n     */axisPointerClass:null,/**\n     * @override\n     */render:function render(axisModel,ecModel,api,payload){// FIXME\n// This process should proformed after coordinate systems updated\n// (axis scale updated), and should be performed each time update.\n// So put it here temporarily, although it is not appropriate to\n// put a model-writing procedure in `view`.\nthis.axisPointerClass&&fixValue(axisModel);AxisView.superApply(this,'render',arguments);_updateAxisPointer(this,axisModel,ecModel,api,payload,true);},/**\n     * Action handler.\n     * @public\n     * @param {module:echarts/coord/cartesian/AxisModel} axisModel\n     * @param {module:echarts/model/Global} ecModel\n     * @param {module:echarts/ExtensionAPI} api\n     * @param {Object} payload\n     */updateAxisPointer:function updateAxisPointer(axisModel,ecModel,api,payload,force){_updateAxisPointer(this,axisModel,ecModel,api,payload,false);},/**\n     * @override\n     */remove:function remove(ecModel,api){var axisPointer=this._axisPointer;axisPointer&&axisPointer.remove(api);AxisView.superApply(this,'remove',arguments);},/**\n     * @override\n     */dispose:function dispose(ecModel,api){disposeAxisPointer(this,api);AxisView.superApply(this,'dispose',arguments);}});function _updateAxisPointer(axisView,axisModel,ecModel,api,payload,forceRender){var Clazz=AxisView.getAxisPointerClass(axisView.axisPointerClass);if(!Clazz){return;}var axisPointerModel=getAxisPointerModel(axisModel);axisPointerModel?(axisView._axisPointer||(axisView._axisPointer=new Clazz())).render(axisModel,axisPointerModel,api,forceRender):disposeAxisPointer(axisView,api);}function disposeAxisPointer(axisView,ecModel,api){var axisPointer=axisView._axisPointer;axisPointer&&axisPointer.dispose(ecModel,api);axisView._axisPointer=null;}var axisPointerClazz=[];AxisView.registerAxisPointerClass=function(type,clazz){if(__DEV__){if(axisPointerClazz[type]){throw new Error('axisPointer '+type+' exists');}}axisPointerClazz[type]=clazz;};AxisView.getAxisPointerClass=function(type){return type&&axisPointerClazz[type];};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Can only be called after coordinate system creation stage.\n * (Can be called before coordinate system update stage).\n *\n * @param {Object} opt {labelInside}\n * @return {Object} {\n *  position, rotation, labelDirection, labelOffset,\n *  tickDirection, labelRotate, z2\n * }\n */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]);}// Axis position\nlayout.position=[axisDim==='y'?posBound[idx[axisPosition]]:rectBound[0],axisDim==='x'?posBound[idx[axisPosition]]:rectBound[3]];// Axis rotation\nlayout.rotation=Math.PI/2*(axisDim==='x'?0:1);// Tick and label direction, x y is axisDim\nvar 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;}// Special label rotation\nvar labelRotate=axisModel.get('axisLabel.rotate');layout.labelRotate=axisPosition==='top'?-labelRotate:labelRotate;// Over splitLine and splitArea\nlayout.z2=1;return layout;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/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;}// For Making appropriate splitArea animation, the color and anid\n// should be corresponding to previous one if possible.\nvar areaColorsLen=areaColors.length;var lastSplitAreaColors=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;var y;var width;var height;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),silent:true}));colorIndex=(colorIndex+1)%areaColorsLen;}axisView.__splitAreaColors=newSplitAreaColors;}function rectCoordAxisHandleRemove(axisView){axisView.__splitAreaColors=null;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var axisBuilderAttrs=['axisLine','axisTickLabel','axisName'];var selfBuilderAttrs=['splitArea','splitLine','minorSplitLine'];var CartesianAxisView=AxisView.extend({type:'cartesianAxis',axisPointerClass:'CartesianAxisPointer',/**\n     * @override\n     */render:function render(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,layout);each$1(axisBuilderAttrs,axisBuilder.add,axisBuilder);this._axisGroup.add(axisBuilder.getGroup());each$1(selfBuilderAttrs,function(name){if(axisModel.get(name+'.show')){this['_'+name](axisModel,gridModel);}},this);groupTransition(oldAxisGroup,this._axisGroup,axisModel);CartesianAxisView.superCall(this,'render',axisModel,ecModel,api,payload);},remove:function remove(){rectCoordAxisHandleRemove(this);},/**\n     * @param {module:echarts/coord/cartesian/AxisModel} axisModel\n     * @param {module:echarts/coord/cartesian/GridModel} gridModel\n     * @private\n     */_splitLine:function _splitLine(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;this._axisGroup.add(new Line({anid:tickValue!=null?'line_'+ticksCoords[i].tickValue:null,subPixelOptimize:true,shape:{x1:p1[0],y1:p1[1],x2:p2[0],y2:p2[1]},style:defaults({stroke:lineColors[colorIndex]},lineStyle),silent:true}));}},/**\n     * @param {module:echarts/coord/cartesian/AxisModel} axisModel\n     * @param {module:echarts/coord/cartesian/GridModel} gridModel\n     * @private\n     */_minorSplitLine:function _minorSplitLine(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;}this._axisGroup.add(new Line({anid:'minor_line_'+minorTicksCoords[i][k].tickValue,subPixelOptimize:true,shape:{x1:p1[0],y1:p1[1],x2:p2[0],y2:p2[1]},style:lineStyle,silent:true}));}}},/**\n     * @param {module:echarts/coord/cartesian/AxisModel} axisModel\n     * @param {module:echarts/coord/cartesian/GridModel} gridModel\n     * @private\n     */_splitArea:function _splitArea(axisModel,gridModel){rectCoordAxisBuildSplitArea(this,this._axisGroup,axisModel,gridModel);}});CartesianAxisView.extend({type:'xAxis'});CartesianAxisView.extend({type:'yAxis'});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Grid view\nextendComponentView({type:'grid',render:function render(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}));}}});registerPreprocessor(function(option){// Only create grid when need\nif(option.xAxis&&option.yAxis&&!option.grid){option.grid={};}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // In case developer forget to include grid component\nregisterVisual(visualSymbol('line','circle','line'));registerLayout(pointsLayout('line'));// Down sample after filter\nregisterProcessor(PRIORITY.PROCESSOR.STATISTIC,dataSample('line'));/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var BaseBarSeries=SeriesModel.extend({type:'series.__base_bar__',getInitialData:function getInitialData(option,ecModel){return createListFromArray(this.getSource(),this,{useEncodeDefaulter:true});},getMarkerPosition:function getMarkerPosition(value){var coordSys=this.coordinateSystem;if(coordSys){// PENDING if clamp ?\nvar 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];},defaultOption:{zlevel:0,// 一级层叠\nz:2,// 二级层叠\ncoordinateSystem:'cartesian2d',legendHoverLink:true,// stack: null\n// Cartesian coordinate system\n// xAxisIndex: 0,\n// yAxisIndex: 0,\n// 最小高度改为0\nbarMinHeight:0,// 最小角度为0，仅对极坐标系下的柱状图有效\nbarMinAngle:0,// cursor: null,\nlarge:false,largeThreshold:400,progressive:3e3,progressiveChunkMode:'mod',// barMaxWidth: null,\n// In cartesian, the default value is 1. Otherwise null.\n// barMinWidth: null,\n// 默认自适应\n// barWidth: null,\n// 柱间距离，默认为柱形宽度的30%，可设固定值\n// barGap: '30%',\n// 类目间柱形距离，默认为类目间距的20%，可设固定值\n// barCategoryGap: '20%',\n// label: {\n//      show: false\n// },\nitemStyle:{},emphasis:{}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/BaseBarSeries.extend({type:'series.bar',dependencies:['grid','polar'],brushSelector:'rect',/**\n     * @override\n     */getProgressive:function getProgressive(){// Do not support progressive in normal mode.\nreturn this.get('large')?this.get('progressive'):false;},/**\n     * @override\n     */getProgressiveThreshold:function getProgressiveThreshold(){// Do not support progressive in normal mode.\nvar progressiveThreshold=this.get('progressiveThreshold');var largeThreshold=this.get('largeThreshold');if(largeThreshold>progressiveThreshold){progressiveThreshold=largeThreshold;}return progressiveThreshold;},defaultOption:{// If clipped\n// Only available on cartesian2d\nclip:true,// If use caps on two sides of bars\n// Only available on tangential polar bar\nroundCap: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}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function setLabel(normalStyle,hoverStyle,itemModel,color,seriesModel,dataIndex,labelPositionOutside){var labelModel=itemModel.getModel('label');var hoverLabelModel=itemModel.getModel('emphasis.label');setLabelStyle(normalStyle,hoverStyle,labelModel,hoverLabelModel,{labelFetcher:seriesModel,labelDataIndex:dataIndex,defaultText:getDefaultLabel(seriesModel.getData(),dataIndex),isRectText:true,autoColor:color});fixPosition(normalStyle);fixPosition(hoverStyle);}function fixPosition(style,labelPositionOutside){if(style.textPosition==='outside'){style.textPosition=labelPositionOutside;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var _getBarItemStyle=makeStyleMapper([['fill','color'],['stroke','borderColor'],['lineWidth','borderWidth'],// Compatitable with 2\n['stroke','barBorderColor'],['lineWidth','barBorderWidth'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor']]);var barItemStyle={getBarItemStyle:function getBarItemStyle(excludes){var style=_getBarItemStyle(this,excludes);if(this.getBorderLineDash){var lineDash=this.getBorderLineDash();lineDash&&(style.lineDash=lineDash);}return style;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Sausage: similar to sector, but have half circle on both sides\n * @public\n */var Sausage=extendShape({type:'sausage',shape:{cx:0,cy:0,r0:0,r:0,startAngle:0,endAngle:Math.PI*2,clockwise:true},buildPath:function buildPath(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();}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var BAR_BORDER_WIDTH_QUERY=['itemStyle','barBorderWidth'];var _eventPos=[0,0];// FIXME\n// Just for compatible with ec2.\nextend(Model.prototype,barItemStyle);function getClipArea(coord,data){var coordSysClipArea=coord.getArea&&coord.getArea();if(coord.type==='cartesian2d'){var baseAxis=coord.getBaseAxis();// When boundaryGap is false or using time axis. bar may exceed the grid.\n// We should not clip this part.\n// See test/bar2.html\nif(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;}extendChartView({type:'bar',render:function render(seriesModel,ecModel,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);}else if(__DEV__){console.warn('Only cartesian2d and polar supported for bar.');}return this.group;},incrementalPrepareRender:function incrementalPrepareRender(seriesModel,ecModel,api){this._clear();this._updateDrawMode(seriesModel);},incrementalRender:function incrementalRender(params,seriesModel,ecModel,api){// Do not support progressive in normal mode.\nthis._incrementalRenderLarge(params,seriesModel);},_updateDrawMode:function _updateDrawMode(seriesModel){var isLargeDraw=seriesModel.pipelineContext.large;if(this._isLargeDraw==null||isLargeDraw^this._isLargeDraw){this._isLargeDraw=isLargeDraw;this._clear();}},_renderNormal:function _renderNormal(seriesModel,ecModel,api){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 needsClip=seriesModel.get('clip',true);var coordSysClipArea=getClipArea(coord,data);// If there is clipPath created in large mode. Remove it.\ngroup.removeClipPath();// We don't use clipPath in normal mode because we needs a perfect animation\n// And don't want the label are clipped.\nvar roundCap=seriesModel.get('roundCap',true);var drawBackground=seriesModel.get('showBackground',true);var backgroundModel=seriesModel.getModel('backgroundStyle');var barBorderRadius=backgroundModel.get('barBorderRadius')||0;var bgEls=[];var oldBgEls=this._backgroundEls||[];var createBackground=function createBackground(dataIndex){var bgLayout=getLayout[coord.type](data,dataIndex);var bgEl=createBackgroundEl(coord,isHorizontalOrRadial,bgLayout);bgEl.useStyle(backgroundModel.getBarItemStyle());// Only cartesian2d support borderRadius.\nif(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 dataZoom in filteMode: 'empty', the baseValue can be set as NaN in \"axisProxy\".\nif(!data.hasValue(dataIndex)){return;}if(needsClip){// Clip will modify the layout params.\n// And return a boolean to determine if the shape are fully clipped.\nvar isClipped=clip[coord.type](coordSysClipArea,layout);if(isClipped){group.remove(el);return;}}var el=elementCreator[coord.type](dataIndex,layout,isHorizontalOrRadial,animationModel,false,roundCap);data.setItemGraphicEl(dataIndex,el);group.add(el);updateStyle(el,data,dataIndex,itemModel,layout,seriesModel,isHorizontalOrRadial,coord.type==='polar');}).update(function(newIndex,oldIndex){var itemModel=data.getItemModel(newIndex);var layout=getLayout[coord.type](data,newIndex,itemModel);if(drawBackground){var bgEl;if(oldBgEls.length===0){bgEl=createBackground(oldIndex);}else{bgEl=oldBgEls[oldIndex];bgEl.useStyle(backgroundModel.getBarItemStyle());// Only cartesian2d support borderRadius.\nif(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);return;}if(needsClip){var isClipped=clip[coord.type](coordSysClipArea,layout);if(isClipped){group.remove(el);return;}}if(el){updateProps(el,{shape:layout},animationModel,newIndex);}else{el=elementCreator[coord.type](newIndex,layout,isHorizontalOrRadial,animationModel,true,roundCap);}data.setItemGraphicEl(newIndex,el);// Add back\ngroup.add(el);updateStyle(el,data,newIndex,itemModel,layout,seriesModel,isHorizontalOrRadial,coord.type==='polar');}).remove(function(dataIndex){var el=oldData.getItemGraphicEl(dataIndex);if(coord.type==='cartesian2d'){el&&removeRect(dataIndex,animationModel,el);}else{el&&removeSector(dataIndex,animationModel,el);}}).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;},_renderLarge:function _renderLarge(seriesModel,ecModel,api){this._clear();createLarge(seriesModel,this.group);// Use clipPath in large mode.\nvar clipPath=seriesModel.get('clip',true)?createClipPath(seriesModel.coordinateSystem,false,seriesModel):null;if(clipPath){this.group.setClipPath(clipPath);}else{this.group.removeClipPath();}},_incrementalRenderLarge:function _incrementalRenderLarge(params,seriesModel){this._removeBackground();createLarge(seriesModel,this.group,true);},dispose:noop,remove:function remove(ecModel){this._clear(ecModel);},_clear:function _clear(ecModel){var group=this.group;var data=this._data;if(ecModel&&ecModel.get('animation')&&data&&!this._isLargeDraw){this._removeBackground();this._backgroundEls=[];data.eachItemGraphicEl(function(el){if(el.type==='sector'){removeSector(el.dataIndex,ecModel,el);}else{removeRect(el.dataIndex,ecModel,el);}});}else{group.removeAll();}this._data=null;},_removeBackground:function _removeBackground(){this.group.remove(this._backgroundGroup);this._backgroundGroup=null;}});var mathMax$4=Math.max;var mathMin$4=Math.min;var clip={cartesian2d:function cartesian2d(coordSysBoundingRect,layout){var signWidth=layout.width<0?-1:1;var signHeight=layout.height<0?-1:1;// Needs positive width and height\nif(signWidth<0){layout.x+=layout.width;layout.width=-layout.width;}if(signHeight<0){layout.y+=layout.height;layout.height=-layout.height;}var x=mathMax$4(layout.x,coordSysBoundingRect.x);var x2=mathMin$4(layout.x+layout.width,coordSysBoundingRect.x+coordSysBoundingRect.width);var y=mathMax$4(layout.y,coordSysBoundingRect.y);var y2=mathMin$4(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;// Reverse back\nif(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 polar(coordSysClipArea,layout){var signR=layout.r0<=layout.r?1:-1;// Make sure r is larger than r0\nif(signR<0){var r=layout.r;layout.r=layout.r0;layout.r0=r;}var r=mathMin$4(layout.r,coordSysClipArea.r);var r0=mathMax$4(layout.r0,coordSysClipArea.r0);layout.r=r;layout.r0=r0;var clipped=r-r0<0;// Reverse back\nif(signR<0){var r=layout.r;layout.r=layout.r0;layout.r0=r;}return clipped;}};var elementCreator={cartesian2d:function cartesian2d(dataIndex,layout,isHorizontal,animationModel,isUpdate){var rect=new Rect({shape:extend({},layout),z2:1});rect.name='item';// Animation\nif(animationModel){var rectShape=rect.shape;var animateProperty=isHorizontal?'height':'width';var animateTarget={};rectShape[animateProperty]=0;animateTarget[animateProperty]=layout[animateProperty];graphic[isUpdate?'updateProps':'initProps'](rect,{shape:animateTarget},animationModel,dataIndex);}return rect;},polar:function polar(dataIndex,layout,isRadial,animationModel,isUpdate,roundCap){// Keep the same logic with bar in catesion: use end value to control\n// direction. Notice that if clockwise is true (by default), the sector\n// will always draw clockwisely, no matter whether endAngle is greater\n// or less than startAngle.\nvar clockwise=layout.startAngle<layout.endAngle;var ShapeClass=!isRadial&&roundCap?Sausage:Sector;var sector=new ShapeClass({shape:defaults({clockwise:clockwise},layout),z2:1});sector.name='item';// Animation\nif(animationModel){var sectorShape=sector.shape;var animateProperty=isRadial?'r':'endAngle';var animateTarget={};sectorShape[animateProperty]=isRadial?0:layout.startAngle;animateTarget[animateProperty]=layout[animateProperty];graphic[isUpdate?'updateProps':'initProps'](sector,{shape:animateTarget},animationModel,dataIndex);}return sector;}};function removeRect(dataIndex,animationModel,el){// Not show text when animating\nel.style.text=null;updateProps(el,{shape:{width:0}},animationModel,dataIndex,function(){el.parent&&el.parent.remove(el);});}function removeSector(dataIndex,animationModel,el){// Not show text when animating\nel.style.text=null;updateProps(el,{shape:{r:el.shape.r0}},animationModel,dataIndex,function(){el.parent&&el.parent.remove(el);});}var getLayout={// itemModel is only used to get borderWidth, which is not needed\n// when calculating bar background layout.\ncartesian2d:function cartesian2d(data,dataIndex,itemModel){var layout=data.getItemLayout(dataIndex);var fixedLineWidth=itemModel?getLineWidth(itemModel,layout):0;// fix layout with lineWidth\nvar 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 polar(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 color=data.getItemVisual(dataIndex,'color');var opacity=data.getItemVisual(dataIndex,'opacity');var stroke=data.getVisual('borderColor');var itemStyleModel=itemModel.getModel('itemStyle');var hoverStyle=itemModel.getModel('emphasis.itemStyle').getBarItemStyle();if(!isPolar){el.setShape('r',itemStyleModel.get('barBorderRadius')||0);}el.useStyle(defaults({stroke:isZeroOnPolar(layout)?'none':stroke,fill:isZeroOnPolar(layout)?'none':color,opacity:opacity},itemStyleModel.getBarItemStyle()));var cursorStyle=itemModel.getShallow('cursor');cursorStyle&&el.attr('cursor',cursorStyle);var labelPositionOutside=isHorizontal?layout.height>0?'bottom':'top':layout.width>0?'left':'right';if(!isPolar){setLabel(el.style,hoverStyle,itemModel,color,seriesModel,dataIndex,labelPositionOutside);}if(isZeroOnPolar(layout)){hoverStyle.fill=hoverStyle.stroke='none';}setHoverStyle(el,hoverStyle);}// In case width or height are too small.\nfunction getLineWidth(itemModel,rawLayout){var lineWidth=itemModel.get(BAR_BORDER_WIDTH_QUERY)||0;// width or height may be NaN for empty data\nvar 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 LargePath=Path.extend({type:'largeBar',shape:{points:[]},buildPath:function buildPath(ctx,shape){// Drawing lines is more efficient than drawing\n// a whole line or drawing rects.\nvar 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]);}}});function createLarge(seriesModel,group,incremental){// TODO support polar\nvar 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,__startPoint:backgroundStartPoint,__baseDimIdx:baseDimIdx,__largeDataIndices:largeDataIndices,__barWidth:barWidth,silent:true,z2:0});setLargeBackgroundStyle(bgEl,backgroundModel,data);group.add(bgEl);}var el=new LargePath({shape:{points:data.getLayout('largePoints')},incremental:!!incremental,__startPoint:startPoint,__baseDimIdx:baseDimIdx,__largeDataIndices:largeDataIndices,__barWidth:barWidth});group.add(el);setLargeStyle(el,seriesModel,data);// Enable tooltip and user mouse/touch event handlers.\nel.seriesIndex=seriesModel.seriesIndex;if(!seriesModel.get('silent')){el.on('mousedown',largePathUpdateDataIndex);el.on('mousemove',largePathUpdateDataIndex);}}// Use throttle to avoid frequently traverse to find dataIndex.\nvar largePathUpdateDataIndex=throttle(function(event){var largePath=this;var dataIndex=largePathFindDataIndex(largePath,event.offsetX,event.offsetY);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 borderColor=data.getVisual('borderColor')||data.getVisual('color');var itemStyle=seriesModel.getModel('itemStyle').getItemStyle(['color','borderColor']);el.useStyle(itemStyle);el.style.fill=null;el.style.stroke=borderColor;el.style.lineWidth=data.getLayout('barWidth');}function setLargeBackgroundStyle(el,backgroundModel,data){var borderColor=backgroundModel.get('borderColor')||backgroundModel.get('color');var itemStyle=backgroundModel.getItemStyle(['color','borderColor']);el.useStyle(itemStyle);el.style.fill=null;el.style.stroke=borderColor;el.style.lineWidth=data.getLayout('barWidth');}function createBackgroundShape(isHorizontalOrRadial,layout,coord){var coordLayout;var isPolar=coord.type==='polar';if(isPolar){coordLayout=coord.getArea();}else{coordLayout=coord.grid.getRect();}if(isPolar){return{cx:coordLayout.cx,cy:coordLayout.cy,r0:isHorizontalOrRadial?coordLayout.r0:layout.r0,r:isHorizontalOrRadial?coordLayout.r:layout.r,startAngle:isHorizontalOrRadial?layout.startAngle:0,endAngle:isHorizontalOrRadial?layout.endAngle:Math.PI*2};}else{return{x:isHorizontalOrRadial?layout.x:coordLayout.x,y:isHorizontalOrRadial?coordLayout.y:layout.y,width:isHorizontalOrRadial?layout.width:coordLayout.width,height:isHorizontalOrRadial?coordLayout.height:layout.height};}}function createBackgroundEl(coord,isHorizontalOrRadial,layout){var ElementClz=coord.type==='polar'?Sector:Rect;return new ElementClz({shape:createBackgroundShape(isHorizontalOrRadial,layout,coord),silent:true,z2:0});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // In case developer forget to include grid component\nregisterLayout(PRIORITY.VISUAL.LAYOUT,curry(layout,'bar'));// Use higher prority to avoid to be blocked by other overall layout, which do not\n// only exist in this module, but probably also exist in other modules, like `barPolar`.\nregisterLayout(PRIORITY.VISUAL.PROGRESSIVE_LAYOUT,largeLayout);registerVisual({seriesType:'bar',reset:function reset(seriesModel){// Visual coding for legend\nseriesModel.getData().setVisual('legendSymbol','roundRect');}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * [Usage]:\n * (1)\n * createListSimply(seriesModel, ['value']);\n * (2)\n * createListSimply(seriesModel, {\n *     coordDimensions: ['value'],\n *     dimensionsCount: 5\n * });\n *\n * @param {module:echarts/model/Series} seriesModel\n * @param {Object|Array.<string|Object>} opt opt or coordDimensions\n *        The options in opt, see `echarts/data/helper/createDimensions`\n * @param {Array.<string>} [nameList]\n * @return {module:echarts/data/List}\n */var createListSimply=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;};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Data selectable mixin for chart series.\n * To eanble data select, option of series must have `selectedMode`.\n * And each data item will use `selected` to toggle itself selected status\n */var dataSelectableMixin={/**\n     * @param {Array.<Object>} targetList [{name, value, selected}, ...]\n     *        If targetList is an array, it should like [{name: ..., value: ...}, ...].\n     *        If targetList is a \"List\", it must have coordDim: 'value' dimension and name.\n     */updateSelectedMap:function updateSelectedMap(targetList){this._targetList=isArray(targetList)?targetList.slice():[];this._selectTargetMap=reduce(targetList||[],function(targetMap,target){targetMap.set(target.name,target);return targetMap;},createHashMap());},/**\n     * Either name or id should be passed as input here.\n     * If both of them are defined, id is used.\n     *\n     * @param {string|undefined} name name of data\n     * @param {number|undefined} id dataIndex of data\n     */ // PENGING If selectedMode is null ?\nselect:function select(name,id){var target=id!=null?this._targetList[id]:this._selectTargetMap.get(name);var selectedMode=this.get('selectedMode');if(selectedMode==='single'){this._selectTargetMap.each(function(target){target.selected=false;});}target&&(target.selected=true);},/**\n     * Either name or id should be passed as input here.\n     * If both of them are defined, id is used.\n     *\n     * @param {string|undefined} name name of data\n     * @param {number|undefined} id dataIndex of data\n     */unSelect:function unSelect(name,id){var target=id!=null?this._targetList[id]:this._selectTargetMap.get(name);// var selectedMode = this.get('selectedMode');\n// selectedMode !== 'single' && target && (target.selected = false);\ntarget&&(target.selected=false);},/**\n     * Either name or id should be passed as input here.\n     * If both of them are defined, id is used.\n     *\n     * @param {string|undefined} name name of data\n     * @param {number|undefined} id dataIndex of data\n     */toggleSelected:function toggleSelected(name,id){var target=id!=null?this._targetList[id]:this._selectTargetMap.get(name);if(target!=null){this[target.selected?'unSelect':'select'](name,id);return target.selected;}},/**\n     * Either name or id should be passed as input here.\n     * If both of them are defined, id is used.\n     *\n     * @param {string|undefined} name name of data\n     * @param {number|undefined} id dataIndex of data\n     */isSelected:function isSelected(name,id){var target=id!=null?this._targetList[id]:this._selectTargetMap.get(name);return target&&target.selected;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * LegendVisualProvider is an bridge that pick encoded color from data and\n * provide to the legend component.\n * @param {Function} getDataWithEncodedVisual Function to get data after filtered. It stores all the encoding info\n * @param {Function} getRawData Function to get raw data before filtered.\n */function LegendVisualProvider(getDataWithEncodedVisual,getRawData){this.getAllNames=function(){var rawData=getRawData();// We find the name from the raw data. In case it's filtered by the legend component.\n// Normally, the name can be found in rawData, but can't be found in filtered data will display as gray.\nreturn rawData.mapArray(rawData.getName);};this.containName=function(name){var rawData=getRawData();return rawData.indexOfName(name)>=0;};this.indexOfName=function(name){// Only get data when necessary.\n// Because LegendVisualProvider constructor may be new in the stage that data is not prepared yet.\n// Invoking Series#getData immediately will throw an error.\nvar dataWithEncodedVisual=getDataWithEncodedVisual();return dataWithEncodedVisual.indexOfName(name);};this.getItemVisual=function(dataIndex,key){// Get encoded visual properties from final filtered data.\nvar dataWithEncodedVisual=getDataWithEncodedVisual();return dataWithEncodedVisual.getItemVisual(dataIndex,key);};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var PieSeries=extendSeriesModel({type:'series.pie',// Overwrite\ninit:function init(option){PieSeries.superApply(this,'init',arguments);// Enable legend selection for each data item\n// Use a function instead of direct access because data reference may changed\nthis.legendVisualProvider=new LegendVisualProvider(bind(this.getData,this),bind(this.getRawData,this));this.updateSelectedMap(this._createSelectableList());this._defaultLabelLine(option);},// Overwrite\nmergeOption:function mergeOption(newOption){PieSeries.superCall(this,'mergeOption',newOption);this.updateSelectedMap(this._createSelectableList());},getInitialData:function getInitialData(option,ecModel){return createListSimply(this,{coordDimensions:['value'],encodeDefaulter:curry(makeSeriesEncodeForNameBased,this)});},_createSelectableList:function _createSelectableList(){var data=this.getRawData();var valueDim=data.mapDimension('value');var targetList=[];for(var i=0,len=data.count();i<len;i++){targetList.push({name:data.getName(i),value:data.get(valueDim,i),selected:retrieveRawAttr(data,i,'selected')});}return targetList;},// Overwrite\ngetDataParams:function getDataParams(dataIndex){var data=this.getData();var params=PieSeries.superCall(this,'getDataParams',dataIndex);// FIXME toFixed?\nvar 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;},_defaultLabelLine:function _defaultLabelLine(option){// Extend labelLine emphasis\ndefaultEmphasis(option,'labelLine',['show']);var labelLineNormalOpt=option.labelLine;var labelLineEmphasisOpt=option.emphasis.labelLine;// Not show label line if `label.normal.show = false`\nlabelLineNormalOpt.show=labelLineNormalOpt.show&&option.label.show;labelLineEmphasisOpt.show=labelLineEmphasisOpt.show&&option.emphasis.label.show;},defaultOption:{zlevel:0,z:2,legendHoverLink:true,hoverAnimation:true,// 默认全局居中\ncenter:['50%','50%'],radius:[0,'75%'],// 默认顺时针\nclockwise:true,startAngle:90,// 最小角度改为0\nminAngle:0,// If the angle of a sector less than `minShowLabelAngle`,\n// the label will not be displayed.\nminShowLabelAngle:0,// 选中时扇区偏移量\nselectedOffset:10,// 高亮扇区偏移量\nhoverOffset:10,// If use strategy to avoid label overlapping\navoidLabelOverlap:true,// 选择模式，默认关闭，可选single，multiple\n// selectedMode: false,\n// 南丁格尔玫瑰图模式，'radius'（半径） | 'area'（面积）\n// roseType: null,\npercentPrecision:2,// If still show when all data zero.\nstillShowZeroSum:true,// cursor: null,\nleft:0,top:0,right:0,bottom:0,width:null,height:null,label:{// If rotate around circle\nrotate:false,show:true,// 'outer', 'inside', 'center'\nposition:'outer',// 'none', 'labelLine', 'edge'. Works only when position is 'outer'\nalignTo:'none',// Closest distance between label and chart edge.\n// Works only position is 'outer' and alignTo is 'edge'.\nmargin:'25%',// Works only position is 'outer' and alignTo is not 'edge'.\nbleedMargin:10,// Distance between text and label line.\ndistanceToLabelLine:5// formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调\n// 默认使用全局文本样式，详见TEXTSTYLE\n// distance: 当position为inner时有效，为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数\n},// Enabled when label.normal.position is 'outer'\nlabelLine:{show:true,// 引导线两段中的第一段长度\nlength:15,// 引导线两段中的第二段长度\nlength2:15,smooth:false,lineStyle:{// color: 各异,\nwidth:1,type:'solid'}},itemStyle:{borderWidth:1},// Animation type. Valid values: expansion, scale\nanimationType:'expansion',// Animation type when update. Valid values: transition, expansion\nanimationTypeUpdate:'transition',animationEasing:'cubicOut'}});mixin(PieSeries,dataSelectableMixin);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {module:echarts/model/Series} seriesModel\n * @param {boolean} hasAnimation\n * @inner\n */function updateDataSelected(uid,seriesModel,hasAnimation,api){var data=seriesModel.getData();var dataIndex=this.dataIndex;var name=data.getName(dataIndex);var selectedOffset=seriesModel.get('selectedOffset');api.dispatchAction({type:'pieToggleSelect',from:uid,name:name,seriesId:seriesModel.id});data.each(function(idx){toggleItemSelected(data.getItemGraphicEl(idx),data.getItemLayout(idx),seriesModel.isSelected(data.getName(idx)),selectedOffset,hasAnimation);});}/**\n * @param {module:zrender/graphic/Sector} el\n * @param {Object} layout\n * @param {boolean} isSelected\n * @param {number} selectedOffset\n * @param {boolean} hasAnimation\n * @inner\n */function toggleItemSelected(el,layout,isSelected,selectedOffset,hasAnimation){var midAngle=(layout.startAngle+layout.endAngle)/2;var dx=Math.cos(midAngle);var dy=Math.sin(midAngle);var offset=isSelected?selectedOffset:0;var position=[dx*offset,dy*offset];hasAnimation// animateTo will stop revious animation like update transition\n?el.animate().when(200,{position:position}).start('bounceOut'):el.attr('position',position);}/**\n * Piece of pie including Sector, Label, LabelLine\n * @constructor\n * @extends {module:zrender/graphic/Group}\n */function PiePiece(data,idx){Group.call(this);var sector=new Sector({z2:2});var polyline=new Polyline();var text=new Text();this.add(sector);this.add(polyline);this.add(text);this.updateData(data,idx,true);}var piePieceProto=PiePiece.prototype;piePieceProto.updateData=function(data,idx,firstCreate){var sector=this.childAt(0);var labelLine=this.childAt(1);var labelText=this.childAt(2);var seriesModel=data.hostModel;var itemModel=data.getItemModel(idx);var layout=data.getItemLayout(idx);var sectorShape=extend({},layout);sectorShape.label=null;var animationTypeUpdate=seriesModel.getShallow('animationTypeUpdate');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);}// Expansion\nelse{sector.shape.endAngle=layout.startAngle;updateProps(sector,{shape:{endAngle:layout.endAngle}},seriesModel,idx);}}else{if(animationTypeUpdate==='expansion'){// Sectors are set to be target shape and an overlaying clipPath is used for animation\nsector.setShape(sectorShape);}else{// Transition animation from the old shape\nupdateProps(sector,{shape:sectorShape},seriesModel,idx);}}// Update common style\nvar visualColor=data.getItemVisual(idx,'color');sector.useStyle(defaults({lineJoin:'bevel',fill:visualColor},itemModel.getModel('itemStyle').getItemStyle()));sector.hoverStyle=itemModel.getModel('emphasis.itemStyle').getItemStyle();var cursorStyle=itemModel.getShallow('cursor');cursorStyle&&sector.attr('cursor',cursorStyle);// Toggle selected\ntoggleItemSelected(this,data.getItemLayout(idx),seriesModel.isSelected(data.getName(idx)),seriesModel.get('selectedOffset'),seriesModel.get('animation'));// Label and text animation should be applied only for transition type animation when update\nvar withAnimation=!firstCreate&&animationTypeUpdate==='transition';this._updateLabel(data,idx,withAnimation);this.highDownOnUpdate=!seriesModel.get('silent')?function(fromState,toState){var hasAnimation=seriesModel.isAnimationEnabled()&&itemModel.get('hoverAnimation');if(toState==='emphasis'){labelLine.ignore=labelLine.hoverIgnore;labelText.ignore=labelText.hoverIgnore;// Sector may has animation of updating data. Force to move to the last frame\n// Or it may stopped on the wrong shape\nif(hasAnimation){sector.stopAnimation(true);sector.animateTo({shape:{r:layout.r+seriesModel.get('hoverOffset')}},300,'elasticOut');}}else{labelLine.ignore=labelLine.normalIgnore;labelText.ignore=labelText.normalIgnore;if(hasAnimation){sector.stopAnimation(true);sector.animateTo({shape:{r:layout.r}},300,'elasticOut');}}}:null;setHoverStyle(this);};piePieceProto._updateLabel=function(data,idx,withAnimation){var labelLine=this.childAt(1);var labelText=this.childAt(2);var seriesModel=data.hostModel;var itemModel=data.getItemModel(idx);var layout=data.getItemLayout(idx);var labelLayout=layout.label;var visualColor=data.getItemVisual(idx,'color');if(!labelLayout||isNaN(labelLayout.x)||isNaN(labelLayout.y)){labelText.ignore=labelText.normalIgnore=labelText.hoverIgnore=labelLine.ignore=labelLine.normalIgnore=labelLine.hoverIgnore=true;return;}var targetLineShape={points:labelLayout.linePoints||[[labelLayout.x,labelLayout.y],[labelLayout.x,labelLayout.y],[labelLayout.x,labelLayout.y]]};var targetTextStyle={x:labelLayout.x,y:labelLayout.y};if(withAnimation){updateProps(labelLine,{shape:targetLineShape},seriesModel,idx);updateProps(labelText,{style:targetTextStyle},seriesModel,idx);}else{labelLine.attr({shape:targetLineShape});labelText.attr({style:targetTextStyle});}labelText.attr({rotation:labelLayout.rotation,origin:[labelLayout.x,labelLayout.y],z2:10});var labelModel=itemModel.getModel('label');var labelHoverModel=itemModel.getModel('emphasis.label');var labelLineModel=itemModel.getModel('labelLine');var labelLineHoverModel=itemModel.getModel('emphasis.labelLine');var visualColor=data.getItemVisual(idx,'color');setLabelStyle(labelText.style,labelText.hoverStyle={},labelModel,labelHoverModel,{labelFetcher:data.hostModel,labelDataIndex:idx,defaultText:labelLayout.text,autoColor:visualColor,useInsideStyle:!!labelLayout.inside},{textAlign:labelLayout.textAlign,textVerticalAlign:labelLayout.verticalAlign,opacity:data.getItemVisual(idx,'opacity')});labelText.ignore=labelText.normalIgnore=!labelModel.get('show');labelText.hoverIgnore=!labelHoverModel.get('show');labelLine.ignore=labelLine.normalIgnore=!labelLineModel.get('show');labelLine.hoverIgnore=!labelLineHoverModel.get('show');// Default use item visual color\nlabelLine.setStyle({stroke:visualColor,opacity:data.getItemVisual(idx,'opacity')});labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());labelLine.hoverStyle=labelLineHoverModel.getModel('lineStyle').getLineStyle();var smooth=labelLineModel.get('smooth');if(smooth&&smooth===true){smooth=0.4;}labelLine.setShape({smooth:smooth});};inherits(PiePiece,Group);// Pie view\nvar PieView=Chart.extend({type:'pie',init:function init(){var sectorGroup=new Group();this._sectorGroup=sectorGroup;},render:function render(seriesModel,ecModel,api,payload){if(payload&&payload.from===this.uid){return;}var data=seriesModel.getData();var oldData=this._data;var group=this.group;var hasAnimation=ecModel.get('animation');var isFirstRender=!oldData;var animationType=seriesModel.get('animationType');var animationTypeUpdate=seriesModel.get('animationTypeUpdate');var onSectorClick=curry(updateDataSelected,this.uid,seriesModel,hasAnimation,api);var selectedMode=seriesModel.get('selectedMode');data.diff(oldData).add(function(idx){var piePiece=new PiePiece(data,idx);// Default expansion animation\nif(isFirstRender&&animationType!=='scale'){piePiece.eachChild(function(child){child.stopAnimation(true);});}selectedMode&&piePiece.on('click',onSectorClick);data.setItemGraphicEl(idx,piePiece);group.add(piePiece);}).update(function(newIdx,oldIdx){var piePiece=oldData.getItemGraphicEl(oldIdx);if(!isFirstRender&&animationTypeUpdate!=='transition'){piePiece.eachChild(function(child){child.stopAnimation(true);});}piePiece.updateData(data,newIdx);piePiece.off('click');selectedMode&&piePiece.on('click',onSectorClick);group.add(piePiece);data.setItemGraphicEl(newIdx,piePiece);}).remove(function(idx){var piePiece=oldData.getItemGraphicEl(idx);group.remove(piePiece);}).execute();if(hasAnimation&&data.count()>0&&(isFirstRender?animationType!=='scale':animationTypeUpdate!=='transition')){var shape=data.getItemLayout(0);for(var s=1;isNaN(shape.startAngle)&&s<data.count();++s){shape=data.getItemLayout(s);}var r=Math.max(api.getWidth(),api.getHeight())/2;var removeClipPath=bind(group.removeClipPath,group);group.setClipPath(this._createClipPath(shape.cx,shape.cy,r,shape.startAngle,shape.clockwise,removeClipPath,seriesModel,isFirstRender));}else{// clipPath is used in first-time animation, so remove it when otherwise. See: #8994\ngroup.removeClipPath();}this._data=data;},dispose:function dispose(){},_createClipPath:function _createClipPath(cx,cy,r,startAngle,clockwise,cb,seriesModel,isFirstRender){var clipPath=new Sector({shape:{cx:cx,cy:cy,r0:0,r:r,startAngle:startAngle,endAngle:startAngle,clockwise:clockwise}});var initOrUpdate=isFirstRender?initProps:updateProps;initOrUpdate(clipPath,{shape:{endAngle:startAngle+(clockwise?1:-1)*Math.PI*2}},seriesModel,cb);return clipPath;},/**\n     * @implement\n     */containPoint:function containPoint(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;}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var createDataSelectAction=function createDataSelectAction(seriesType,actionInfos){each$1(actionInfos,function(actionInfo){actionInfo.update='updateView';/**\n         * @payload\n         * @property {string} seriesName\n         * @property {string} name\n         */registerAction(actionInfo,function(payload,ecModel){var selected={};ecModel.eachComponent({mainType:'series',subType:seriesType,query:payload},function(seriesModel){if(seriesModel[actionInfo.method]){seriesModel[actionInfo.method](payload.name,payload.dataIndex);}var data=seriesModel.getData();// Create selected map\ndata.each(function(idx){var name=data.getName(idx);selected[name]=seriesModel.isSelected(name)||false;});});return{name:payload.name,selected:selected,seriesId:payload.seriesId};});});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Pick color from palette for each data item.\n// Applicable for charts that require applying color palette\n// in data level (like pie, funnel, chord).\nvar dataColor=function dataColor(seriesType){return{getTargetSeries:function getTargetSeries(ecModel){// Pie and funnel may use diferrent scope\nvar paletteScope={};var seiresModelMap=createHashMap();ecModel.eachSeriesByType(seriesType,function(seriesModel){seriesModel.__paletteScope=paletteScope;seiresModelMap.set(seriesModel.uid,seriesModel);});return seiresModelMap;},reset:function reset(seriesModel,ecModel){var dataAll=seriesModel.getRawData();var idxMap={};var data=seriesModel.getData();data.each(function(idx){var rawIdx=data.getRawIndex(idx);idxMap[rawIdx]=idx;});dataAll.each(function(rawIdx){var filteredIdx=idxMap[rawIdx];// If series.itemStyle.normal.color is a function. itemVisual may be encoded\nvar singleDataColor=filteredIdx!=null&&data.getItemVisual(filteredIdx,'color',true);var singleDataBorderColor=filteredIdx!=null&&data.getItemVisual(filteredIdx,'borderColor',true);var itemModel;if(!singleDataColor||!singleDataBorderColor){// FIXME Performance\nitemModel=dataAll.getItemModel(rawIdx);}if(!singleDataColor){var color=itemModel.get('itemStyle.color')||seriesModel.getColorFromPalette(dataAll.getName(rawIdx)||rawIdx+'',seriesModel.__paletteScope,dataAll.count());// Data is not filtered\nif(filteredIdx!=null){data.setItemVisual(filteredIdx,'color',color);}}if(!singleDataBorderColor){var borderColor=itemModel.get('itemStyle.borderColor');// Data is not filtered\nif(filteredIdx!=null){data.setItemVisual(filteredIdx,'borderColor',borderColor);}}});}};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // FIXME emphasis label position is not same with normal label position\nvar RADIAN$1=Math.PI/180;function adjustSingleSide(list,cx,cy,r,dir,viewWidth,viewHeight,viewLeft,viewTop,farthestX){list.sort(function(a,b){return a.y-b.y;});function shiftDown(start,end,delta,dir){for(var j=start;j<end;j++){if(list[j].y+delta>viewTop+viewHeight){break;}list[j].y+=delta;if(j>start&&j+1<end&&list[j+1].y>list[j].y+list[j].height){shiftUp(j,delta/2);return;}}shiftUp(end-1,delta/2);}function shiftUp(end,delta){for(var j=end;j>=0;j--){if(list[j].y-delta<viewTop){break;}list[j].y-=delta;if(j>0&&list[j].y>list[j-1].y+list[j-1].height){break;}}}function changeX(list,isDownList,cx,cy,r,dir){var lastDeltaX=dir>0?isDownList// right-side\n?Number.MAX_VALUE// down\n:0// up\n:isDownList// left-side\n?Number.MAX_VALUE// down\n:0;// up\nfor(var i=0,l=list.length;i<l;i++){if(list[i].labelAlignTo!=='none'){continue;}var deltaY=Math.abs(list[i].y-cy);var length=list[i].len;var length2=list[i].len2;var deltaX=deltaY<r+length?Math.sqrt((r+length+length2)*(r+length+length2)-deltaY*deltaY):Math.abs(list[i].x-cx);if(isDownList&&deltaX>=lastDeltaX){// right-down, left-down\ndeltaX=lastDeltaX-10;}if(!isDownList&&deltaX<=lastDeltaX){// right-up, left-up\ndeltaX=lastDeltaX+10;}list[i].x=cx+deltaX*dir;lastDeltaX=deltaX;}}var lastY=0;var delta;var len=list.length;var upList=[];var downList=[];for(var i=0;i<len;i++){if(list[i].position==='outer'&&list[i].labelAlignTo==='labelLine'){var dx=list[i].x-farthestX;list[i].linePoints[1][0]+=dx;list[i].x=farthestX;}delta=list[i].y-lastY;if(delta<0){shiftDown(i,len,-delta,dir);}lastY=list[i].y+list[i].height;}if(viewHeight-lastY<0){shiftUp(len-1,lastY-viewHeight);}for(var i=0;i<len;i++){if(list[i].y>=cy){downList.push(list[i]);}else{upList.push(list[i]);}}changeX(upList,false,cx,cy,r,dir);changeX(downList,true,cx,cy,r,dir);}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++){if(isPositionCenter(labelLayoutList[i])){continue;}if(labelLayoutList[i].x<cx){leftmostX=Math.min(leftmostX,labelLayoutList[i].x);leftList.push(labelLayoutList[i]);}else{rightmostX=Math.max(rightmostX,labelLayoutList[i].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];if(isPositionCenter(layout)){continue;}var linePoints=layout.linePoints;if(linePoints){var isAlignToEdge=layout.labelAlignTo==='edge';var realTextWidth=layout.textRect.width;var targetTextWidth;if(isAlignToEdge){if(layout.x<cx){targetTextWidth=linePoints[2][0]-layout.labelDistance-viewLeft-layout.labelMargin;}else{targetTextWidth=viewLeft+viewWidth-layout.labelMargin-linePoints[2][0]-layout.labelDistance;}}else{if(layout.x<cx){targetTextWidth=layout.x-viewLeft-layout.bleedMargin;}else{targetTextWidth=viewLeft+viewWidth-layout.x-layout.bleedMargin;}}if(targetTextWidth<layout.textRect.width){layout.text=truncateText(layout.text,targetTextWidth,layout.font);if(layout.labelAlignTo==='edge'){realTextWidth=getWidth(layout.text,layout.font);}}var dist=linePoints[1][0]-linePoints[2][0];if(isAlignToEdge){if(layout.x<cx){linePoints[2][0]=viewLeft+layout.labelMargin+realTextWidth+layout.labelDistance;}else{linePoints[2][0]=viewLeft+viewWidth-layout.labelMargin-realTextWidth-layout.labelDistance;}}else{if(layout.x<cx){linePoints[2][0]=layout.x+layout.labelDistance;}else{linePoints[2][0]=layout.x-layout.labelDistance;}linePoints[1][0]=linePoints[2][0]+dist;}linePoints[1][1]=linePoints[2][1]=layout.y;}}}function isPositionCenter(layout){// Not change x for center label\nreturn layout.position==='center';}var labelLayout=function labelLayout(seriesModel,r,viewWidth,viewHeight,viewLeft,viewTop){var data=seriesModel.getData();var labelLayoutList=[];var cx;var cy;var hasLabelRotate=false;var minShowLabelRadian=(seriesModel.get('minShowLabelAngle')||0)*RADIAN$1;data.each(function(idx){var layout=data.getItemLayout(idx);var itemModel=data.getItemModel(idx);var labelModel=itemModel.getModel('label');// Use position in normal or emphasis\nvar labelPosition=labelModel.get('position')||itemModel.get('emphasis.label.position');var labelDistance=labelModel.get('distanceToLabelLine');var labelAlignTo=labelModel.get('alignTo');var labelMargin=parsePercent$1(labelModel.get('margin'),viewWidth);var bleedMargin=labelModel.get('bleedMargin');var font=labelModel.getFont();var labelLineModel=itemModel.getModel('labelLine');var labelLineLen=labelLineModel.get('length');labelLineLen=parsePercent$1(labelLineLen,viewWidth);var labelLineLen2=labelLineModel.get('length2');labelLineLen2=parsePercent$1(labelLineLen2,viewWidth);if(layout.angle<minShowLabelRadian){return;}var midAngle=(layout.startAngle+layout.endAngle)/2;var dx=Math.cos(midAngle);var dy=Math.sin(midAngle);var textX;var textY;var linePoints;var textAlign;cx=layout.cx;cy=layout.cy;var text=seriesModel.getFormattedLabel(idx,'normal')||data.getName(idx);var textRect=_getBoundingRect(text,font,textAlign,'top');var isLabelInside=labelPosition==='inside'||labelPosition==='inner';if(labelPosition==='center'){textX=layout.cx;textY=layout.cy;textAlign='center';}else{var x1=(isLabelInside?(layout.r+layout.r0)/2*dx:layout.r*dx)+cx;var y1=(isLabelInside?(layout.r+layout.r0)/2*dy:layout.r*dy)+cy;textX=x1+dx*3;textY=y1+dy*3;if(!isLabelInside){// For roseType\nvar x2=x1+dx*(labelLineLen+r-layout.r);var y2=y1+dy*(labelLineLen+r-layout.r);var x3=x2+(dx<0?-1:1)*labelLineLen2;var y3=y2;if(labelAlignTo==='edge'){// Adjust textX because text align of edge is opposite\ntextX=dx<0?viewLeft+labelMargin:viewLeft+viewWidth-labelMargin;}else{textX=x3+(dx<0?-labelDistance:labelDistance);}textY=y3;linePoints=[[x1,y1],[x2,y2],[x3,y3]];}textAlign=isLabelInside?'center':labelAlignTo==='edge'?dx>0?'right':'left':dx>0?'left':'right';}var labelRotate;var rotate=labelModel.get('rotate');if(typeof rotate==='number'){labelRotate=rotate*(Math.PI/180);}else{labelRotate=rotate?dx<0?-midAngle+Math.PI:-midAngle:0;}hasLabelRotate=!!labelRotate;layout.label={x:textX,y:textY,position:labelPosition,height:textRect.height,len:labelLineLen,len2:labelLineLen2,linePoints:linePoints,textAlign:textAlign,verticalAlign:'middle',rotation:labelRotate,inside:isLabelInside,labelDistance:labelDistance,labelAlignTo:labelAlignTo,labelMargin:labelMargin,bleedMargin:bleedMargin,textRect:textRect,text:text,font:font};// Not layout the inside label\nif(!isLabelInside){labelLayoutList.push(layout.label);}});if(!hasLabelRotate&&seriesModel.get('avoidLabelOverlap')){avoidOverlap(labelLayoutList,cx,cy,r,viewWidth,viewHeight,viewLeft,viewTop);}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var PI2$4=Math.PI*2;var RADIAN=Math.PI/180;function getViewRect(seriesModel,api){return getLayoutRect(seriesModel.getBoxLayoutParams(),{width:api.getWidth(),height:api.getHeight()});}var pieLayout=function pieLayout(seriesType,ecModel,api,payload){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$1(viewRect.width,api.getWidth());var height=parsePercent$1(viewRect.height,api.getHeight());var size=Math.min(width,height);var cx=parsePercent$1(center[0],width)+viewRect.x;var cy=parsePercent$1(center[1],height)+viewRect.y;var r0=parsePercent$1(radius[0],size/2);var r=parsePercent$1(radius[1],size/2);var startAngle=-seriesModel.get('startAngle')*RADIAN;var minAngle=seriesModel.get('minAngle')*RADIAN;var validDataCount=0;data.each(valueDim,function(value){!isNaN(value)&&validDataCount++;});var sum=data.getSum(valueDim);// Sum may be 0\nvar unitRadian=Math.PI/(sum||validDataCount)*2;var clockwise=seriesModel.get('clockwise');var roseType=seriesModel.get('roseType');var stillShowZeroSum=seriesModel.get('stillShowZeroSum');// [0...max]\nvar extent=data.getDataExtent(valueDim);extent[0]=0;// In the case some sector angle is smaller than minAngle\nvar restAngle=PI2$4;var valueSumLargerThanMinAngle=0;var currentAngle=startAngle;var dir=clockwise?1:-1;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,viewRect:viewRect});return;}// FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样？\nif(roseType!=='area'){angle=sum===0&&stillShowZeroSum?unitRadian:value*unitRadian;}else{angle=PI2$4/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,viewRect:viewRect});currentAngle=endAngle;});// Some sector is constrained by minAngle\n// Rest sectors needs recalculate angle\nif(restAngle<PI2$4&&validDataCount){// Average the angle if rest angle is not enough after all angles is\n// Constrained by minAngle\nif(restAngle<=1e-3){var angle=PI2$4/validDataCount;data.each(valueDim,function(value,idx){if(!isNaN(value)){var layout=data.getItemLayout(idx);layout.angle=angle;layout.startAngle=startAngle+dir*idx*angle;layout.endAngle=startAngle+dir*(idx+1)*angle;}});}else{unitRadian=restAngle/valueSumLargerThanMinAngle;currentAngle=startAngle;data.each(valueDim,function(value,idx){if(!isNaN(value)){var layout=data.getItemLayout(idx);var angle=layout.angle===minAngle?minAngle:value*unitRadian;layout.startAngle=currentAngle;layout.endAngle=currentAngle+dir*angle;currentAngle+=dir*angle;}});}}labelLayout(seriesModel,r,viewRect.width,viewRect.height,viewRect.x,viewRect.y);});};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var dataFilter=function dataFilter(seriesType){return{seriesType:seriesType,reset:function reset(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);// If in any legend component the status is not selected.\nfor(var i=0;i<legendModels.length;i++){if(!legendModels[i].isSelected(name)){return false;}}return true;});}};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/createDataSelectAction('pie',[{type:'pieToggleSelect',event:'pieselectchanged',method:'toggleSelected'},{type:'pieSelect',event:'pieselected',method:'select'},{type:'pieUnSelect',event:'pieunselected',method:'unSelect'}]);registerVisual(dataColor('pie'));registerLayout(curry(pieLayout,'pie'));registerProcessor(dataFilter('pie'));/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/SeriesModel.extend({type:'series.scatter',dependencies:['grid','polar','geo','singleAxis','calendar'],getInitialData:function getInitialData(option,ecModel){return createListFromArray(this.getSource(),this,{useEncodeDefaulter:true});},brushSelector:'point',getProgressive:function getProgressive(){var progressive=this.option.progressive;if(progressive==null){// PENDING\nreturn this.option.large?5e3:this.get('progressive');}return progressive;},getProgressiveThreshold:function getProgressiveThreshold(){var progressiveThreshold=this.option.progressiveThreshold;if(progressiveThreshold==null){// PENDING\nreturn this.option.large?1e4:this.get('progressiveThreshold');}return progressiveThreshold;},defaultOption:{coordinateSystem:'cartesian2d',zlevel:0,z:2,legendHoverLink:true,hoverAnimation:true,// Cartesian coordinate system\n// xAxisIndex: 0,\n// yAxisIndex: 0,\n// Polar coordinate system\n// polarIndex: 0,\n// Geo coordinate system\n// geoIndex: 0,\n// symbol: null,        // 图形类型\nsymbolSize:10,// 图形大小，半宽（半径）参数，当图形为方向或菱形则总宽度为symbolSize * 2\n// symbolRotate: null,  // 图形旋转控制\nlarge:false,// Available when large is true\nlargeThreshold:2000,// cursor: null,\n// label: {\n// show: false\n// distance: 5,\n// formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调\n// position: 默认自适应，水平布局为'top'，垂直布局为'right'，可选为\n//           'inside'|'left'|'right'|'top'|'bottom'\n// 默认使用全局文本样式，详见TEXTSTYLE\n// },\nitemStyle:{opacity:0.8// color: 各异\n},// If clip the overflow graphics\n// Works on cartesian / polar series\nclip:true// progressive: null\n}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /* global Float32Array */ // TODO Batch by color\nvar BOOST_SIZE_THRESHOLD=4;var LargeSymbolPath=extendShape({shape:{points:null},symbolProxy:null,softClipShape:null,buildPath:function buildPath(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;// Do draw in afterBrush.\nif(canBoost){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;}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);}},afterBrush:function afterBrush(ctx){var shape=this.shape;var points=shape.points;var size=shape.size;var canBoost=size[0]<BOOST_SIZE_THRESHOLD;if(!canBoost){return;}this.setTransform(ctx);// PENDING If style or other canvas status changed?\nfor(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;}// fillRect is faster than building a rect path and draw.\n// And it support light globalCompositeOperation.\nctx.fillRect(x-size[0]/2,y-size[1]/2,size[0],size[1]);}this.restoreTransform(ctx);},findDataIndex:function findDataIndex(x,y){// TODO ???\n// Consider transform\nvar 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);// Not consider transform\n// Treat each element as a rect\n// top down traverse\nfor(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;}});function LargeSymbolDraw(){this.group=new Group();}var largeSymbolProto=LargeSymbolDraw.prototype;largeSymbolProto.isPersistent=function(){return!this._incremental;};/**\n * Update symbols draw by new data\n * @param {module:echarts/data/List} data\n * @param {Object} opt\n * @param {Object} [opt.clipShape]\n */largeSymbolProto.updateData=function(data,opt){this.group.removeAll();var symbolEl=new LargeSymbolPath({rectHover:true,cursor:'default'});symbolEl.setShape({points:data.getLayout('symbolPoints')});this._setCommon(symbolEl,data,false,opt);this.group.add(symbolEl);this._incremental=null;};largeSymbolProto.updateLayout=function(data){if(this._incremental){return;}var points=data.getLayout('symbolPoints');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);});};largeSymbolProto.incrementalPrepareUpdate=function(data){this.group.removeAll();this._clearIncremental();// Only use incremental displayables when data amount is larger than 2 million.\n// PENDING Incremental data?\nif(data.count()>2e6){if(!this._incremental){this._incremental=new IncrementalDisplayble({silent:true});}this.group.add(this._incremental);}else{this._incremental=null;}};largeSymbolProto.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('symbolPoints')});this._setCommon(symbolEl,data,!!this._incremental,opt);};largeSymbolProto._setCommon=function(symbolEl,data,isIncremental,opt){var hostModel=data.hostModel;opt=opt||{};// TODO\n// if (data.hasItemVisual.symbolSize) {\n//     // TODO typed array?\n//     symbolEl.setShape('sizes', data.mapArray(\n//         function (idx) {\n//             var size = data.getItemVisual(idx, 'symbolSize');\n//             return (size instanceof Array) ? size : [size, size];\n//         }\n//     ));\n// }\n// else {\nvar size=data.getVisual('symbolSize');symbolEl.setShape('size',size instanceof Array?size:[size,size]);// }\nsymbolEl.softClipShape=opt.clipShape||null;// Create symbolProxy to build path for each data\nsymbolEl.symbolProxy=createSymbol(data.getVisual('symbol'),0,0,0,0);// Use symbolProxy setColor method\nsymbolEl.setColor=symbolEl.symbolProxy.setColor;var extrudeShadow=symbolEl.shape.size[0]<BOOST_SIZE_THRESHOLD;symbolEl.useStyle(// Draw shadow when doing fillRect is extremely slow.\nhostModel.getModel('itemStyle').getItemStyle(extrudeShadow?['color','shadowBlur','shadowColor']:['color']));var visualColor=data.getVisual('color');if(visualColor){symbolEl.setColor(visualColor);}if(!isIncremental){// Enable tooltip\n// PENDING May have performance issue when path is extremely large\nsymbolEl.seriesIndex=hostModel.seriesIndex;symbolEl.on('mousemove',function(e){symbolEl.dataIndex=null;var dataIndex=symbolEl.findDataIndex(e.offsetX,e.offsetY);if(dataIndex>=0){// Provide dataIndex for tooltip\nsymbolEl.dataIndex=dataIndex+(symbolEl.startIndex||0);}});}};largeSymbolProto.remove=function(){this._clearIncremental();this._incremental=null;this.group.removeAll();};largeSymbolProto._clearIncremental=function(){var incremental=this._incremental;if(incremental){incremental.clearDisplaybles();}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/extendChartView({type:'scatter',render:function render(seriesModel,ecModel,api){var data=seriesModel.getData();var symbolDraw=this._updateSymbolDraw(data,seriesModel);symbolDraw.updateData(data,{// TODO\n// If this parameter should be a shape or a bounding volume\n// shape will be more general.\n// But bounding volume like bounding rect will be much faster in the contain calculation\nclipShape:this._getClipShape(seriesModel)});this._finished=true;},incrementalPrepareRender:function incrementalPrepareRender(seriesModel,ecModel,api){var data=seriesModel.getData();var symbolDraw=this._updateSymbolDraw(data,seriesModel);symbolDraw.incrementalPrepareUpdate(data);this._finished=false;},incrementalRender:function incrementalRender(taskParams,seriesModel,ecModel){this._symbolDraw.incrementalUpdate(taskParams,seriesModel.getData(),{clipShape:this._getClipShape(seriesModel)});this._finished=taskParams.end===seriesModel.getData().count();},updateTransform:function updateTransform(seriesModel,ecModel,api){var data=seriesModel.getData();// Must mark group dirty and make sure the incremental layer will be cleared\n// PENDING\nthis.group.dirty();if(!this._finished||data.count()>1e4||!this._symbolDraw.isPersistent()){return{update:true};}else{var res=pointsLayout().reset(seriesModel);if(res.progress){res.progress({start:0,end:data.count()},data);}this._symbolDraw.updateLayout(data);}},_getClipShape:function _getClipShape(seriesModel){var coordSys=seriesModel.coordinateSystem;var clipArea=coordSys&&coordSys.getArea&&coordSys.getArea();return seriesModel.get('clip',true)?clipArea:null;},_updateSymbolDraw:function _updateSymbolDraw(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;},remove:function remove(ecModel,api){this._symbolDraw&&this._symbolDraw.remove(true);this._symbolDraw=null;},dispose:function dispose(){}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // import * as zrUtil from 'zrender/src/core/util';\n// In case developer forget to include grid component\nregisterVisual(visualSymbol('scatter','circle'));registerLayout(pointsLayout('scatter'));// echarts.registerProcessor(function (ecModel, api) {\n//     ecModel.eachSeriesByType('scatter', function (seriesModel) {\n//         var data = seriesModel.getData();\n//         var coordSys = seriesModel.coordinateSystem;\n//         if (coordSys.type !== 'geo') {\n//             return;\n//         }\n//         var startPt = coordSys.pointToData([0, 0]);\n//         var endPt = coordSys.pointToData([api.getWidth(), api.getHeight()]);\n//         var dims = zrUtil.map(coordSys.dimensions, function (dim) {\n//             return data.mapDimension(dim);\n//         });\n//         var range = {};\n//         range[dims[0]] = [Math.min(startPt[0], endPt[0]), Math.max(startPt[0], endPt[0])];\n//         range[dims[1]] = [Math.min(startPt[1], endPt[1]), Math.max(startPt[1], endPt[1])];\n//         data.selectRange(range);\n//     });\n// });\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var _nonShapeGraphicElements={// Reserved but not supported in graphic component.\npath:null,compoundPath:null,// Supported in graphic component.\ngroup:Group,image:ZImage,text:Text};// -------------\n// Preprocessor\n// -------------\nregisterPreprocessor(function(option){var graphicOption=option.graphic;// Convert\n// {graphic: [{left: 10, type: 'circle'}, ...]}\n// or\n// {graphic: {left: 10, type: 'circle'}}\n// to\n// {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]}\nif(isArray(graphicOption)){if(!graphicOption[0]||!graphicOption[0].elements){option.graphic=[{elements:graphicOption}];}else{// Only one graphic instance can be instantiated. (We dont\n// want that too many views are created in echarts._viewMap)\noption.graphic=[option.graphic[0]];}}else if(graphicOption&&!graphicOption.elements){option.graphic=[{elements:[graphicOption]}];}});// ------\n// Model\n// ------\nvar GraphicModel=extendComponentModel({type:'graphic',defaultOption:{// Extra properties for each elements:\n//\n// left/right/top/bottom: (like 12, '22%', 'center', default undefined)\n//      If left/rigth is set, shape.x/shape.cx/position will not be used.\n//      If top/bottom is set, shape.y/shape.cy/position will not be used.\n//      This mechanism is useful when you want to position a group/element\n//      against the right side or the center of this container.\n//\n// width/height: (can only be pixel value, default 0)\n//      Only be used to specify contianer(group) size, if needed. And\n//      can not be percentage value (like '33%'). See the reason in the\n//      layout algorithm below.\n//\n// bounding: (enum: 'all' (default) | 'raw')\n//      Specify how to calculate boundingRect when locating.\n//      'all': Get uioned and transformed boundingRect\n//          from both itself and its descendants.\n//          This mode simplies confining a group of elements in the bounding\n//          of their ancester container (e.g., using 'right: 0').\n//      'raw': Only use the boundingRect of itself and before transformed.\n//          This mode is similar to css behavior, which is useful when you\n//          want an element to be able to overflow its container. (Consider\n//          a rotated circle needs to be located in a corner.)\n// info: custom info. enables user to mount some info on elements and use them\n//      in event handlers. Update them only when user specified, otherwise, remain.\n// Note: elements is always behind its ancestors in this elements array.\nelements:[],parentId:null},/**\n     * Save el options for the sake of the performance (only update modified graphics).\n     * The order is the same as those in option. (ancesters -> descendants)\n     *\n     * @private\n     * @type {Array.<Object>}\n     */_elOptionsToUpdate:null,/**\n     * @override\n     */mergeOption:function mergeOption(option){// Prevent default merge to elements\nvar elements=this.option.elements;this.option.elements=null;GraphicModel.superApply(this,'mergeOption',arguments);this.option.elements=elements;},/**\n     * @override\n     */optionUpdated:function optionUpdated(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);var mappingResult=mappingToExists(existList,flattenedList);makeIdAndName(mappingResult);// Clear elOptionsToUpdate\nvar elOptionsToUpdate=this._elOptionsToUpdate=[];each$1(mappingResult,function(resultItem,index){var newElOption=resultItem.option;if(__DEV__){assert$1(isObject$1(newElOption)||resultItem.exist,'Empty graphic option definition');}if(!newElOption){return;}elOptionsToUpdate.push(newElOption);setKeyInfoToNewElOption(resultItem,newElOption);mergeNewElOptionToExist(existList,index,newElOption);setLayoutInfoToExist(existList[index],newElOption);},this);// Clean\nfor(var i=existList.length-1;i>=0;i--){if(existList[i]==null){existList.splice(i,1);}else{// $action should be volatile, otherwise option gotten from\n// `getOption` will contain unexpected $action.\ndelete existList[i].$action;}}},/**\n     * Convert\n     * [{\n     *  type: 'group',\n     *  id: 'xx',\n     *  children: [{type: 'circle'}, {type: 'polygon'}]\n     * }]\n     * to\n     * [\n     *  {type: 'group', id: 'xx'},\n     *  {type: 'circle', parentId: 'xx'},\n     *  {type: 'polygon', parentId: 'xx'}\n     * ]\n     *\n     * @private\n     * @param {Array.<Object>} optionList option list\n     * @param {Array.<Object>} result result of flatten\n     * @param {Object} parentOption parent option\n     */_flatten:function _flatten(optionList,result,parentOption){each$1(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);}// Deleting for JSON output, and for not affecting group creation.\ndelete option.children;},this);},// FIXME\n// Pass to view using payload? setOption has a payload?\nuseElOptionsToUpdate:function useElOptionsToUpdate(){var els=this._elOptionsToUpdate;// Clear to avoid render duplicately when zooming.\nthis._elOptionsToUpdate=null;return els;}});// -----\n// View\n// -----\nextendComponentView({type:'graphic',/**\n     * @override\n     */init:function init(ecModel,api){/**\n         * @private\n         * @type {module:zrender/core/util.HashMap}\n         */this._elMap=createHashMap();/**\n         * @private\n         * @type {module:echarts/graphic/GraphicModel}\n         */this._lastGraphicModel;},/**\n     * @override\n     */render:function render(graphicModel,ecModel,api){// Having leveraged between use cases and algorithm complexity, a very\n// simple layout mechanism is used:\n// The size(width/height) can be determined by itself or its parent (not\n// implemented yet), but can not by its children. (Top-down travel)\n// The location(x/y) can be determined by the bounding rect of itself\n// (can including its descendants or not) and the size of its parent.\n// (Bottom-up travel)\n// When `chart.clear()` or `chart.setOption({...}, true)` with the same id,\n// view will be reused.\nif(graphicModel!==this._lastGraphicModel){this._clear();}this._lastGraphicModel=graphicModel;this._updateElements(graphicModel);this._relocate(graphicModel,api);},/**\n     * Update graphic elements.\n     *\n     * @private\n     * @param {Object} graphicModel graphic model\n     */_updateElements:function _updateElements(graphicModel){var elOptionsToUpdate=graphicModel.useElOptionsToUpdate();if(!elOptionsToUpdate){return;}var elMap=this._elMap;var rootGroup=this.group;// Top-down tranverse to assign graphic settings to each elements.\neach$1(elOptionsToUpdate,function(elOption){var $action=elOption.$action;var id=elOption.id;var existEl=elMap.get(id);var parentId=elOption.parentId;var targetElParent=parentId!=null?elMap.get(parentId):rootGroup;var elOptionStyle=elOption.style;if(elOption.type==='text'&&elOptionStyle){// In top/bottom mode, textVerticalAlign should not be used, which cause\n// inaccurately locating.\nif(elOption.hv&&elOption.hv[1]){elOptionStyle.textVerticalAlign=elOptionStyle.textBaseline=null;}// Compatible with previous setting: both support fill and textFill,\n// stroke and textStroke.\n!elOptionStyle.hasOwnProperty('textFill')&&elOptionStyle.fill&&(elOptionStyle.textFill=elOptionStyle.fill);!elOptionStyle.hasOwnProperty('textStroke')&&elOptionStyle.stroke&&(elOptionStyle.textStroke=elOptionStyle.stroke);}// Remove unnecessary props to avoid potential problems.\nvar elOptionCleaned=getCleanedElOption(elOption);// For simple, do not support parent change, otherwise reorder is needed.\nif(__DEV__){existEl&&assert$1(targetElParent===existEl.parent,'Changing parent is not supported.');}if(!$action||$action==='merge'){existEl?existEl.attr(elOptionCleaned):createEl(id,targetElParent,elOptionCleaned,elMap);}else if($action==='replace'){removeEl(existEl,elMap);createEl(id,targetElParent,elOptionCleaned,elMap);}else if($action==='remove'){removeEl(existEl,elMap);}var el=elMap.get(id);if(el){el.__ecGraphicWidthOption=elOption.width;el.__ecGraphicHeightOption=elOption.height;setEventData(el,graphicModel,elOption);}});},/**\n     * Locate graphic elements.\n     *\n     * @private\n     * @param {Object} graphicModel graphic model\n     * @param {module:echarts/ExtensionAPI} api extension API\n     */_relocate:function _relocate(graphicModel,api){var elOptions=graphicModel.option.elements;var rootGroup=this.group;var elMap=this._elMap;var apiWidth=api.getWidth();var apiHeight=api.getHeight();// Top-down to calculate percentage width/height of group\nfor(var i=0;i<elOptions.length;i++){var elOption=elOptions[i];var el=elMap.get(elOption.id);if(!el||!el.isGroup){continue;}var parentEl=el.parent;var isParentRoot=parentEl===rootGroup;// Like 'position:absolut' in css, default 0.\nel.__ecGraphicWidth=parsePercent$1(el.__ecGraphicWidthOption,isParentRoot?apiWidth:parentEl.__ecGraphicWidth)||0;el.__ecGraphicHeight=parsePercent$1(el.__ecGraphicHeightOption,isParentRoot?apiHeight:parentEl.__ecGraphicHeight)||0;}// Bottom-up tranvese all elements (consider ec resize) to locate elements.\nfor(var i=elOptions.length-1;i>=0;i--){var elOption=elOptions[i];var el=elMap.get(elOption.id);if(!el){continue;}var parentEl=el.parent;var containerInfo=parentEl===rootGroup?{width:apiWidth,height:apiHeight}:{width:parentEl.__ecGraphicWidth,height:parentEl.__ecGraphicHeight};// PENDING\n// Currently, when `bounding: 'all'`, the union bounding rect of the group\n// does not include the rect of [0, 0, group.width, group.height], which\n// is probably weird for users. Should we make a break change for it?\npositionElement(el,elOption,containerInfo,null,{hv:elOption.hv,boundingMode:elOption.bounding});}},/**\n     * Clear all elements.\n     *\n     * @private\n     */_clear:function _clear(){var elMap=this._elMap;elMap.each(function(el){removeEl(el,elMap);});this._elMap=createHashMap();},/**\n     * @override\n     */dispose:function dispose(){this._clear();}});function createEl(id,targetElParent,elOption,elMap){var graphicType=elOption.type;if(__DEV__){assert$1(graphicType,'graphic type MUST be set');}var Clz=_nonShapeGraphicElements.hasOwnProperty(graphicType)// Those graphic elements are not shapes. They should not be\n// overwritten by users, so do them first.\n?_nonShapeGraphicElements[graphicType]:getShapeClass(graphicType);if(__DEV__){assert$1(Clz,'graphic type can not be found');}var el=new Clz(elOption);targetElParent.add(el);elMap.set(id,el);el.__ecGraphicId=id;}function removeEl(existEl,elMap){var existElParent=existEl&&existEl.parent;if(existElParent){existEl.type==='group'&&existEl.traverse(function(el){removeEl(el,elMap);});elMap.removeKey(existEl.__ecGraphicId);existElParent.remove(existEl);}}// Remove unnecessary props to avoid potential problems.\nfunction getCleanedElOption(elOption){elOption=extend({},elOption);each$1(['id','parentId','$action','hv','bounding'].concat(LOCATION_PARAMS),function(name){delete elOption[name];});return elOption;}function isSetLoc(obj,props){var isSet;each$1(props,function(prop){obj[prop]!=null&&obj[prop]!=='auto'&&(isSet=true);});return isSet;}function setKeyInfoToNewElOption(resultItem,newElOption){var existElOption=resultItem.exist;// Set id and type after id assigned.\nnewElOption.id=resultItem.keyInfo.id;!newElOption.type&&existElOption&&(newElOption.type=existElOption.type);// Set parent id if not specified\nif(newElOption.parentId==null){var newElParentOption=newElOption.parentOption;if(newElParentOption){newElOption.parentId=newElParentOption.id;}else if(existElOption){newElOption.parentId=existElOption.parentId;}}// Clear\nnewElOption.parentOption=null;}function mergeNewElOptionToExist(existList,index,newElOption){// Update existing options, for `getOption` feature.\nvar newElOptCopy=extend({},newElOption);var existElOption=existList[index];var $action=newElOption.$action||'merge';if($action==='merge'){if(existElOption){if(__DEV__){var newType=newElOption.type;assert$1(!newType||existElOption.type===newType,'Please set $action: \"replace\" to change `type`');}// We can ensure that newElOptCopy and existElOption are not\n// the same object, so `merge` will not change newElOptCopy.\nmerge(existElOption,newElOptCopy,true);// Rigid body, use ignoreSize.\nmergeLayoutParam(existElOption,newElOptCopy,{ignoreSize:true});// Will be used in render.\ncopyLayoutParams(newElOption,existElOption);}else{existList[index]=newElOptCopy;}}else if($action==='replace'){existList[index]=newElOptCopy;}else if($action==='remove'){// null will be cleaned later.\nexistElOption&&(existList[index]=null);}}function setLayoutInfoToExist(existItem,newElOption){if(!existItem){return;}existItem.hv=newElOption.hv=[// Rigid body, dont care `width`.\nisSetLoc(newElOption,['left','right']),// Rigid body, dont care `height`.\nisSetLoc(newElOption,['top','bottom'])];// Give default group size. Otherwise layout error may occur.\nif(existItem.type==='group'){existItem.width==null&&(existItem.width=newElOption.width=0);existItem.height==null&&(existItem.height=newElOption.height=0);}}function setEventData(el,graphicModel,elOption){var eventData=el.eventData;// Simple optimize for large amount of elements that no need event.\nif(!el.silent&&!el.ignore&&!eventData){eventData=el.eventData={componentType:'graphic',componentIndex:graphicModel.componentIndex,name:el.name};}// `elOption.info` enables user to mount some info on\n// elements and use them in event handlers.\nif(eventData){eventData.info=el.info;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {Object} finder contains {seriesIndex, dataIndex, dataIndexInside}\n * @param {module:echarts/model/Global} ecModel\n * @return {Object} {point: [x, y], el: ...} point Will not be null.\n */var findPointFromSeries=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){point=coordSys.dataToPoint(data.getValues(map(coordSys.dimensions,function(dim){return data.mapDimension(dim);}),dataIndex,true))||[];}else if(el){// Use graphic bounding rect\nvar rect=el.getBoundingRect().clone();rect.applyTransform(el.transform);point=[rect.x+rect.width/2,rect.y+rect.height/2];}return{point:point,el:el};};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$7=each$1;var curry$2=curry;var inner$7=makeInner();/**\n * Basic logic: check all axis, if they do not demand show/highlight,\n * then hide/downplay them.\n *\n * @param {Object} coordSysAxesInfo\n * @param {Object} payload\n * @param {string} [payload.currTrigger] 'click' | 'mousemove' | 'leave'\n * @param {Array.<number>} [payload.x] x and y, which are mandatory, specify a point to\n *              trigger axisPointer and tooltip.\n * @param {Array.<number>} [payload.y] x and y, which are mandatory, specify a point to\n *              trigger axisPointer and tooltip.\n * @param {Object} [payload.seriesIndex] finder, optional, restrict target axes.\n * @param {Object} [payload.dataIndex] finder, restrict target axes.\n * @param {Object} [payload.axesInfo] finder, restrict target axes.\n *        [{\n *          axisDim: 'x'|'y'|'angle'|...,\n *          axisIndex: ...,\n *          value: ...\n *        }, ...]\n * @param {Function} [payload.dispatchAction]\n * @param {Object} [payload.tooltipOption]\n * @param {Object|Array.<number>|Function} [payload.position] Tooltip position,\n *        which can be specified in dispatchAction\n * @param {module:echarts/model/Global} ecModel\n * @param {module:echarts/ExtensionAPI} api\n * @return {Object} content of event obj for echarts.connect.\n */var axisTrigger=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;// Pending\n// See #6121. But we are not able to reproduce it yet.\nif(!coordSysAxesInfo){return;}if(illegalPoint(point)){// Used in the default behavior of `connection`: use the sample seriesIndex\n// and dataIndex. And also used in the tooltipView trigger.\npoint=findPointFromSeries({seriesIndex:finder.seriesIndex,// Do not use dataIndexInside from other ec instance.\n// FIXME: auto detect it?\ndataIndex:finder.dataIndex},ecModel).point;}var isIllegalPoint=illegalPoint(point);// Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}).\n// Notice: In this case, it is difficult to get the `point` (which is necessary to show\n// tooltip, so if point is not given, we just use the point found by sample seriesIndex\n// and dataIndex.\nvar inputAxesInfo=finder.axesInfo;var axesInfo=coordSysAxesInfo.axesInfo;var shouldHide=currTrigger==='leave'||illegalPoint(point);var outputFinder={};var showValueMap={};var dataByCoordSys={list:[],map:{}};var updaters={showPointer:curry$2(showPointer,showValueMap),showTooltip:curry$2(showTooltip,dataByCoordSys)};// Process for triggered axes.\neach$7(coordSysAxesInfo.coordSysMap,function(coordSys,coordSysKey){// If a point given, it must be contained by the coordinate system.\nvar coordSysContainsPoint=isIllegalPoint||coordSys.containPoint(point);each$7(coordSysAxesInfo.coordSysAxesInfo[coordSysKey],function(axisInfo,key){var axis=axisInfo.axis;var inputAxisInfo=findInputAxisInfo(inputAxesInfo,axisInfo);// If no inputAxesInfo, no axis is restricted.\nif(!shouldHide&&coordSysContainsPoint&&(!inputAxesInfo||inputAxisInfo)){var val=inputAxisInfo&&inputAxisInfo.value;if(val==null&&!isIllegalPoint){val=axis.pointToData(point);}val!=null&&processOnAxis(axisInfo,val,updaters,false,outputFinder);}});});// Process for linked axes.\nvar linkTriggers={};each$7(axesInfo,function(tarAxisInfo,tarKey){var linkGroup=tarAxisInfo.linkGroup;// If axis has been triggered in the previous stage, it should not be triggered by link.\nif(linkGroup&&!showValueMap[tarKey]){each$7(linkGroup.axesInfo,function(srcAxisInfo,srcKey){var srcValItem=showValueMap[srcKey];// If srcValItem exist, source axis is triggered, so link to target axis.\nif(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$7(linkTriggers,function(val,tarKey){processOnAxis(axesInfo[tarKey],val,updaters,true,outputFinder);});updateModelActually(showValueMap,axesInfo,outputFinder);dispatchTooltipActually(dataByCoordSys,point,payload,dispatchAction);dispatchHighDownActually(axesInfo,dispatchAction,api);return outputFinder;};function processOnAxis(axisInfo,newValue,updaters,dontSnap,outputFinder){var axis=axisInfo.axis;if(axis.scale.isBlank()||!axis.containData(newValue)){return;}if(!axisInfo.involveSeries){updaters.showPointer(axisInfo,newValue);return;}// Heavy calculation. So put it after axis.containData checking.\nvar payloadInfo=buildPayloadsBySeries(newValue,axisInfo);var payloadBatch=payloadInfo.payloadBatch;var snapToValue=payloadInfo.snapToValue;// Fill content of event obj for echarts.connect.\n// By default use the first involved series data as a sample to connect.\nif(payloadBatch[0]&&outputFinder.seriesIndex==null){extend(outputFinder,payloadBatch[0]);}// If no linkSource input, this process is for collecting link\n// target, where snap should not be accepted.\nif(!dontSnap&&axisInfo.snap){if(axis.containData(snapToValue)&&snapToValue!=null){newValue=snapToValue;}}updaters.showPointer(axisInfo,newValue,payloadBatch,outputFinder);// Tooltip should always be snapToValue, otherwise there will be\n// incorrect \"axis value ~ series value\" mapping displayed in tooltip.\nupdaters.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$7(axisInfo.seriesModels,function(series,idx){var dataDim=series.getData().mapDimension(dim,true);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,// Add a threshold to avoid find the wrong dataIndex\n// when data length is not same.\n// false,\naxis.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);// Consider category case\nif(dist<=minDist){if(dist<minDist||diff>=0&&minDiff<0){minDist=dist;minDiff=diff;snapToValue=seriesNestestValue;payloadBatch.length=0;}each$7(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 no data, do not create anything in dataByCoordSys,\n// whose length will be used to judge whether dispatch action.\nif(!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,// Caustion: viewHelper.getValueLabel is actually on \"view stage\", which\n// depends that all models have been updated. So it should not be performed\n// here. Considering axisPointerModel used here is volatile, which is hard\n// to be retrieve in TooltipView, we prepare parameters here.\nvalueLabelOpt:{precision:axisPointerModel.get('label.precision'),formatter:axisPointerModel.get('label.formatter')},seriesDataIndices:payloadBatch.slice()});}function updateModelActually(showValueMap,axesInfo,outputFinder){var outputAxesInfo=outputFinder.axesInfo=[];// Basic logic: If no 'show' required, 'hide' this axisPointer.\neach$7(axesInfo,function(axisInfo,key){var option=axisInfo.axisPointerModel.option;var valItem=showValueMap[key];if(valItem){!axisInfo.useHandle&&(option.status='show');option.value=valItem.value;// For label formatter param and highlight.\noption.seriesDataIndices=(valItem.payloadBatch||[]).slice();}// When always show (e.g., handle used), remain\n// original value and status.\nelse{// If hide, value still need to be set, consider\n// click legend to toggle axis blank.\n!axisInfo.useHandle&&(option.status='hide');}// If status is 'hide', should be no info in payload.\noption.status==='show'&&outputAxesInfo.push({axisDim:axisInfo.axis.dim,axisIndex:axisInfo.axis.model.componentIndex,value:option.value});});}function dispatchTooltipActually(dataByCoordSys,point,payload,dispatchAction){// Basic logic: If no showTip required, hideTip will be dispatched.\nif(illegalPoint(point)||!dataByCoordSys.list.length){dispatchAction({type:'hideTip'});return;}// In most case only one axis (or event one series is used). It is\n// convinient to fetch payload.seriesIndex and payload.dataIndex\n// dirtectly. So put the first seriesIndex and dataIndex of the first\n// axis on the payload.\nvar 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){// FIXME\n// highlight status modification shoule be a stage of main process?\n// (Consider confilct (e.g., legend and axisPointer) and setOption)\nvar zr=api.getZr();var highDownKey='axisPointerLastHighlights';var lastHighlights=inner$7(zr)[highDownKey]||{};var newHighlights=inner$7(zr)[highDownKey]={};// Update highlight/downplay status according to axisPointer model.\n// Build hash map and remove duplicate incidentally.\neach$7(axesInfo,function(axisInfo,key){var option=axisInfo.axisPointerModel.option;option.status==='show'&&each$7(option.seriesDataIndices,function(batchItem){var key=batchItem.seriesIndex+' | '+batchItem.dataIndex;newHighlights[key]=batchItem;});});// Diff.\nvar toHighlight=[];var toDownplay=[];each$1(lastHighlights,function(batchItem,key){!newHighlights[key]&&toDownplay.push(batchItem);});each$1(newHighlights,function(batchItem,key){!lastHighlights[key]&&toHighlight.push(batchItem);});toDownplay.length&&api.dispatchAction({type:'downplay',escapeConnect:true,batch:toDownplay});toHighlight.length&&api.dispatchAction({type:'highlight',escapeConnect: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]);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var AxisPointerModel=extendComponentModel({type:'axisPointer',coordSysAxesInfo:null,defaultOption:{// 'auto' means that show when triggered by tooltip or handle.\nshow:'auto',// 'click' | 'mousemove' | 'none'\ntriggerOn:null,// set default in AxisPonterView.js\nzlevel:0,z:50,type:'line',// 'line' 'shadow' 'cross' 'none'.\n// axispointer triggered by tootip determine snap automatically,\n// see `modelHelper`.\nsnap:false,triggerTooltip:true,value:null,status:null,// Init value depends on whether handle is used.\n// [group0, group1, ...]\n// Each group can be: {\n//      mapper: function () {},\n//      singleTooltip: 'multiple',  // 'multiple' or 'single'\n//      xAxisId: ...,\n//      yAxisName: ...,\n//      angleAxisIndex: ...\n// }\n// mapper: can be ignored.\n//      input: {axisInfo, value}\n//      output: {axisInfo, value}\nlink:[],// Do not set 'auto' here, otherwise global animation: false\n// will not effect at this axispointer.\nanimation:null,animationDurationUpdate:200,lineStyle:{color:'#aaa',width:1,type:'solid'},shadowStyle:{color:'rgba(150,150,150,0.3)'},label:{show:true,formatter:null,// string | Function\nprecision:'auto',// Or a number like 0, 1, 2 ...\nmargin:3,color:'#fff',padding:[5,7,5,7],backgroundColor:'auto',// default: axis line color\nborderColor:null,borderWidth:0,shadowBlur:3,shadowColor:'#aaa'// Considering applicability, common style should\n// better not have shadowOffset.\n// shadowOffsetX: 0,\n// shadowOffsetY: 2\n},handle:{show:false,/* eslint-disable */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',// jshint ignore:line\n/* eslint-enable */size:45,// handle margin is from symbol center to axis, which is stable when circular move.\nmargin:50,// color: '#1b8bbd'\n// color: '#2f4554'\ncolor:'#333',shadowBlur:3,shadowColor:'#aaa',shadowOffsetX:0,shadowOffsetY:2,// For mobile performance\nthrottle:40}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$8=makeInner();var each$8=each$1;/**\n * @param {string} key\n * @param {module:echarts/ExtensionAPI} api\n * @param {Function} handler\n *      param: {string} currTrigger\n *      param: {Array.<number>} point\n */function register(key,api,handler){if(env$1.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('mouseout', onLeave);\nuseHandler('globalout',onLeave);function useHandler(eventType,cb){zr.on(eventType,function(e){var dis=makeDispatchAction(api);each$8(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:[]};// FIXME\n// better approach?\n// 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip,\n// which may be conflict, (axisPointer call showTip but tooltip call hideTip);\n// So we have to add \"final stage\" to merge those dispatched actions.\nvar dispatchAction=function dispatchAction(payload){var pendingList=pendings[payload.type];if(pendingList){pendingList.push(payload);}else{payload.dispatchAction=dispatchAction;api.dispatchAction(payload);}};return{dispatchAction:dispatchAction,pendings:pendings};}/**\n * @param {string} key\n * @param {module:echarts/ExtensionAPI} api\n */function unregister(key,api){if(env$1.node){return;}var zr=api.getZr();var record=(inner$8(zr).records||{})[key];if(record){inner$8(zr).records[key]=null;}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var AxisPointerView=extendComponentView({type:'axisPointer',render:function render(globalAxisPointerModel,ecModel,api){var globalTooltipModel=ecModel.getComponent('tooltip');var triggerOn=globalAxisPointerModel.get('triggerOn')||globalTooltipModel&&globalTooltipModel.get('triggerOn')||'mousemove|click';// Register global listener in AxisPointerView to enable\n// AxisPointerView to be independent to Tooltip.\nregister('axisPointer',api,function(currTrigger,e,dispatchAction){// If 'none', it is not controlled by mouse totally.\nif(triggerOn!=='none'&&(currTrigger==='leave'||triggerOn.indexOf(currTrigger)>=0)){dispatchAction({type:'updateAxisPointer',currTrigger:currTrigger,x:e&&e.offsetX,y:e&&e.offsetY});}});},/**\n     * @override\n     */remove:function remove(ecModel,api){unregister(api.getZr(),'axisPointer');AxisPointerView.superApply(this._model,'remove',arguments);},/**\n     * @override\n     */dispose:function dispose(ecModel,api){unregister('axisPointer',api);AxisPointerView.superApply(this._model,'dispose',arguments);}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var inner$9=makeInner();var clone$4=_clone;var bind$1=bind;/**\n * Base axis pointer class in 2D.\n * Implemenents {module:echarts/component/axis/IAxisPointer}.\n */function BaseAxisPointer(){}BaseAxisPointer.prototype={/**\n     * @private\n     */_group:null,/**\n     * @private\n     */_lastGraphicKey:null,/**\n     * @private\n     */_handle:null,/**\n     * @private\n     */_dragging:false,/**\n     * @private\n     */_lastValue:null,/**\n     * @private\n     */_lastStatus:null,/**\n     * @private\n     */_payloadInfo:null,/**\n     * In px, arbitrary value. Do not set too small,\n     * no animation is ok for most cases.\n     * @protected\n     */animationThreshold:15,/**\n     * @implement\n     */render:function render(axisModel,axisPointerModel,api,forceRender){var value=axisPointerModel.get('value');var status=axisPointerModel.get('status');// Bind them to `this`, not in closure, otherwise they will not\n// be replaced when user calling setOption in not merge mode.\nthis._axisModel=axisModel;this._axisPointerModel=axisPointerModel;this._api=api;// Optimize: `render` will be called repeatly during mouse move.\n// So it is power consuming if performing `render` each time,\n// especially on mobile device.\nif(!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'){// Do not clear here, for animation better.\ngroup&&group.hide();handle&&handle.hide();return;}group&&group.show();handle&&handle.show();// Otherwise status is 'show'\nvar elOption={};this.makeElOption(elOption,value,axisModel,axisPointerModel,api);// Enable change axis pointer type.\nvar 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,axisPointerModel);this.updateLabelEl(group,elOption,doUpdateProps,axisPointerModel);}updateMandatoryProps(group,axisPointerModel,true);this._renderHandle(value);},/**\n     * @implement\n     */remove:function remove(api){this.clear(api);},/**\n     * @implement\n     */dispose:function dispose(api){this.clear(api);},/**\n     * @protected\n     */determineAnimation:function determineAnimation(axisModel,axisPointerModel){var animation=axisPointerModel.get('animation');var axis=axisModel.axis;var isCategoryAxis=axis.type==='category';var useSnap=axisPointerModel.get('snap');// Value axis without snap always do not snap.\nif(!useSnap&&!isCategoryAxis){return false;}if(animation==='auto'||animation==null){var animationThreshold=this.animationThreshold;if(isCategoryAxis&&axis.getBandWidth()>animationThreshold){return true;}// It is important to auto animation when snap used. Consider if there is\n// a dataZoom, animation will be disabled when too many points exist, while\n// it will be enabled for better visual effect when little points exist.\nif(useSnap){var seriesDataCount=getAxisInfo(axisModel).seriesDataCount;var axisExtent=axis.getExtent();// Approximate band width\nreturn Math.abs(axisExtent[0]-axisExtent[1])/seriesDataCount>animationThreshold;}return false;}return animation===true;},/**\n     * add {pointer, label, graphicKey} to elOption\n     * @protected\n     */makeElOption:function makeElOption(elOption,value,axisModel,axisPointerModel,api){// Shoule be implemenented by sub-class.\n},/**\n     * @protected\n     */createPointerEl:function createPointerEl(group,elOption,axisModel,axisPointerModel){var pointerOption=elOption.pointer;if(pointerOption){var pointerEl=inner$9(group).pointerEl=new graphic[pointerOption.type](clone$4(elOption.pointer));group.add(pointerEl);}},/**\n     * @protected\n     */createLabelEl:function createLabelEl(group,elOption,axisModel,axisPointerModel){if(elOption.label){var labelEl=inner$9(group).labelEl=new Rect(clone$4(elOption.label));group.add(labelEl);updateLabelShowHide(labelEl,axisPointerModel);}},/**\n     * @protected\n     */updatePointerEl:function updatePointerEl(group,elOption,updateProps$$1){var pointerEl=inner$9(group).pointerEl;if(pointerEl&&elOption.pointer){pointerEl.setStyle(elOption.pointer.style);updateProps$$1(pointerEl,{shape:elOption.pointer.shape});}},/**\n     * @protected\n     */updateLabelEl:function updateLabelEl(group,elOption,updateProps$$1,axisPointerModel){var labelEl=inner$9(group).labelEl;if(labelEl){labelEl.setStyle(elOption.label.style);updateProps$$1(labelEl,{// Consider text length change in vertical axis, animation should\n// be used on shape, otherwise the effect will be weird.\nshape:elOption.label.shape,position:elOption.label.position});updateLabelShowHide(labelEl,axisPointerModel);}},/**\n     * @private\n     */_renderHandle:function _renderHandle(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 onmousemove(e){// Fot mobile devicem, prevent screen slider on the button.\nstop(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);// update style\nvar includeStyles=['color','borderColor','borderWidth','opacity','shadowColor','shadowBlur','shadowOffsetX','shadowOffsetY'];handle.setStyle(handleModel.getItemStyle(null,includeStyles));// update position\nvar handleSize=handleModel.get('size');if(!isArray(handleSize)){handleSize=[handleSize,handleSize];}handle.attr('scale',[handleSize[0]/2,handleSize[1]/2]);createOrUpdate(this,'_doDispatchAxisPointer',handleModel.get('throttle')||0,'fixRate');this._moveHandleToValue(value,isInit);},/**\n     * @private\n     */_moveHandleToValue:function _moveHandleToValue(value,isInit){updateProps$1(this._axisPointerModel,!isInit&&this._moveAnimation,this._handle,getHandleTransProps(this.getHandleTransform(value,this._axisModel,this._axisPointerModel)));},/**\n     * @private\n     */_onHandleDragMove:function _onHandleDragMove(dx,dy){var handle=this._handle;if(!handle){return;}this._dragging=true;// Persistent for throttle.\nvar 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();},/**\n     * Throttled method.\n     * @private\n     */_doDispatchAxisPointer:function _doDispatchAxisPointer(){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}]});},/**\n     * @private\n     */_onHandleDragEnd:function _onHandleDragEnd(moveAnimation){this._dragging=false;var handle=this._handle;if(!handle){return;}var value=this._axisPointerModel.get('value');// Consider snap or categroy axis, handle may be not consistent with\n// axisPointer. So move handle to align the exact value position when\n// drag ended.\nthis._moveHandleToValue(value);// For the effect: tooltip will be shown when finger holding on handle\n// button, and will be hidden after finger left handle button.\nthis._api.dispatchAction({type:'hideTip'});},/**\n     * Should be implemenented by sub-class if support `handle`.\n     * @protected\n     * @param {number} value\n     * @param {module:echarts/model/Model} axisModel\n     * @param {module:echarts/model/Model} axisPointerModel\n     * @return {Object} {position: [x, y], rotation: 0}\n     */getHandleTransform:null,/**\n     * * Should be implemenented by sub-class if support `handle`.\n     * @protected\n     * @param {Object} transform {position, rotation}\n     * @param {Array.<number>} delta [dx, dy]\n     * @param {module:echarts/model/Model} axisModel\n     * @param {module:echarts/model/Model} axisPointerModel\n     * @return {Object} {position: [x, y], rotation: 0, cursorPoint: [x, y]}\n     */updateHandleTransform:null,/**\n     * @private\n     */clear:function clear(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;}},/**\n     * @protected\n     */doClear:function doClear(){// Implemented by sub-class if necessary.\n},/**\n     * @protected\n     * @param {Array.<number>} xy\n     * @param {Array.<number>} wh\n     * @param {number} [xDimIndex=0] or 1\n     */buildLabel:function buildLabel(xy,wh,xDimIndex){xDimIndex=xDimIndex||0;return{x:xy[xDimIndex],y:xy[1-xDimIndex],width:wh[xDimIndex],height:wh[1-xDimIndex]};}};BaseAxisPointer.prototype.constructor=BaseAxisPointer;function updateProps$1(animationModel,moveAnimation,el,props){// Animation optimize.\nif(!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$1(lastProps)&&isObject$1(newProps)){var equals=true;each$1(newProps,function(item,key){equals=equals&&propsEqual(lastProps[key],item);});return!!equals;}else{return lastProps===newProps;}}function updateLabelShowHide(labelEl,axisPointerModel){labelEl[axisPointerModel.get('label.show')?'show':'hide']();}function getHandleTransProps(trans){return{position:trans.position.slice(),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;}});}enableClassExtend(BaseAxisPointer);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @param {module:echarts/model/Model} axisPointerModel\n */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;}/**\n * @param {Function} labelPos {align, verticalAlign, position}\n */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];// Adjust by align.\nvar 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);// Not overflow ec container\nconfineInContainer(position,width,height,api);var bgColor=labelModel.get('backgroundColor');if(!bgColor||bgColor==='auto'){bgColor=axisModel.get('axisLine.lineStyle.color');}elOption.label={shape:{x:0,y:0,width:width,height:height,r:labelModel.get('borderRadius')},position:position.slice(),// TODO: rich\nstyle:{text:text,textFont:font,textFill:labelModel.getTextColor(),textPosition:'inside',textPadding:paddings,fill:bgColor,stroke:labelModel.get('borderColor')||'transparent',lineWidth:labelModel.get('borderWidth')||0,shadowBlur:labelModel.get('shadowBlur'),shadowColor:labelModel.get('shadowColor'),shadowOffsetX:labelModel.get('shadowOffsetX'),shadowOffsetY:labelModel.get('shadowOffsetY')},// Lable should be over axisPointer.\nz2:10};}// Do not overflow ec container\nfunction 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);}/**\n * @param {number} value\n * @param {module:echarts/coord/Axis} axis\n * @param {module:echarts/model/Global} ecModel\n * @param {Object} opt\n * @param {Array.<Object>} seriesDataIndices\n * @param {number|string} opt.precision 'auto' or a number\n * @param {string|Function} opt.formatter label formatter\n */function getValueLabel(value,axis,ecModel,seriesDataIndices,opt){value=axis.scale.parse(value);var text=axis.scale.getLabel(// If `precision` is set, width can be fixed (like '12.00500'), which\n// helps to debounce when when moving label.\nvalue,{precision:opt.precision});var formatter=opt.formatter;if(formatter){var params={value:getAxisRawValue(axis,value),axisDimension:axis.dim,axisIndex:axis.index,seriesData:[]};each$1(seriesDataIndices,function(idxItem){var series=ecModel.getSeriesByIndex(idxItem.seriesIndex);var dataIndex=idxItem.dataIndexInside;var dataParams=series&&series.getDataParams(dataIndex);dataParams&&params.seriesData.push(dataParams);});if(isString(formatter)){text=formatter.replace('{value}',text);}else if(isFunction$1(formatter)){text=formatter(params);}}return text;}/**\n * @param {module:echarts/coord/Axis} axis\n * @param {number} value\n * @param {Object} layoutInfo {\n *  rotation, position, labelOffset, labelDirection, labelMargin\n * }\n */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});}/**\n * @param {Array.<number>} p1\n * @param {Array.<number>} p2\n * @param {number} [xDimIndex=0] or 1\n */function makeLineShape(p1,p2,xDimIndex){xDimIndex=xDimIndex||0;return{x1:p1[xDimIndex],y1:p1[1-xDimIndex],x2:p2[xDimIndex],y2:p2[1-xDimIndex]};}/**\n * @param {Array.<number>} xy\n * @param {Array.<number>} wh\n * @param {number} [xDimIndex=0] or 1\n */function makeRectShape(xy,wh,xDimIndex){xDimIndex=xDimIndex||0;return{x:xy[xDimIndex],y:xy[1-xDimIndex],width:wh[xDimIndex],height:wh[1-xDimIndex]};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var CartesianAxisPointer=BaseAxisPointer.extend({/**\n     * @override\n     */makeElOption:function makeElOption(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);},/**\n     * @override\n     */getHandleTransform:function getHandleTransform(value,axisModel,axisPointerModel){var layoutInfo=layout$1(axisModel.axis.grid.model,axisModel,{labelInside:false});layoutInfo.labelMargin=axisPointerModel.get('handle.margin');return{position:getTransformedPosition(axisModel.axis,value,layoutInfo),rotation:layoutInfo.rotation+(layoutInfo.labelDirection<0?Math.PI:0)};},/**\n     * @override\n     */updateHandleTransform:function updateHandleTransform(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.position;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];// Make tooltip do not overlap axisPointer and in the middle of the grid.\nvar tooltipOptions=[{verticalAlign:'middle'},{align:'center'}];return{position:currPosition,rotation:transform.rotation,cursorPoint:cursorPoint,tooltipOption:tooltipOptions[dimIndex]};}});function getCartesian(grid,axis){var opt={};opt[axis.dim+'AxisIndex']=axis.index;return grid.getCartesian(opt);}var pointerShapeBuilder={line:function line(axis,pixelValue,otherExtent){var targetShape=makeLineShape([pixelValue,otherExtent[0]],[pixelValue,otherExtent[1]],getAxisDimIndex(axis));return{type:'Line',subPixelOptimize:true,shape:targetShape};},shadow:function shadow(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);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // CartesianAxisPointer is not supposed to be required here. But consider\n// echarts.simple.js and online build tooltip, which only require gridSimple,\n// CartesianAxisPointer should be able to required somewhere.\nregisterPreprocessor(function(option){// Always has a global axisPointerModel for default setting.\nif(option){(!option.axisPointer||option.axisPointer.length===0)&&(option.axisPointer={});var link=option.axisPointer.link;// Normalize to array to avoid object mergin. But if link\n// is not set, remain null/undefined, otherwise it will\n// override existent link setting.\nif(link&&!isArray(link)){option.axisPointer.link=[link];}}});// This process should proformed after coordinate systems created\n// and series data processed. So put it on statistic processing stage.\nregisterProcessor(PRIORITY.PROCESSOR.STATISTIC,function(ecModel,api){// Build axisPointerModel, mergin tooltip.axisPointer model for each axis.\n// allAxesInfo should be updated when setOption performed.\necModel.getComponent('axisPointer').coordSysAxesInfo=collect(ecModel,api);});// Broadcast to all views.\nregisterAction({type:'updateAxisPointer',event:'updateAxisPointer',update:':updateAxisPointer'},axisTrigger);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/extendComponentModel({type:'tooltip',dependencies:['axisPointer'],defaultOption:{zlevel:0,z:60,show:true,// tooltip主体内容\nshowContent:true,// 'trigger' only works on coordinate system.\n// 'item' | 'axis' | 'none'\ntrigger:'item',// 'click' | 'mousemove' | 'none'\ntriggerOn:'mousemove|click',alwaysShowContent:false,displayMode:'single',// 'single' | 'multipleByCoordSys'\nrenderMode:'auto',// 'auto' | 'html' | 'richText'\n// 'auto': use html by default, and use non-html if `document` is not defined\n// 'html': use html for tooltip\n// 'richText': use canvas, svg, and etc. for tooltip\n// 位置 {Array} | {Function}\n// position: null\n// Consider triggered from axisPointer handle, verticalAlign should be 'middle'\n// align: null,\n// verticalAlign: null,\n// 是否约束 content 在 viewRect 中。默认 false 是为了兼容以前版本。\nconfine:false,// 内容格式器：{string}（Template） ¦ {Function}\n// formatter: null\nshowDelay:0,// 隐藏延迟，单位ms\nhideDelay:100,// 动画变换时间，单位s\ntransitionDuration:0.4,enterable:false,// 提示背景颜色，默认为透明度为0.7的黑色\nbackgroundColor:'rgba(50,50,50,0.7)',// 提示边框颜色\nborderColor:'#333',// 提示边框圆角，单位px，默认为4\nborderRadius:4,// 提示边框线宽，单位px，默认为0（无边框）\nborderWidth:0,// 提示内边距，单位px，默认各方向内边距为5，\n// 接受数组分别设定上右下左边距，同css\npadding:5,// Extra css text\nextraCssText:'',// 坐标轴指示器，坐标轴触发有效\naxisPointer:{// 默认为直线\n// 可选为：'line' | 'shadow' | 'cross'\ntype:'line',// type 为 line 的时候有效，指定 tooltip line 所在的轴，可选\n// 可选 'x' | 'y' | 'angle' | 'radius' | 'auto'\n// 默认 'auto'，会选择类型为 category 的轴，对于双数值轴，笛卡尔坐标系会默认选择 x 轴\n// 极坐标系会默认选择 angle 轴\naxis:'auto',animation:'auto',animationDurationUpdate:200,animationEasingUpdate:'exponentialOut',crossStyle:{color:'#999',width:1,type:'dashed',// TODO formatter\ntextStyle:{}}// lineStyle and shadowStyle should not be specified here,\n// otherwise it will always override those styles on option.axisPointer.\n},textStyle:{color:'#fff',fontSize:14}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$10=each$1;var toCamelCase$1=toCamelCase;var vendors=['','-webkit-','-moz-','-o-'];var gCssText='position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';/**\n * @param {number} duration\n * @return {string}\n * @inner\n */function assembleTransition(duration){var transitionCurve='cubic-bezier(0.23, 1, 0.32, 1)';var transitionText='left '+duration+'s '+transitionCurve+','+'top '+duration+'s '+transitionCurve;return map(vendors,function(vendorPrefix){return vendorPrefix+'transition:'+transitionText;}).join(';');}/**\n * @param {Object} textStyle\n * @return {string}\n * @inner\n */function assembleFont(textStyleModel){var cssText=[];var fontSize=textStyleModel.get('fontSize');var color=textStyleModel.getTextColor();color&&cssText.push('color:'+color);cssText.push('font:'+textStyleModel.getFont());var lineHeight=textStyleModel.get('lineHeight');if(lineHeight==null){lineHeight=Math.round(fontSize*3/2);}fontSize&&cssText.push('line-height:'+lineHeight+'px');var shadowColor=textStyleModel.get('textShadowColor');var shadowBlur=textStyleModel.get('textShadowBlur')||0;var shadowOffsetX=textStyleModel.get('textShadowOffsetX')||0;var shadowOffsetY=textStyleModel.get('textShadowOffsetY')||0;shadowBlur&&cssText.push('text-shadow:'+shadowOffsetX+'px '+shadowOffsetY+'px '+shadowBlur+'px '+shadowColor);each$10(['decoration','align'],function(name){var val=textStyleModel.get(name);val&&cssText.push('text-'+name+':'+val);});return cssText.join(';');}/**\n * @param {Object} tooltipModel\n * @return {string}\n * @inner\n */function assembleCssText(tooltipModel){var cssText=[];var transitionDuration=tooltipModel.get('transitionDuration');var backgroundColor=tooltipModel.get('backgroundColor');var textStyleModel=tooltipModel.getModel('textStyle');var padding=tooltipModel.get('padding');// Animation transition. Do not animate when transitionDuration is 0.\ntransitionDuration&&cssText.push(assembleTransition(transitionDuration));if(backgroundColor){if(env$1.canvasSupported){cssText.push('background-Color:'+backgroundColor);}else{// for ie\ncssText.push('background-Color:#'+toHex(backgroundColor));cssText.push('filter:alpha(opacity=70)');}}// Border style\neach$10(['width','color','radius'],function(name){var borderName='border-'+name;var camelCase=toCamelCase$1(borderName);var val=tooltipModel.get(camelCase);val!=null&&cssText.push(borderName+':'+val+(name==='color'?'':'px'));});// Text style\ncssText.push(assembleFont(textStyleModel));// Padding\nif(padding!=null){cssText.push('padding:'+normalizeCssArray$1(padding).join('px ')+'px');}return cssText.join(';')+';';}// If not able to make, do not modify the input `out`.\nfunction makeStyleCoord(out,zr,appendToBody,zrX,zrY){var zrPainter=zr&&zr.painter;if(appendToBody){var zrViewportRoot=zrPainter&&zrPainter.getViewportRoot();if(zrViewportRoot){// Some APPs might use scale on body, so we support CSS transform here.\ntransformLocalCoord(out,zrViewportRoot,document.body,zrX,zrY);}}else{out[0]=zrX;out[1]=zrY;// xy should be based on canvas root. But tooltipContent is\n// the sibling of canvas root. So padding of ec container\n// should be considered here.\nvar viewportRootOffset=zrPainter&&zrPainter.getViewportRootOffset();if(viewportRootOffset){out[0]+=viewportRootOffset.offsetLeft;out[1]+=viewportRootOffset.offsetTop;}}out[2]=out[0]/zr.getWidth();// The ratio of left to width\nout[3]=out[1]/zr.getHeight();// The ratio of top to height\n}/**\n * @alias module:echarts/component/tooltip/TooltipContent\n * @param {HTMLElement} container\n * @param {ExtensionAPI} api\n * @param {Object} [opt]\n * @param {boolean} [opt.appendToBody]\n *        `false`: the DOM element will be inside the container. Default value.\n *        `true`: the DOM element will be appended to HTML body, which avoid\n *                some overflow clip but intrude outside of the container.\n * @constructor\n */function TooltipContent(container,api,opt){if(env$1.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;this._styleCoord=[0,0,0,0];// [left, top, left/width, top/height]\nmakeStyleCoord(this._styleCoord,zr,appendToBody,api.getWidth()/2,api.getHeight()/2);if(appendToBody){document.body.appendChild(el);}else{container.appendChild(el);}this._container=container;this._show=false;/**\n     * @private\n     */this._hideTimeout;// FIXME\n// Is it needed to trigger zr event manually if\n// the browser do not support `pointer-events: none`.\nvar self=this;el.onmouseenter=function(){// clear the timeout in hideLater and keep showing tooltip\nif(self._enterable){clearTimeout(self._hideTimeout);self._show=true;}self._inContent=true;};el.onmousemove=function(e){e=e||window.event;if(!self._enterable){// `pointer-events: none` is set to tooltip content div\n// if `enterable` is set as `false`, and `el.onmousemove`\n// can not be triggered. But in browser that do not\n// support `pointer-events`, we need to do this:\n// Try trigger zrender event to avoid mouse\n// in and out shape too frequently\nvar handler=zr.handler;var zrViewportRoot=zr.painter.getViewportRoot();normalizeEvent(zrViewportRoot,e,true);handler.dispatch('mousemove',e);}};el.onmouseleave=function(){if(self._enterable){if(self._show){self.hideLater(self._hideDelay);}}self._inContent=false;};}TooltipContent.prototype={constructor:TooltipContent,/**\n     * @private\n     * @type {boolean}\n     */_enterable:true,/**\n     * Update when tooltip is rendered\n     */update:function update(tooltipModel){// FIXME\n// Move this logic to ec main?\nvar 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._moveTooltipIfResized();// Hide the tooltip\n// PENDING\n// this.hide();\n},/**\n     * when `alwaysShowContent` is true,\n     * we should move the tooltip after chart resized\n     */_moveTooltipIfResized:function _moveTooltipIfResized(){var ratioX=this._styleCoord[2];// The ratio of left to width\nvar ratioY=this._styleCoord[3];// The ratio of top to height\nvar realX=ratioX*this._zr.getWidth();var realY=ratioY*this._zr.getHeight();this.moveTo(realX,realY);},show:function show(tooltipModel){clearTimeout(this._hideTimeout);var el=this.el;var styleCoord=this._styleCoord;el.style.cssText=gCssText+assembleCssText(tooltipModel)// Because of the reason described in:\n// http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore\n// we should set initial value to `left` and `top`.\n+';left:'+styleCoord[0]+'px;top:'+styleCoord[1]+'px;'+(tooltipModel.get('extraCssText')||'');el.style.display=el.innerHTML?'block':'none';// If mouse occasionally move over the tooltip, a mouseout event will be\n// triggered by canvas, and cause some unexpectable result like dragging\n// stop, \"unfocusAdjacency\". Here `pointer-events: none` is used to solve\n// it. Although it is not supported by IE8~IE10, fortunately it is a rare\n// scenario.\nel.style.pointerEvents=this._enterable?'auto':'none';this._show=true;},setContent:function setContent(content){this.el.innerHTML=content==null?'':content;},setEnterable:function setEnterable(enterable){this._enterable=enterable;},getSize:function getSize(){var el=this.el;return[el.clientWidth,el.clientHeight];},moveTo:function moveTo(zrX,zrY){var styleCoord=this._styleCoord;makeStyleCoord(styleCoord,this._zr,this._appendToBody,zrX,zrY);var style=this.el.style;style.left=styleCoord[0]+'px';style.top=styleCoord[1]+'px';},hide:function hide(){this.el.style.display='none';this._show=false;},hideLater:function hideLater(time){if(this._show&&!(this._inContent&&this._enterable)){if(time){this._hideDelay=time;// Set show false to avoid invoke hideLater multiple times\nthis._show=false;this._hideTimeout=setTimeout(bind(this.hide,this),time);}else{this.hide();}}},isShow:function isShow(){return this._show;},dispose:function dispose(){this.el.parentNode.removeChild(this.el);},getOuterSize:function getOuterSize(){var width=this.el.clientWidth;var height=this.el.clientHeight;// Consider browser compatibility.\n// IE8 does not support getComputedStyle.\nif(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};}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // import Group from 'zrender/src/container/Group';\nfunction makeStyleCoord$1(out,zr,zrX,zrY){out[0]=zrX;out[1]=zrY;out[2]=out[0]/zr.getWidth();// The ratio of left to width\nout[3]=out[1]/zr.getHeight();// The ratio of top to height\n}/**\n * @alias module:echarts/component/tooltip/TooltipRichContent\n * @constructor\n */function TooltipRichContent(api){var zr=this._zr=api.getZr();this._styleCoord=[0,0,0,0];// [left, top, left/width, top/height]\nmakeStyleCoord$1(this._styleCoord,zr,api.getWidth()/2,api.getHeight()/2);this._show=false;/**\n     * @private\n     */this._hideTimeout;}TooltipRichContent.prototype={constructor:TooltipRichContent,/**\n     * @private\n     * @type {boolean}\n     */_enterable:true,/**\n     * Update when tooltip is rendered\n     */update:function update(tooltipModel){var alwaysShowContent=tooltipModel.get('alwaysShowContent');alwaysShowContent&&this._moveTooltipIfResized();},/**\n     * when `alwaysShowContent` is true,\n     * we should move the tooltip after chart resized\n     */_moveTooltipIfResized:function _moveTooltipIfResized(){var ratioX=this._styleCoord[2];// The ratio of left to width\nvar ratioY=this._styleCoord[3];// The ratio of top to height\nvar realX=ratioX*this._zr.getWidth();var realY=ratioY*this._zr.getHeight();this.moveTo(realX,realY);},show:function show(tooltipModel){if(this._hideTimeout){clearTimeout(this._hideTimeout);}this.el.attr('show',true);this._show=true;},/**\n     * Set tooltip content\n     *\n     * @param {string} content rich text string of content\n     * @param {Object} markerRich rich text style\n     * @param {Object} tooltipModel tooltip model\n     */setContent:function setContent(content,markerRich,tooltipModel){if(this.el){this._zr.remove(this.el);}var markers={};var text=content;var prefix='{marker';var suffix='|}';var startId=text.indexOf(prefix);while(startId>=0){var endId=text.indexOf(suffix);var name=text.substr(startId+prefix.length,endId-startId-prefix.length);if(name.indexOf('sub')>-1){markers['marker'+name]={textWidth:4,textHeight:4,textBorderRadius:2,textBackgroundColor:markerRich[name],// TODO: textOffset is not implemented for rich text\ntextOffset:[3,0]};}else{markers['marker'+name]={textWidth:10,textHeight:10,textBorderRadius:5,textBackgroundColor:markerRich[name]};}text=text.substr(endId+1);startId=text.indexOf('{marker');}var textStyleModel=tooltipModel.getModel('textStyle');var fontSize=textStyleModel.get('fontSize');var lineHeight=tooltipModel.get('textLineHeight');if(lineHeight==null){lineHeight=Math.round(fontSize*3/2);}this.el=new Text({style:setTextStyle({},textStyleModel,{rich:markers,text:content,textBackgroundColor:tooltipModel.get('backgroundColor'),textBorderRadius:tooltipModel.get('borderRadius'),textFill:tooltipModel.get('textStyle.color'),textPadding:tooltipModel.get('padding'),textLineHeight:lineHeight}),z:tooltipModel.get('z')});this._zr.add(this.el);var self=this;this.el.on('mouseover',function(){// clear the timeout in hideLater and keep showing tooltip\nif(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;});},setEnterable:function setEnterable(enterable){this._enterable=enterable;},getSize:function getSize(){var bounding=this.el.getBoundingRect();return[bounding.width,bounding.height];},moveTo:function moveTo(x,y){if(this.el){var styleCoord=this._styleCoord;makeStyleCoord$1(styleCoord,this._zr,x,y);this.el.attr('position',[styleCoord[0],styleCoord[1]]);}},hide:function hide(){if(this.el){this.el.hide();}this._show=false;},hideLater:function hideLater(time){if(this._show&&!(this._inContent&&this._enterable)){if(time){this._hideDelay=time;// Set show false to avoid invoke hideLater multiple times\nthis._show=false;this._hideTimeout=setTimeout(bind(this.hide,this),time);}else{this.hide();}}},isShow:function isShow(){return this._show;},dispose:function dispose(){clearTimeout(this._hideTimeout);if(this.el){this._zr.remove(this.el);}},getOuterSize:function getOuterSize(){var size=this.getSize();return{width:size[0],height:size[1]};}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var bind$2=bind;var each$9=each$1;var parsePercent$2=parsePercent$1;var proxyRect=new Rect({shape:{x:-1,y:-1,width:2,height:2}});extendComponentView({type:'tooltip',init:function init(ecModel,api){if(env$1.node){return;}var tooltipModel=ecModel.getComponent('tooltip');var renderMode=tooltipModel.get('renderMode');this._renderMode=getTooltipRenderMode(renderMode);var tooltipContent;if(this._renderMode==='html'){tooltipContent=new TooltipContent(api.getDom(),api,{appendToBody:tooltipModel.get('appendToBody',true)});this._newLine='<br/>';}else{tooltipContent=new TooltipRichContent(api);this._newLine='\\n';}this._tooltipContent=tooltipContent;},render:function render(tooltipModel,ecModel,api){if(env$1.node){return;}// Reset\nthis.group.removeAll();/**\n         * @private\n         * @type {module:echarts/component/tooltip/TooltipModel}\n         */this._tooltipModel=tooltipModel;/**\n         * @private\n         * @type {module:echarts/model/Global}\n         */this._ecModel=ecModel;/**\n         * @private\n         * @type {module:echarts/ExtensionAPI}\n         */this._api=api;/**\n         * Should be cleaned when render.\n         * @private\n         * @type {Array.<Array.<Object>>}\n         */this._lastDataByCoordSys=null;/**\n         * @private\n         * @type {boolean}\n         */this._alwaysShowContent=tooltipModel.get('alwaysShowContent');var tooltipContent=this._tooltipContent;tooltipContent.update(tooltipModel);tooltipContent.setEnterable(tooltipModel.get('enterable'));this._initGlobalListener();this._keepShow();},_initGlobalListener:function _initGlobalListener(){var tooltipModel=this._tooltipModel;var triggerOn=tooltipModel.get('triggerOn');register('itemTooltip',this._api,bind$2(function(currTrigger,e,dispatchAction){// If 'none', it is not controlled by mouse totally.\nif(triggerOn!=='none'){if(triggerOn.indexOf(currTrigger)>=0){this._tryShow(e,dispatchAction);}else if(currTrigger==='leave'){this._hide(dispatchAction);}}},this));},_keepShow:function _keepShow(){var tooltipModel=this._tooltipModel;var ecModel=this._ecModel;var api=this._api;// Try to keep the tooltip show when refreshing\nif(this._lastX!=null&&this._lastY!=null// When user is willing to control tooltip totally using API,\n// self.manuallyShowTip({x, y}) might cause tooltip hide,\n// which is not expected.\n&&tooltipModel.get('triggerOn')!=='none'){var self=this;clearTimeout(this._refreshUpdateTimeout);this._refreshUpdateTimeout=setTimeout(function(){// Show tip next tick after other charts are rendered\n// In case highlight action has wrong result\n// FIXME\n!api.isDisposed()&&self.manuallyShowTip(tooltipModel,ecModel,api,{x:self._lastX,y:self._lastY});});}},/**\n     * Show tip manually by\n     * dispatchAction({\n     *     type: 'showTip',\n     *     x: 10,\n     *     y: 10\n     * });\n     * Or\n     * dispatchAction({\n     *      type: 'showTip',\n     *      seriesIndex: 0,\n     *      dataIndex or dataIndexInside or name\n     * });\n     *\n     *  TODO Batch\n     */manuallyShowTip:function manuallyShowTip(tooltipModel,ecModel,api,payload){if(payload.from===this.uid||env$1.node){return;}var dispatchAction=makeDispatchAction$1(payload,api);// Reset ticket\nthis._ticket='';// When triggered from axisPointer.\nvar dataByCoordSys=payload.dataByCoordSys;if(payload.tooltip&&payload.x!=null&&payload.y!=null){var el=proxyRect;el.position=[payload.x,payload.y];el.update();el.tooltip=payload.tooltip;// Manually show tooltip while view is not using zrender elements.\nthis._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:payload.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){// FIXME\n// should wrap dispatchAction like `axisPointer/globalListener` ?\napi.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);}},manuallyHideTip:function manuallyHideTip(tooltipModel,ecModel,api,payload){var tooltipContent=this._tooltipContent;if(!this._alwaysShowContent&&this._tooltipModel){tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));}this._lastX=this._lastY=null;if(payload.from!==this.uid){this._hide(makeDispatchAction$1(payload,api));}},// Be compatible with previous design, that is, when tooltip.type is 'axis' and\n// dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer\n// and tooltip.\n_manuallyAxisShowTip:function _manuallyAxisShowTip(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 tooltipModel=buildTooltipModel([data.getItemModel(dataIndex),seriesModel,(seriesModel.coordinateSystem||{}).model,tooltipModel]);if(tooltipModel.get('trigger')!=='axis'){return;}api.dispatchAction({type:'updateAxisPointer',seriesIndex:seriesIndex,dataIndex:dataIndex,position:payload.position});return true;},_tryShow:function _tryShow(e,dispatchAction){var el=e.target;var tooltipModel=this._tooltipModel;if(!tooltipModel){return;}// Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed\nthis._lastX=e.offsetX;this._lastY=e.offsetY;var dataByCoordSys=e.dataByCoordSys;if(dataByCoordSys&&dataByCoordSys.length){this._showAxisTooltip(dataByCoordSys,e);}// Always show item tooltip if mouse is on the element with dataIndex\nelse if(el&&el.dataIndex!=null){this._lastDataByCoordSys=null;this._showSeriesItemTooltip(e,el,dispatchAction);}// Tooltip provided directly. Like legend.\nelse if(el&&el.tooltip){this._lastDataByCoordSys=null;this._showComponentItemTooltip(e,el,dispatchAction);}else{this._lastDataByCoordSys=null;this._hide(dispatchAction);}},_showOrMove:function _showOrMove(tooltipModel,cb){// showDelay is used in this case: tooltip.enterable is set\n// as true. User intent to move mouse into tooltip and click\n// something. `showDelay` makes it easier to enter the content\n// but tooltip do not move immediately.\nvar delay=tooltipModel.get('showDelay');cb=bind(cb,this);clearTimeout(this._showTimout);delay>0?this._showTimout=setTimeout(cb,delay):cb();},_showAxisTooltip:function _showAxisTooltip(dataByCoordSys,e){var ecModel=this._ecModel;var globalTooltipModel=this._tooltipModel;var point=[e.offsetX,e.offsetY];var singleDefaultHTML=[];var singleParamsList=[];var singleTooltipModel=buildTooltipModel([e.tooltipOption,globalTooltipModel]);var renderMode=this._renderMode;var newLine=this._newLine;var markers={};each$9(dataByCoordSys,function(itemCoordSys){// var coordParamList = [];\n// var coordDefaultHTML = [];\n// var coordTooltipModel = buildTooltipModel([\n//     e.tooltipOption,\n//     itemCoordSys.tooltipOption,\n//     ecModel.getComponent(itemCoordSys.coordSysMainType, itemCoordSys.coordSysIndex),\n//     globalTooltipModel\n// ]);\n// var displayMode = coordTooltipModel.get('displayMode');\n// var paramsList = displayMode === 'single' ? singleParamsList : [];\neach$9(itemCoordSys.dataByAxis,function(item){var axisModel=ecModel.getComponent(item.axisDim+'Axis',item.axisIndex);var axisValue=item.value;var seriesDefaultHTML=[];if(!axisModel||axisValue==null){return;}var valueLabel=getValueLabel(axisValue,axisModel.axis,ecModel,item.seriesDataIndices,item.valueLabelOpt);each$1(item.seriesDataIndices,function(idxItem){var series=ecModel.getSeriesByIndex(idxItem.seriesIndex);var dataIndex=idxItem.dataIndexInside;var dataParams=series&&series.getDataParams(dataIndex);dataParams.axisDim=item.axisDim;dataParams.axisIndex=item.axisIndex;dataParams.axisType=item.axisType;dataParams.axisId=item.axisId;dataParams.axisValue=getAxisRawValue(axisModel.axis,axisValue);dataParams.axisValueLabel=valueLabel;if(dataParams){singleParamsList.push(dataParams);var seriesTooltip=series.formatTooltip(dataIndex,true,null,renderMode);var html;if(isObject$1(seriesTooltip)){html=seriesTooltip.html;var newMarkers=seriesTooltip.markers;merge(markers,newMarkers);}else{html=seriesTooltip;}seriesDefaultHTML.push(html);}});// Default tooltip content\n// FIXME\n// (1) should be the first data which has name?\n// (2) themeRiver, firstDataIndex is array, and first line is unnecessary.\nvar firstLine=valueLabel;if(renderMode!=='html'){singleDefaultHTML.push(seriesDefaultHTML.join(newLine));}else{singleDefaultHTML.push((firstLine?encodeHTML(firstLine)+newLine:'')+seriesDefaultHTML.join(newLine));}});},this);// In most case, the second axis is shown upper than the first one.\nsingleDefaultHTML.reverse();singleDefaultHTML=singleDefaultHTML.join(this._newLine+this._newLine);var positionExpr=e.position;this._showOrMove(singleTooltipModel,function(){if(this._updateContentNotChangedOnAxis(dataByCoordSys)){this._updatePosition(singleTooltipModel,positionExpr,point[0],point[1],this._tooltipContent,singleParamsList);}else{this._showTooltipContent(singleTooltipModel,singleDefaultHTML,singleParamsList,Math.random(),point[0],point[1],positionExpr,undefined,markers);}});// Do not trigger events here, because this branch only be entered\n// from dispatchAction.\n},_showSeriesItemTooltip:function _showSeriesItemTooltip(e,el,dispatchAction){var ecModel=this._ecModel;// Use dataModel in element if possible\n// Used when mouseover on a element like markPoint or edge\n// In which case, the data is not main data in series.\nvar seriesIndex=el.seriesIndex;var seriesModel=ecModel.getSeriesByIndex(seriesIndex);// For example, graph link.\nvar dataModel=el.dataModel||seriesModel;var dataIndex=el.dataIndex;var dataType=el.dataType;var data=dataModel.getData(dataType);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 seriesTooltip=dataModel.formatTooltip(dataIndex,false,dataType,this._renderMode);var defaultHtml;var markers;if(isObject$1(seriesTooltip)){defaultHtml=seriesTooltip.html;markers=seriesTooltip.markers;}else{defaultHtml=seriesTooltip;markers=null;}var asyncTicket='item_'+dataModel.name+'_'+dataIndex;this._showOrMove(tooltipModel,function(){this._showTooltipContent(tooltipModel,defaultHtml,params,asyncTicket,e.offsetX,e.offsetY,e.position,e.target,markers);});// FIXME\n// duplicated showtip if manuallyShowTip is called from dispatchAction.\ndispatchAction({type:'showTip',dataIndexInside:dataIndex,dataIndex:data.getRawIndex(dataIndex),seriesIndex:seriesIndex,from:this.uid});},_showComponentItemTooltip:function _showComponentItemTooltip(e,el,dispatchAction){var tooltipOpt=el.tooltip;if(typeof tooltipOpt==='string'){var content=tooltipOpt;tooltipOpt={content:content,// Fixed formatter\nformatter:content};}var subTooltipModel=new Model(tooltipOpt,this._tooltipModel,this._ecModel);var defaultHtml=subTooltipModel.get('content');var asyncTicket=Math.random();// Do not check whether `trigger` is 'none' here, because `trigger`\n// only works on coordinate system. In fact, we have not found case\n// that requires setting `trigger` nothing on component yet.\nthis._showOrMove(subTooltipModel,function(){this._showTooltipContent(subTooltipModel,defaultHtml,subTooltipModel.get('formatterParams')||{},asyncTicket,e.offsetX,e.offsetY,e.position,el);});// If not dispatch showTip, tip may be hide triggered by axis.\ndispatchAction({type:'showTip',from:this.uid});},_showTooltipContent:function _showTooltipContent(tooltipModel,defaultHtml,params,asyncTicket,x,y,positionExpr,el,markers){// Reset ticket\nthis._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;if(formatter&&typeof formatter==='string'){html=formatTpl(formatter,params,true);}else if(typeof formatter==='function'){var callback=bind$2(function(cbTicket,html){if(cbTicket===this._ticket){tooltipContent.setContent(html,markers,tooltipModel);this._updatePosition(tooltipModel,positionExpr,x,y,tooltipContent,params,el);}},this);this._ticket=asyncTicket;html=formatter(params,asyncTicket,callback);}tooltipContent.setContent(html,markers,tooltipModel);tooltipContent.show(tooltipModel);this._updatePosition(tooltipModel,positionExpr,x,y,tooltipContent,params,el);},/**\n     * @param  {string|Function|Array.<number>|Object} positionExpr\n     * @param  {number} x Mouse x\n     * @param  {number} y Mouse y\n     * @param  {boolean} confine Whether confine tooltip content in view rect.\n     * @param  {Object|<Array.<Object>} params\n     * @param  {module:zrender/Element} el target element\n     * @param  {module:echarts/ExtensionAPI} api\n     * @return {Array.<number>}\n     */_updatePosition:function _updatePosition(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(typeof positionExpr==='function'){// Callback of position can be an array or a string specify the position\npositionExpr=positionExpr([x,y],params,content.el,rect,{viewSize:[viewWidth,viewHeight],contentSize:contentSize.slice()});}if(isArray(positionExpr)){x=parsePercent$2(positionExpr[0],viewWidth);y=parsePercent$2(positionExpr[1],viewHeight);}else if(isObject$1(positionExpr)){positionExpr.width=contentSize[0];positionExpr.height=contentSize[1];var layoutRect=getLayoutRect(positionExpr,{width:viewWidth,height:viewHeight});x=layoutRect.x;y=layoutRect.y;align=null;// When positionExpr is left/top/right/bottom,\n// align and verticalAlign will not work.\nvAlign=null;}// Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element\nelse if(typeof positionExpr==='string'&&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(tooltipModel.get('confine')){var pos=confineTooltipPosition(x,y,content,viewWidth,viewHeight);x=pos[0];y=pos[1];}content.moveTo(x,y);},// FIXME\n// Should we remove this but leave this to user?\n_updateContentNotChangedOnAxis:function _updateContentNotChangedOnAxis(dataByCoordSys){var lastCoordSys=this._lastDataByCoordSys;var contentNotChanged=!!lastCoordSys&&lastCoordSys.length===dataByCoordSys.length;contentNotChanged&&each$9(lastCoordSys,function(lastItemCoordSys,indexCoordSys){var lastDataByAxis=lastItemCoordSys.dataByAxis||{};var thisItemCoordSys=dataByCoordSys[indexCoordSys]||{};var thisDataByAxis=thisItemCoordSys.dataByAxis||[];contentNotChanged&=lastDataByAxis.length===thisDataByAxis.length;contentNotChanged&&each$9(lastDataByAxis,function(lastItem,indexAxis){var thisItem=thisDataByAxis[indexAxis]||{};var lastIndices=lastItem.seriesDataIndices||[];var newIndices=thisItem.seriesDataIndices||[];contentNotChanged&=lastItem.value===thisItem.value&&lastItem.axisType===thisItem.axisType&&lastItem.axisId===thisItem.axisId&&lastIndices.length===newIndices.length;contentNotChanged&&each$9(lastIndices,function(lastIdxItem,j){var newIdxItem=newIndices[j];contentNotChanged&=lastIdxItem.seriesIndex===newIdxItem.seriesIndex&&lastIdxItem.dataIndex===newIdxItem.dataIndex;});});});this._lastDataByCoordSys=dataByCoordSys;return!!contentNotChanged;},_hide:function _hide(dispatchAction){// Do not directly hideLater here, because this behavior may be prevented\n// in dispatchAction when showTip is dispatched.\n// FIXME\n// duplicated hideTip if manuallyHideTip is called from dispatchAction.\nthis._lastDataByCoordSys=null;dispatchAction({type:'hideTip',from:this.uid});},dispose:function dispose(ecModel,api){if(env$1.node){return;}this._tooltipContent.dispose();unregister('itemTooltip',api);}});/**\n * @param {Array.<Object|module:echarts/model/Model>} modelCascade\n * From top to bottom. (the last one should be globalTooltipModel);\n */function buildTooltipModel(modelCascade){var resultModel=modelCascade.pop();while(modelCascade.length){var tooltipOpt=modelCascade.pop();if(tooltipOpt){if(Model.isInstance(tooltipOpt)){tooltipOpt=tooltipOpt.get('tooltip',true);}// In each data item tooltip can be simply write:\n// {\n//  value: 10,\n//  tooltip: 'Something you need to know'\n// }\nif(typeof tooltipOpt==='string'){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>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=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;y=rect.y+rectHeight/2-domHeight/2;break;case'right':x=rect.x+rectWidth+gap;y=rect.y+rectHeight/2-domHeight/2;}return[x,y];}function isCenterAlign(align){return align==='center'||align==='middle';}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // FIXME Better way to pack data in graphic element\n/**\n * @action\n * @property {string} type\n * @property {number} seriesIndex\n * @property {number} dataIndex\n * @property {number} [x]\n * @property {number} [y]\n */registerAction({type:'showTip',event:'showTip',update:'tooltip:manuallyShowTip'},// noop\nfunction(){});registerAction({type:'hideTip',event:'hideTip',update:'tooltip:manuallyHideTip'},// noop\nfunction(){});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var langSelector=lang.legend.selector;var defaultSelectorOption={all:{type:'all',title:_clone(langSelector.all)},inverse:{type:'inverse',title:_clone(langSelector.inverse)}};var LegendModel=extendComponentModel({type:'legend.plain',dependencies:['series'],layoutMode:{type:'box',// legend.width/height are maxWidth/maxHeight actually,\n// whereas realy width/height is calculated by its content.\n// (Setting {left: 10, right: 10} does not make sense).\n// So consider the case:\n// `setOption({legend: {left: 10});`\n// then `setOption({legend: {right: 10});`\n// The previous `left` should be cleared by setting `ignoreSize`.\nignoreSize:true},init:function init(option,parentModel,ecModel){this.mergeDefaultAndTheme(option,ecModel);option.selected=option.selected||{};this._updateSelector(option);},mergeOption:function mergeOption(option){LegendModel.superCall(this,'mergeOption',option);this._updateSelector(option);},_updateSelector:function _updateSelector(option){var selector=option.selector;if(selector===true){selector=option.selector=['all','inverse'];}if(isArray(selector)){each$1(selector,function(item,index){isString(item)&&(item={type:item});selector[index]=merge(item,defaultSelectorOption[item.type]);});}},optionUpdated:function optionUpdated(){this._updateData(this.ecModel);var legendData=this._data;// If selectedMode is single, try to select one\nif(legendData[0]&&this.get('selectedMode')==='single'){var hasSelected=false;// If has any selected in option.selected\nfor(var i=0;i<legendData.length;i++){var name=legendData[i].get('name');if(this.isSelected(name)){// Force to unselect others\nthis.select(name);hasSelected=true;break;}}// Try select the first if selectedMode is single\n!hasSelected&&this.select(legendData[0].get('name'));}},_updateData:function _updateData(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);}});/**\n         * @type {Array.<string>}\n         * @private\n         */this._availableNames=availableNames;// If legend.data not specified in option, use availableNames as data,\n// which is convinient for user preparing option.\nvar rawData=this.get('data')||potentialData;var legendData=map(rawData,function(dataItem){// Can be string or number\nif(typeof dataItem==='string'||typeof dataItem==='number'){dataItem={name:dataItem};}return new Model(dataItem,this,this.ecModel);},this);/**\n         * @type {Array.<module:echarts/model/Model>}\n         * @private\n         */this._data=legendData;},/**\n     * @return {Array.<module:echarts/model/Model>}\n     */getData:function getData(){return this._data;},/**\n     * @param {string} name\n     */select:function select(name){var selected=this.option.selected;var selectedMode=this.get('selectedMode');if(selectedMode==='single'){var data=this._data;each$1(data,function(dataItem){selected[dataItem.get('name')]=false;});}selected[name]=true;},/**\n     * @param {string} name\n     */unSelect:function unSelect(name){if(this.get('selectedMode')!=='single'){this.option.selected[name]=false;}},/**\n     * @param {string} name\n     */toggleSelected:function toggleSelected(name){var selected=this.option.selected;// Default is true\nif(!selected.hasOwnProperty(name)){selected[name]=true;}this[selected[name]?'unSelect':'select'](name);},allSelect:function allSelect(){var data=this._data;var selected=this.option.selected;each$1(data,function(dataItem){selected[dataItem.get('name',true)]=true;});},inverseSelect:function inverseSelect(){var data=this._data;var selected=this.option.selected;each$1(data,function(dataItem){var name=dataItem.get('name',true);// Initially, default value is true\nif(!selected.hasOwnProperty(name)){selected[name]=true;}selected[name]=!selected[name];});},/**\n     * @param {string} name\n     */isSelected:function isSelected(name){var selected=this.option.selected;return!(selected.hasOwnProperty(name)&&!selected[name])&&indexOf(this._availableNames,name)>=0;},getOrient:function getOrient(){return this.get('orient')==='vertical'?{index:1,name:'vertical'}:{index:0,name:'horizontal'};},defaultOption:{// 一级层叠\nzlevel:0,// 二级层叠\nz:4,show:true,// 布局方式，默认为水平布局，可选为：\n// 'horizontal' | 'vertical'\norient:'horizontal',left:'center',// right: 'center',\ntop:0,// bottom: null,\n// 水平对齐\n// 'auto' | 'left' | 'right'\n// 默认为 'auto', 根据 x 的位置判断是左对齐还是右对齐\nalign:'auto',backgroundColor:'rgba(0,0,0,0)',// 图例边框颜色\nborderColor:'#ccc',borderRadius:0,// 图例边框线宽，单位px，默认为0（无边框）\nborderWidth:0,// 图例内边距，单位px，默认各方向内边距为5，\n// 接受数组分别设定上右下左边距，同css\npadding:5,// 各个item之间的间隔，单位px，默认为10，\n// 横向布局时为水平间隔，纵向布局时为纵向间隔\nitemGap:10,// the width of legend symbol\nitemWidth:25,// the height of legend symbol\nitemHeight:14,// the color of unselected legend symbol\ninactiveColor:'#ccc',// the borderColor of unselected legend symbol\ninactiveBorderColor:'#ccc',itemStyle:{// the default borderWidth of legend symbol\nborderWidth:0},textStyle:{// 图例文字颜色\ncolor:'#333'},// formatter: '',\n// 选择模式，默认开启图例开关\nselectedMode:true,// 配置默认选中状态，可配合LEGEND.SELECTED事件做动态数据载入\n// selected: null,\n// 图例内容（详见legend.data，数组中每一项代表一个item\n// data: [],\n// Usage:\n// selector: [{type: 'all or inverse', title: xxx}]\n// or\n// selector: true\n// or\n// selector: ['all', 'inverse']\nselector: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'}},// Value can be 'start' or 'end'\nselectorPosition:'auto',selectorItemGap:7,selectorButtonGap:10,// Tooltip 相关配置\ntooltip:{show:false}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function legendSelectActionHandler(methodName,payload,ecModel){var selectedMap={};var isToggleSelect=methodName==='toggleSelected';var isSelected;// Update all legend components\necModel.eachComponent('legend',function(legendModel){if(isToggleSelect&&isSelected!=null){// Force other legend has same selected status\n// Or the first is toggled to true and other are toggled to false\n// In the case one legend has some item unSelected in option. And if other legend\n// doesn't has the item, they will assume it is selected.\nlegendModel[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$1(legendData,function(model){var name=model.get('name');// Wrap element\nif(name==='\\n'||name===''){return;}var isItemSelected=legendModel.isSelected(name);if(selectedMap.hasOwnProperty(name)){// Unselected if any legend is unselected\nselectedMap[name]=selectedMap[name]&&isItemSelected;}else{selectedMap[name]=isItemSelected;}});});// Return the event explicitly\nreturn methodName==='allSelect'||methodName==='inverseSelect'?{selected:selectedMap}:{name:payload.name,selected:selectedMap};}/**\n * @event legendToggleSelect\n * @type {Object}\n * @property {string} type 'legendToggleSelect'\n * @property {string} [from]\n * @property {string} name Series name or data item name\n */registerAction('legendToggleSelect','legendselectchanged',curry(legendSelectActionHandler,'toggleSelected'));registerAction('legendAllSelect','legendselectall',curry(legendSelectActionHandler,'allSelect'));registerAction('legendInverseSelect','legendinverseselect',curry(legendSelectActionHandler,'inverseSelect'));/**\n * @event legendSelect\n * @type {Object}\n * @property {string} type 'legendSelect'\n * @property {string} name Series name or data item name\n */registerAction('legendSelect','legendselected',curry(legendSelectActionHandler,'select'));/**\n * @event legendUnSelect\n * @type {Object}\n * @property {string} type 'legendUnSelect'\n * @property {string} name Series name or data item name\n */registerAction('legendUnSelect','legendunselected',curry(legendSelectActionHandler,'unSelect'));/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Layout list like component.\n * It will box layout each items in group of component and then position the whole group in the viewport\n * @param {module:zrender/group/Group} group\n * @param {module:echarts/model/Component} componentModel\n * @param {module:echarts/ExtensionAPI}\n */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');var 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});// FIXME\n// `subPixelOptimizeRect` may bring some gap between edge of viewpart\n// and background rect when setting like `left: 0`, `top: 0`.\n// graphic.subPixelOptimizeRect(rect);\nreturn rect;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var curry$3=curry;var each$11=each$1;var Group$2=Group;var LegendView=extendComponentView({type:'legend.plain',newlineDisabled:false,/**\n     * @override\n     */init:function init(){/**\n         * @private\n         * @type {module:zrender/container/Group}\n         */this.group.add(this._contentGroup=new Group$2());/**\n         * @private\n         * @type {module:zrender/Element}\n         */this._backgroundEl;/**\n         * @private\n         * @type {module:zrender/container/Group}\n         */this.group.add(this._selectorGroup=new Group$2());/**\n         * If first rendering, `contentGroup.position` is [0, 0], which\n         * does not make sense and may cause unexepcted animation if adopted.\n         * @private\n         * @type {boolean}\n         */this._isFirstRender=true;},/**\n     * @protected\n     */getContentGroup:function getContentGroup(){return this._contentGroup;},/**\n     * @protected\n     */getSelectorGroup:function getSelectorGroup(){return this._selectorGroup;},/**\n     * @override\n     */render:function render(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);// Perform layout.\nvar 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);// Place mainGroup, based on the calculated `mainRect`.\nvar layoutRect=getLayoutRect(defaults({width:mainRect.width,height:mainRect.height},positionInfo),viewportSize,padding);this.group.attr('position',[layoutRect.x-mainRect.x,layoutRect.y-mainRect.y]);// Render background after group is layout.\nthis.group.add(this._backgroundEl=makeBackground(mainRect,legendModel));},/**\n     * @protected\n     */resetInner:function resetInner(){this.getContentGroup().removeAll();this._backgroundEl&&this.group.remove(this._backgroundEl);this.getSelectorGroup().removeAll();},/**\n     * @protected\n     */renderInner:function renderInner(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$11(legendModel.getData(),function(itemModel,dataIndex){var name=itemModel.get('name');// Use empty string or \\n as a newline string\nif(!this.newlineDisabled&&(name===''||name==='\\n')){contentGroup.add(new Group$2({newline:true}));return;}// Representitive series.\nvar seriesModel=ecModel.getSeriesByName(name)[0];if(legendDrawnMap.get(name)){// Have been drawed\nreturn;}// Legend to control series.\nif(seriesModel){var data=seriesModel.getData();var color=data.getVisual('color');var borderColor=data.getVisual('borderColor');// If color is a callback function\nif(typeof color==='function'){// Use the first data\ncolor=color(seriesModel.getDataParams(0));}// If borderColor is a callback function\nif(typeof borderColor==='function'){// Use the first data\nborderColor=borderColor(seriesModel.getDataParams(0));}// Using rect symbol defaultly\nvar legendSymbolType=data.getVisual('legendSymbol')||'roundRect';var symbolType=data.getVisual('symbol');var itemGroup=this._createItem(name,dataIndex,itemModel,legendModel,legendSymbolType,symbolType,itemAlign,color,borderColor,selectMode);itemGroup.on('click',curry$3(dispatchSelectAction,name,null,api,excludeSeriesId)).on('mouseover',curry$3(dispatchHighlightAction,seriesModel.name,null,api,excludeSeriesId)).on('mouseout',curry$3(dispatchDownplayAction,seriesModel.name,null,api,excludeSeriesId));legendDrawnMap.set(name,true);}else{// Legend to control data. In pie and funnel.\necModel.eachRawSeries(function(seriesModel){// In case multiple series has same data name\nif(legendDrawnMap.get(name)){return;}if(seriesModel.legendVisualProvider){var provider=seriesModel.legendVisualProvider;if(!provider.containName(name)){return;}var idx=provider.indexOfName(name);var color=provider.getItemVisual(idx,'color');var borderColor=provider.getItemVisual(idx,'borderColor');var legendSymbolType='roundRect';var itemGroup=this._createItem(name,dataIndex,itemModel,legendModel,legendSymbolType,null,itemAlign,color,borderColor,selectMode);// FIXME: consider different series has items with the same name.\nitemGroup.on('click',curry$3(dispatchSelectAction,null,name,api,excludeSeriesId))// Should not specify the series name, consider legend controls\n// more than one pie series.\n.on('mouseover',curry$3(dispatchHighlightAction,null,name,api,excludeSeriesId)).on('mouseout',curry$3(dispatchDownplayAction,null,name,api,excludeSeriesId));legendDrawnMap.set(name,true);}},this);}if(__DEV__){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);}},_createSelector:function _createSelector(selector,legendModel,api,orient,selectorPosition){var selectorGroup=this.getSelectorGroup();each$11(selector,function(selectorItem){createSelectorButton(selectorItem);});function createSelectorButton(selectorItem){var type=selectorItem.type;var labelText=new Text({style:{x:0,y:0,align:'center',verticalAlign:'middle'},onclick:function onclick(){api.dispatchAction({type:type==='all'?'legendAllSelect':'legendInverseSelect'});}});selectorGroup.add(labelText);var labelModel=legendModel.getModel('selectorLabel');var emphasisLabelModel=legendModel.getModel('emphasis.selectorLabel');setLabelStyle(labelText.style,labelText.hoverStyle={},labelModel,emphasisLabelModel,{defaultText:selectorItem.title,isRectText:false});setHoverStyle(labelText);}},_createItem:function _createItem(name,dataIndex,itemModel,legendModel,legendSymbolType,symbolType,itemAlign,color,borderColor,selectMode){var itemWidth=legendModel.get('itemWidth');var itemHeight=legendModel.get('itemHeight');var inactiveColor=legendModel.get('inactiveColor');var inactiveBorderColor=legendModel.get('inactiveBorderColor');var symbolKeepAspect=legendModel.get('symbolKeepAspect');var legendModelItemStyle=legendModel.getModel('itemStyle');var isSelected=legendModel.isSelected(name);var itemGroup=new Group$2();var textStyleModel=itemModel.getModel('textStyle');var itemIcon=itemModel.get('icon');var tooltipModel=itemModel.getModel('tooltip');var legendGlobalTooltipModel=tooltipModel.parentModel;// Use user given icon first\nlegendSymbolType=itemIcon||legendSymbolType;var legendSymbol=createSymbol(legendSymbolType,0,0,itemWidth,itemHeight,isSelected?color:inactiveColor,// symbolKeepAspect default true for legend\nsymbolKeepAspect==null?true:symbolKeepAspect);itemGroup.add(setSymbolStyle(legendSymbol,legendSymbolType,legendModelItemStyle,borderColor,inactiveBorderColor,isSelected));// Compose symbols\n// PENDING\nif(!itemIcon&&symbolType// At least show one symbol, can't be all none\n&&(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 default true for legend\nsymbolKeepAspect==null?true:symbolKeepAspect);// Put symbol in the center\nitemGroup.add(setSymbolStyle(legendSymbolCenter,symbolType,legendModelItemStyle,borderColor,inactiveBorderColor,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 Text({style:setTextStyle({},textStyleModel,{text:content,x:textX,y:itemHeight/2,textFill:isSelected?textStyleModel.getTextColor():inactiveColor,textAlign:textAlign,textVerticalAlign:'middle'})}));// Add a invisible rect to increase the area of mouse hover\nvar hitRect=new Rect({shape:itemGroup.getBoundingRect(),invisible:true,tooltip:tooltipModel.get('show')?extend({content:name,// Defaul formatter\nformatter:legendGlobalTooltipModel.get('formatter',true)||function(){return name;},formatterParams:{componentType:'legend',legendIndex:legendModel.componentIndex,name:name,$vars:['name']}},tooltipModel.option):null});itemGroup.add(hitRect);itemGroup.eachChild(function(child){child.silent=true;});hitRect.silent=!selectMode;this.getContentGroup().add(itemGroup);setHoverStyle(itemGroup);itemGroup.__legendDataIndex=dataIndex;return itemGroup;},/**\n     * @protected\n     */layoutInner:function layoutInner(legendModel,itemAlign,maxSize,isFirstRender,selector,selectorPosition){var contentGroup=this.getContentGroup();var selectorGroup=this.getSelectorGroup();// Place items in contentGroup.\nbox(legendModel.get('orient'),contentGroup,legendModel.get('itemGap'),maxSize.width,maxSize.height);var contentRect=contentGroup.getBoundingRect();var contentPos=[-contentRect.x,-contentRect.y];if(selector){// Place buttons in selectorGroup\nbox(// Buttons in selectorGroup always layout horizontally\n'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;}//Always align selector to content as 'middle'\nselectorPos[1-orientIdx]+=contentRect[hw]/2-selectorRect[hw]/2;selectorGroup.attr('position',selectorPos);contentGroup.attr('position',contentPos);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.attr('position',contentPos);return this.group.getBoundingRect();}},/**\n     * @protected\n     */remove:function remove(){this.getContentGroup().removeAll();this._isFirstRender=true;}});function setSymbolStyle(symbol,symbolType,legendModelItemStyle,borderColor,inactiveBorderColor,isSelected){var itemStyle;if(symbolType!=='line'&&symbolType.indexOf('empty')<0){itemStyle=legendModelItemStyle.getItemStyle();symbol.style.stroke=borderColor;if(!isSelected){itemStyle.stroke=inactiveBorderColor;}}else{itemStyle=legendModelItemStyle.getItemStyle(['borderWidth','borderColor']);}return symbol.setStyle(itemStyle);}function dispatchSelectAction(seriesName,dataName,api,excludeSeriesId){// downplay before unselect\ndispatchDownplayAction(seriesName,dataName,api,excludeSeriesId);api.dispatchAction({type:'legendToggleSelect',name:seriesName!=null?seriesName:dataName});// highlight after select\ndispatchHighlightAction(seriesName,dataName,api,excludeSeriesId);}function dispatchHighlightAction(seriesName,dataName,api,excludeSeriesId){// If element hover will move to a hoverLayer.\nvar el=api.getZr().storage.getDisplayList()[0];if(!(el&&el.useHoverLayer)){api.dispatchAction({type:'highlight',seriesName:seriesName,name:dataName,excludeSeriesId:excludeSeriesId});}}function dispatchDownplayAction(seriesName,dataName,api,excludeSeriesId){// If element hover will move to a hoverLayer.\nvar el=api.getZr().storage.getDisplayList()[0];if(!(el&&el.useHoverLayer)){api.dispatchAction({type:'downplay',seriesName:seriesName,name:dataName,excludeSeriesId:excludeSeriesId});}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var legendFilter=function legendFilter(ecModel){var legendModels=ecModel.findComponents({mainType:'legend'});if(legendModels&&legendModels.length){ecModel.filterSeries(function(series){// If in any legend component the status is not selected.\n// Because in legend series is assumed selected when it is not in the legend data.\nfor(var i=0;i<legendModels.length;i++){if(!legendModels[i].isSelected(series.name)){return false;}}return true;});}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Do not contain scrollable legend, for sake of file size.\n// Series Filter\nregisterProcessor(PRIORITY.PROCESSOR.SERIES_FILTER,legendFilter);ComponentModel.registerSubTypeDefaulter('legend',function(){// Default 'plain' when no type specified.\nreturn'plain';});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var ScrollableLegendModel=LegendModel.extend({type:'legend.scroll',/**\n     * @param {number} scrollDataIndex\n     */setScrollDataIndex:function setScrollDataIndex(scrollDataIndex){this.option.scrollDataIndex=scrollDataIndex;},defaultOption:{scrollDataIndex:0,pageButtonItemGap:5,pageButtonGap:null,pageButtonPosition:'end',// 'start' or 'end'\npageFormatter:'{current}/{total}',// If null/undefined, do not show page.\npageIcons:{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,// Can be [10, 3], which represents [width, height]\npageTextStyle:{color:'#333'},animationDurationUpdate:800},/**\n     * @override\n     */init:function init(option,parentModel,ecModel,extraOpt){var inputPositionParams=getLayoutParams(option);ScrollableLegendModel.superCall(this,'init',option,parentModel,ecModel,extraOpt);mergeAndNormalizeLayoutParams(this,option,inputPositionParams);},/**\n     * @override\n     */mergeOption:function mergeOption(option,extraOpt){ScrollableLegendModel.superCall(this,'mergeOption',option,extraOpt);mergeAndNormalizeLayoutParams(this,this.option,option);}});// Do not `ignoreSize` to enable setting {left: 10, right: 10}.\nfunction mergeAndNormalizeLayoutParams(legendModel,target,raw){var orient=legendModel.getOrient();var ignoreSize=[1,1];ignoreSize[orient.index]=0;mergeLayoutParam(target,raw,{type:'box',ignoreSize:ignoreSize});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Separate legend and scrollable legend to reduce package size.\n */var Group$3=Group;var WH=['width','height'];var XY=['x','y'];var ScrollableLegendView=LegendView.extend({type:'legend.scroll',newlineDisabled:true,init:function init(){ScrollableLegendView.superCall(this,'init');/**\n         * @private\n         * @type {number} For `scroll`.\n         */this._currentIndex=0;/**\n         * @private\n         * @type {module:zrender/container/Group}\n         */this.group.add(this._containerGroup=new Group$3());this._containerGroup.add(this.getContentGroup());/**\n         * @private\n         * @type {module:zrender/container/Group}\n         */this.group.add(this._controllerGroup=new Group$3());/**\n         *\n         * @private\n         */this._showController;},/**\n     * @override\n     */resetInner:function resetInner(){ScrollableLegendView.superCall(this,'resetInner');this._controllerGroup.removeAll();this._containerGroup.removeClipPath();this._containerGroup.__rectSize=null;},/**\n     * @override\n     */renderInner:function renderInner(itemAlign,legendModel,ecModel,api,selector,orient,selectorPosition){var me=this;// Render content items.\nScrollableLegendView.superCall(this,'renderInner',itemAlign,legendModel,ecModel,api,selector,orient,selectorPosition);var controllerGroup=this._controllerGroup;// FIXME: support be 'auto' adapt to size number text length,\n// e.g., '3/12345' should not overlap with the control arrow button.\nvar pageIconSize=legendModel.get('pageIconSize',true);if(!isArray(pageIconSize)){pageIconSize=[pageIconSize,pageIconSize];}createPageButton('pagePrev',0);var pageTextStyleModel=legendModel.getModel('pageTextStyle');controllerGroup.add(new Text({name:'pageText',style:{textFill:pageTextStyleModel.getTextColor(),font:pageTextStyleModel.getFont(),textVerticalAlign:'middle',textAlign:'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],{// Buttons will be created in each render, so we do not need\n// to worry about avoiding using legendModel kept in scope.\nonclick:bind(me._pageGo,me,pageDataIndexName,legendModel,api)},{x:-pageIconSize[0]/2,y:-pageIconSize[1]/2,width:pageIconSize[0],height:pageIconSize[1]});icon.name=name;controllerGroup.add(icon);}},/**\n     * @override\n     */layoutInner:function layoutInner(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(// Buttons in selectorGroup always layout horizontally\n'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);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.attr('position',selectorPos);}return mainRect;},_layoutContentAndController:function _layoutContentAndController(legendModel,isFirstRender,maxSize,orientIdx,wh,hw,yx){var contentGroup=this.getContentGroup();var containerGroup=this._containerGroup;var controllerGroup=this._controllerGroup;// Place items in contentGroup.\nbox(legendModel.get('orient'),contentGroup,legendModel.get('itemGap'),!orientIdx?null:maxSize.width,orientIdx?null:maxSize.height);box(// Buttons in controller are layout always horizontally.\n'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];// Remain contentPos when scroll animation perfroming.\n// If first rendering, `contentGroup.position` is [0, 0], which\n// does not make sense and may cause unexepcted animation if adopted.\nif(!isFirstRender){contentPos[orientIdx]=contentGroup.position[orientIdx];}// Layout container group based on 0.\nvar containerPos=[0,0];var controllerPos=[-controllerRect.x,-controllerRect.y];var pageButtonGap=retrieve2(legendModel.get('pageButtonGap',true),legendModel.get('itemGap',true));// Place containerGroup and controllerGroup and contentGroup.\nif(showController){var pageButtonPosition=legendModel.get('pageButtonPosition',true);// controller is on the right / bottom.\nif(pageButtonPosition==='end'){controllerPos[orientIdx]+=maxSize[wh]-controllerRect[wh];}// controller is on the left / top.\nelse{containerPos[orientIdx]+=controllerRect[wh]+pageButtonGap;}}// Always align controller to content as 'middle'.\ncontrollerPos[1-orientIdx]+=contentRect[hw]/2-controllerRect[hw]/2;contentGroup.attr('position',contentPos);containerGroup.attr('position',containerPos);controllerGroup.attr('position',controllerPos);// Calculate `mainRect` and set `clipPath`.\n// mainRect should not be calculated by `this.group.getBoundingRect()`\n// for sake of the overflow.\nvar mainRect={x:0,y:0};// Consider content may be overflow (should be clipped).\nmainRect[wh]=showController?maxSize[wh]:contentRect[wh];mainRect[hw]=Math.max(contentRect[hw],controllerRect[hw]);// `containerRect[yx] + containerPos[1 - orientIdx]` is 0.\nmainRect[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}));// Consider content may be larger than container, container rect\n// can not be obtained from `containerGroup.getBoundingRect()`.\ncontainerGroup.__rectSize=clipShape[wh];}else{// Do not remove or ignore controller. Keep them set as placeholders.\ncontrollerGroup.eachChild(function(child){child.attr({invisible:true,silent:true});});}// Content translate animation.\nvar pageInfo=this._getPageInfo(legendModel);pageInfo.pageIndex!=null&&updateProps(contentGroup,{position:pageInfo.contentPosition},// When switch from \"show controller\" to \"not show controller\", view should be\n// updated immediately without animation, otherwise causes weird effect.\nshowController?legendModel:false);this._updatePageInfoView(legendModel,pageInfo);return mainRect;},_pageGo:function _pageGo(to,legendModel,api){var scrollDataIndex=this._getPageInfo(legendModel)[to];scrollDataIndex!=null&&api.dispatchAction({type:'legendScroll',scrollDataIndex:scrollDataIndex,legendId:legendModel.id});},_updatePageInfoView:function _updatePageInfoView(legendModel,pageInfo){var controllerGroup=this._controllerGroup;each$1(['pagePrev','pageNext'],function(name){var canJump=pageInfo[name+'DataIndex']!=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).replace('{total}',total):pageFormatter({current:current,total:total}));},/**\n     * @param {module:echarts/model/Model} legendModel\n     * @return {Object} {\n     *  contentPosition: Array.<number>, null when data item not found.\n     *  pageIndex: number, null when data item not found.\n     *  pageCount: number, always be a number, can be 0.\n     *  pagePrevDataIndex: number, null when no previous page.\n     *  pageNextDataIndex: number, null when no next page.\n     * }\n     */_getPageInfo:function _getPageInfo(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.position.slice(),pageCount:pCount,pageIndex:pCount-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!targetItem){return result;}var targetItemInfo=getItemInfo(targetItem);result.contentPosition[orientIdx]=-targetItemInfo.s;// Strategy:\n// (1) Always align based on the left/top most item.\n// (2) It is user-friendly that the last item shown in the\n// current window is shown at the begining of next window.\n// Otherwise if half of the last item is cut by the window,\n// it will have no chance to display entirely.\n// (3) Consider that item size probably be different, we\n// have calculate pageIndex by size rather than item index,\n// and we can not get page index directly by division.\n// (4) The window is to narrow to contain more than\n// one item, we should make sure that the page can be fliped.\nfor(var i=targetItemIndex+1,winStartItemInfo=targetItemInfo,winEndItemInfo=targetItemInfo,currItemInfo=null;i<=itemCount;++i){currItemInfo=getItemInfo(children[i]);if(// Half of the last item is out of the window.\n!currItemInfo&&winEndItemInfo.e>winStartItemInfo.s+containerRectSize||// If the current item does not intersect with the window, the new page\n// can be started at the current item or the last item.\ncurrItemInfo&&!intersect(currItemInfo,winStartItemInfo.s)){if(winEndItemInfo.i>winStartItemInfo.i){winStartItemInfo=winEndItemInfo;}else{// e.g., when page size is smaller than item size.\nwinStartItemInfo=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(// If the the end item does not intersect with the window started\n// from the current item, a page can be settled.\n(!currItemInfo||!intersect(winEndItemInfo,currItemInfo.s))&&// e.g., when page size is smaller than item size.\nwinStartItemInfo.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.position[orientIdx];return{s:start,e:start+itemRect[wh],i:el.__legendDataIndex};}}function intersect(itemInfo,winStart){return itemInfo.e>=winStart&&itemInfo.s<=winStart+containerRectSize;}},_findTargetItemIndex:function _findTargetItemIndex(targetDataIndex){if(!this._showController){return 0;}var index;var contentGroup=this.getContentGroup();var defaultIndex;contentGroup.eachChild(function(child,idx){var legendDataIdx=child.__legendDataIndex;// FIXME\n// If the given targetDataIndex (from model) is illegal,\n// we use defaultIndex. But the index on the legend model and\n// action payload is still illegal. That case will not be\n// changed until some scenario requires.\nif(defaultIndex==null&&legendDataIdx!=null){defaultIndex=idx;}if(legendDataIdx===targetDataIndex){index=idx;}});return index!=null?index:defaultIndex;}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @event legendScroll\n * @type {Object}\n * @property {string} type 'legendScroll'\n * @property {string} scrollDataIndex\n */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);});});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Legend component entry file8\n */ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Model\nextendComponentModel({type:'title',layoutMode:{type:'box',ignoreSize:true},defaultOption:{// 一级层叠\nzlevel:0,// 二级层叠\nz:6,show:true,text:'',// 超链接跳转\n// link: null,\n// 仅支持self | blank\ntarget:'blank',subtext:'',// 超链接跳转\n// sublink: null,\n// 仅支持self | blank\nsubtarget:'blank',// 'center' ¦ 'left' ¦ 'right'\n// ¦ {number}（x坐标，单位px）\nleft:0,// 'top' ¦ 'bottom' ¦ 'center'\n// ¦ {number}（y坐标，单位px）\ntop:0,// 水平对齐\n// 'auto' | 'left' | 'right' | 'center'\n// 默认根据 left 的位置判断是左对齐还是右对齐\n// textAlign: null\n//\n// 垂直对齐\n// 'auto' | 'top' | 'bottom' | 'middle'\n// 默认根据 top 位置判断是上对齐还是下对齐\n// textVerticalAlign: null\n// textBaseline: null // The same as textVerticalAlign.\nbackgroundColor:'rgba(0,0,0,0)',// 标题边框颜色\nborderColor:'#ccc',// 标题边框线宽，单位px，默认为0（无边框）\nborderWidth:0,// 标题内边距，单位px，默认各方向内边距为5，\n// 接受数组分别设定上右下左边距，同css\npadding:5,// 主副标题纵向间隔，单位px，默认为10，\nitemGap:10,textStyle:{fontSize:18,fontWeight:'bolder',color:'#333'},subtextStyle:{color:'#aaa'}}});// View\nextendComponentView({type:'title',render:function render(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 Text({style:setTextStyle({},textStyleModel,{text:titleModel.get('text'),textFill:textStyleModel.getTextColor()},{disableBox:true}),z2:10});var textRect=textEl.getBoundingRect();var subText=titleModel.get('subtext');var subTextEl=new Text({style:setTextStyle({},subtextStyleModel,{text:subText,textFill:subtextStyleModel.getTextColor(),y:textRect.height+titleModel.get('itemGap'),textVerticalAlign:'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'));});}textEl.eventData=subTextEl.eventData=triggerEvent?{componentType:'title',componentIndex:titleModel.componentIndex}:null;group.add(textEl);subText&&group.add(subTextEl);// If no subText, but add subTextEl, there will be an empty line.\nvar 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'));// Adjust text align based on position\nif(!textAlign){// Align left if title is on the left. center and right is same\ntextAlign=titleModel.get('left')||titleModel.get('right');if(textAlign==='middle'){textAlign='center';}// Adjust layout by text align\nif(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.attr('position',[layoutRect.x,layoutRect.y]);var alignStyle={textAlign:textAlign,textVerticalAlign:textVerticalAlign};textEl.setStyle(alignStyle);subTextEl.setStyle(alignStyle);// Render background\n// Get groupRect again because textAlign has been changed\ngroupRect=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);}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var addCommas$1=addCommas;var encodeHTML$1=encodeHTML;function fillLabel(opt){defaultEmphasis(opt,'label',['show']);}var MarkerModel=extendComponentModel({type:'marker',dependencies:['series','grid','polar','geo'],/**\n     * @overrite\n     */init:function init(option,parentModel,ecModel){if(__DEV__){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);},/**\n     * @return {boolean}\n     */isAnimationEnabled:function isAnimationEnabled(){if(env$1.node){return false;}var hostSeries=this.__hostSeries;return this.getShallow('animation')&&hostSeries&&hostSeries.isAnimationEnabled();},/**\n     * @overrite\n     */mergeOption:function mergeOption(newOpt,ecModel){this._mergeOption(newOpt,ecModel,false,false);},_mergeOption:function _mergeOption(newOpt,ecModel,createdBySelf,isInit){var MarkerModel=this.constructor;var modelPropName=this.mainType+'Model';if(!createdBySelf){ecModel.eachSeries(function(seriesModel){var markerOpt=seriesModel.get(this.mainType,true);var markerModel=seriesModel[modelPropName];if(!markerOpt||!markerOpt.data){seriesModel[modelPropName]=null;return;}if(!markerModel){if(isInit){// Default label emphasis `position` and `show`\nfillLabel(markerOpt);}each$1(markerOpt.data,function(item){// FIXME Overwrite fillLabel method ?\nif(item instanceof Array){fillLabel(item[0]);fillLabel(item[1]);}else{fillLabel(item);}});markerModel=new MarkerModel(markerOpt,this,ecModel);extend(markerModel,{mainType:this.mainType,// Use the same series index and name\nseriesIndex:seriesModel.seriesIndex,name:seriesModel.name,createdBySelf:true});markerModel.__hostSeries=seriesModel;}else{markerModel._mergeOption(markerOpt,ecModel,true);}seriesModel[modelPropName]=markerModel;},this);}},formatTooltip:function formatTooltip(dataIndex,multipleSeries,dataType,renderMode){var data=this.getData();var value=this.getRawValue(dataIndex);var formattedValue=isArray(value)?map(value,addCommas$1).join(', '):addCommas$1(value);var name=data.getName(dataIndex);var html=encodeHTML$1(this.name);var newLine=renderMode==='html'?'<br/>':'\\n';if(value!=null||name){html+=newLine;}if(name){html+=encodeHTML$1(name);if(value!=null){html+=' : ';}}if(value!=null){html+=encodeHTML$1(formattedValue);}return html;},getData:function getData(){return this._data;},setData:function setData(data){this._data=data;}});mixin(MarkerModel,dataFormatMixin);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/MarkerModel.extend({type:'markPoint',defaultOption:{zlevel:0,z:5,symbol:'pin',symbolSize:50,//symbolRotate: 0,\n//symbolOffset: [0, 0]\ntooltip:{trigger:'item'},label:{show:true,position:'inside'},itemStyle:{borderWidth:2},emphasis:{label:{show:true}}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var indexOf$1=indexOf;function hasXOrY(item){return!(isNaN(parseFloat(item.x))&&isNaN(parseFloat(item.y)));}function hasXAndY(item){return!isNaN(parseFloat(item.x))&&!isNaN(parseFloat(item.y));}// Make it simple, do not visit all stacked value to count precision.\n// function getPrecision(data, valueAxisDim, dataIndex) {\n//     var precision = -1;\n//     var stackedDim = data.mapDimension(valueAxisDim);\n//     do {\n//         precision = Math.max(\n//             numberUtil.getPrecision(data.get(stackedDim, dataIndex)),\n//             precision\n//         );\n//         var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');\n//         if (stackedOnSeries) {\n//             var byValue = data.get(data.getCalculationInfo('stackedByDimension'), dataIndex);\n//             data = stackedOnSeries.getData();\n//             dataIndex = data.indexOf(data.getCalculationInfo('stackedByDimension'), byValue);\n//             stackedDim = data.getCalculationInfo('stackedDimension');\n//         }\n//         else {\n//             data = null;\n//         }\n//     } while (data);\n//     return precision;\n// }\nfunction markerTypeCalculatorWithExtent(mlType,data,otherDataDim,targetDataDim,otherCoordIndex,targetCoordIndex){var coordArr=[];var stacked=isDimensionStacked(data,targetDataDim/*, otherDataDim*/);var calcDataDim=stacked?data.getCalculationInfo('stackResultDimension'):targetDataDim;var value=numCalculate(data,calcDataDim,mlType);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);// Make it simple, do not visit all stacked value to count precision.\nvar precision=getPrecision(data.get(targetDataDim,dataIndex));precision=Math.min(precision,20);if(precision>=0){coordArr[targetCoordIndex]=+coordArr[targetCoordIndex].toFixed(precision);}return[coordArr,coordArrValue];}var curry$4=curry;// TODO Specified percent\nvar markerTypeCalculator={/**\n     * @method\n     * @param {module:echarts/data/List} data\n     * @param {string} baseAxisDim\n     * @param {string} valueAxisDim\n     */min:curry$4(markerTypeCalculatorWithExtent,'min'),/**\n     * @method\n     * @param {module:echarts/data/List} data\n     * @param {string} baseAxisDim\n     * @param {string} valueAxisDim\n     */max:curry$4(markerTypeCalculatorWithExtent,'max'),/**\n     * @method\n     * @param {module:echarts/data/List} data\n     * @param {string} baseAxisDim\n     * @param {string} valueAxisDim\n     */average:curry$4(markerTypeCalculatorWithExtent,'average')};/**\n * Transform markPoint data item to format used in List by do the following\n * 1. Calculate statistic like `max`, `min`, `average`\n * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array\n * @param  {module:echarts/model/Series} seriesModel\n * @param  {module:echarts/coord/*} [coordSys]\n * @param  {Object} item\n * @return {Object}\n */function dataTransform(seriesModel,item){var data=seriesModel.getData();var coordSys=seriesModel.coordinateSystem;// 1. If not specify the position with pixel directly\n// 2. If `coord` is not a data array. Which uses `xAxis`,\n// `yAxis` to specify the coord on each dimension\n// parseFloat first because item.x and item.y can be percent string like '20%'\nif(item&&!hasXAndY(item)&&!isArray(item.coord)&&coordSys){var dims=coordSys.dimensions;var axisInfo=getAxisInfo$1(item,data,coordSys,seriesModel);// Clone the option\n// Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value\nitem=_clone(item);if(item.type&&markerTypeCalculator[item.type]&&axisInfo.baseAxis&&axisInfo.valueAxis){var otherCoordIndex=indexOf$1(dims,axisInfo.baseAxis.dim);var targetCoordIndex=indexOf$1(dims,axisInfo.valueAxis.dim);var coordInfo=markerTypeCalculator[item.type](data,axisInfo.baseDataDim,axisInfo.valueDataDim,otherCoordIndex,targetCoordIndex);item.coord=coordInfo[0];// Force to use the value of calculated value.\n// let item use the value without stack.\nitem.value=coordInfo[1];}else{// FIXME Only has one of xAxis and yAxis.\nvar coord=[item.xAxis!=null?item.xAxis:item.radiusAxis,item.yAxis!=null?item.yAxis:item.angleAxis];// Each coord support max, min, average\nfor(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;}}}/**\n * Filter data which is out of coordinateSystem range\n * [dataFilter description]\n * @param  {module:echarts/coord/*} [coordSys]\n * @param  {Object} item\n * @return {boolean}\n */function dataFilter$1(coordSys,item){// Alwalys return true if there is no coordSys\nreturn coordSys&&coordSys.containData&&item.coord&&!hasXOrY(item)?coordSys.containData(item.coord):true;}function dimValueGetter(item,dimName,dataIndex,dimIndex){// x, y, radius, angle\nif(dimIndex<2){return item.coord&&item.coord[dimIndex];}return item.value;}function numCalculate(data,valueDataDim,type){if(type==='average'){var sum=0;var count=0;data.each(valueDataDim,function(val,idx){if(!isNaN(val)){sum+=val;count++;}});return sum/count;}else if(type==='median'){return data.getMedian(valueDataDim);}else{// max & min\nreturn data.getDataExtent(valueDataDim,true)[type==='max'?1:0];}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var MarkerView=extendComponentView({type:'marker',init:function init(){/**\n         * Markline grouped by series\n         * @private\n         * @type {module:zrender/core/util.HashMap}\n         */this.markerGroupMap=createHashMap();},render:function render(markerModel,ecModel,api){var markerGroupMap=this.markerGroupMap;markerGroupMap.each(function(item){item.__keep=false;});var markerModelKey=this.type+'Model';ecModel.eachSeries(function(seriesModel){var markerModel=seriesModel[markerModelKey];markerModel&&this.renderSeries(seriesModel,markerModel,ecModel,api);},this);markerGroupMap.each(function(item){!item.__keep&&this.group.remove(item.group);},this);},renderSeries:function renderSeries(){}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function updateMarkerLayout(mpData,seriesModel,api){var coordSys=seriesModel.coordinateSystem;mpData.each(function(idx){var itemModel=mpData.getItemModel(idx);var point;var xPx=parsePercent$1(itemModel.get('x'),api.getWidth());var yPx=parsePercent$1(itemModel.get('y'),api.getHeight());if(!isNaN(xPx)&&!isNaN(yPx)){point=[xPx,yPx];}// Chart like bar may have there own marker positioning logic\nelse if(seriesModel.getMarkerPosition){// Use the getMarkerPoisition\npoint=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]);}// Use x, y if has any\nif(!isNaN(xPx)){point[0]=xPx;}if(!isNaN(yPx)){point[1]=yPx;}mpData.setItemLayout(idx,point);});}MarkerView.extend({type:'markPoint',// updateLayout: function (markPointModel, ecModel, api) {\n//     ecModel.eachSeries(function (seriesModel) {\n//         var mpModel = seriesModel.markPointModel;\n//         if (mpModel) {\n//             updateMarkerLayout(mpModel.getData(), seriesModel, api);\n//             this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel);\n//         }\n//     }, this);\n// },\nupdateTransform:function updateTransform(markPointModel,ecModel,api){ecModel.eachSeries(function(seriesModel){var mpModel=seriesModel.markPointModel;if(mpModel){updateMarkerLayout(mpModel.getData(),seriesModel,api);this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel);}},this);},renderSeries:function renderSeries(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);// FIXME\nmpModel.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');var isFnSymbol=isFunction$1(symbol);var isFnSymbolSize=isFunction$1(symbolSize);var isFnSymbolRotate=isFunction$1(symbolRotate);if(isFnSymbol||isFnSymbolSize||isFnSymbolRotate){var rawIdx=mpModel.getRawValue(idx);var dataParams=mpModel.getDataParams(idx);if(isFnSymbol){symbol=symbol(rawIdx,dataParams);}if(isFnSymbolSize){// FIXME 这里不兼容 ECharts 2.x，2.x 貌似参数是整个数据？\nsymbolSize=symbolSize(rawIdx,dataParams);}if(isFnSymbolRotate){symbolRotate=symbolRotate(rawIdx,dataParams);}}mpData.setItemVisual(idx,{symbol:symbol,symbolSize:symbolSize,symbolRotate:symbolRotate,color:itemModel.get('itemStyle.color')||seriesData.getVisual('color')});});// TODO Text are wrong\nsymbolDraw.updateData(mpData);this.group.add(symbolDraw.group);// Set host model for tooltip\n// FIXME\nmpData.eachItemGraphicEl(function(el){el.traverse(function(child){child.dataModel=mpModel;});});symbolDraw.__keep=true;symbolDraw.group.silent=mpModel.get('silent')||seriesModel.get('silent');}});/**\n * @inner\n * @param {module:echarts/coord/*} [coordSys]\n * @param {module:echarts/model/Series} seriesModel\n * @param {module:echarts/model/Model} mpModel\n */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))||{};// In map series data don't have lng and lat dimension. Fallback to same with coordSys\nreturn 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;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // HINT Markpoint can't be used too much\nregisterPreprocessor(function(opt){// Make sure markPoint component is enabled\nopt.markPoint=opt.markPoint||{};});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/MarkerModel.extend({type:'markLine',defaultOption:{zlevel:0,z:5,symbol:['circle','arrow'],symbolSize:[8,16],//symbolRotate: 0,\nprecision:2,tooltip:{trigger:'item'},label:{show:true,position:'end',distance:5},lineStyle:{type:'dashed'},emphasis:{label:{show:true},lineStyle:{width:3}},animationEasing:'linear'}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Line path for bezier and straight line draw\n */var straightLineProto=Line.prototype;var bezierCurveProto=BezierCurve.prototype;function isLine(shape){return isNaN(+shape.cpx1)||isNaN(+shape.cpy1);}var LinePath=extendShape({type:'ec-line',style:{stroke:'#000',fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function buildPath(ctx,shape){this[isLine(shape)?'_buildPathLine':'_buildPathCurve'](ctx,shape);},_buildPathLine:straightLineProto.buildPath,_buildPathCurve:bezierCurveProto.buildPath,pointAt:function pointAt(t){return this[isLine(this.shape)?'_pointAtLine':'_pointAtCurve'](t);},_pointAtLine:straightLineProto.pointAt,_pointAtCurve:bezierCurveProto.pointAt,tangentAt:function tangentAt(t){var shape=this.shape;var p=isLine(shape)?[shape.x2-shape.x1,shape.y2-shape.y1]:this._tangentAtCurve(t);return normalize(p,p);},_tangentAtCurve:bezierCurveProto.tangentAt});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/chart/helper/Line\n */var SYMBOL_CATEGORIES=['fromSymbol','toSymbol'];function makeSymbolTypeKey(symbolCategory){return'_'+symbolCategory+'Type';}/**\n * @inner\n */function createSymbol$1(name,lineData,idx){var symbolType=lineData.getItemVisual(idx,name);if(!symbolType||symbolType==='none'){return;}var color=lineData.getItemVisual(idx,'color');var symbolSize=lineData.getItemVisual(idx,name+'Size');var symbolRotate=lineData.getItemVisual(idx,name+'Rotate');if(!isArray(symbolSize)){symbolSize=[symbolSize,symbolSize];}var symbolPath=createSymbol(symbolType,-symbolSize[0]/2,-symbolSize[1]/2,symbolSize[0],symbolSize[1],color);// rotate by default if symbolRotate is not specified or NaN\nsymbolPath.__specifiedRotation=symbolRotate==null||isNaN(symbolRotate)?void 0:+symbolRotate*Math.PI/180||0;symbolPath.name=name;return symbolPath;}function createLine(points){var line=new LinePath({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;}}function updateSymbolAndLabelBeforeLineUpdate(){var lineGroup=this;var symbolFrom=lineGroup.childOfName('fromSymbol');var symbolTo=lineGroup.childOfName('toSymbol');var label=lineGroup.childOfName('label');// Quick reject\nif(!symbolFrom&&!symbolTo&&label.ignore){return;}var invScale=1;var parentNode=this.parent;while(parentNode){if(parentNode.scale){invScale/=parentNode.scale[0];}parentNode=parentNode.parent;}var line=lineGroup.childOfName('line');// If line not changed\n// FIXME Parent scale changed\nif(!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);if(symbolFrom){symbolFrom.attr('position',fromPos);// Fix #12388\n// when symbol is set to be 'arrow' in markLine,\n// symbolRotate value will be ignored, and compulsively use tangent angle.\n// rotate by default if symbol rotation is not specified\nvar specifiedRotation=symbolFrom.__specifiedRotation;if(specifiedRotation==null){var tangent=line.tangentAt(0);symbolFrom.attr('rotation',Math.PI/2-Math.atan2(tangent[1],tangent[0]));}else{symbolFrom.attr('rotation',specifiedRotation);}symbolFrom.attr('scale',[invScale*percent,invScale*percent]);}if(symbolTo){symbolTo.attr('position',toPos);// Fix #12388\n// when symbol is set to be 'arrow' in markLine,\n// symbolRotate value will be ignored, and compulsively use tangent angle.\n// rotate by default if symbol rotation is not specified\nvar specifiedRotation=symbolTo.__specifiedRotation;if(specifiedRotation==null){var tangent=line.tangentAt(1);symbolTo.attr('rotation',-Math.PI/2-Math.atan2(tangent[1],tangent[0]));}else{symbolTo.attr('rotation',specifiedRotation);}symbolTo.attr('scale',[invScale*percent,invScale*percent]);}if(!label.ignore){label.attr('position',toPos);var textPosition;var textAlign;var textVerticalAlign;var textOrigin;var distance$$1=label.__labelDistance;var distanceX=distance$$1[0]*invScale;var distanceY=distance$$1[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.attr('rotation',rotation);}var dy;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':textPosition=[d[0]*distanceX+toPos[0],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':textPosition=[-d[0]*distanceX+fromPos[0],-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':textPosition=[distanceX*dir+fromPos[0],fromPos[1]+dy];textAlign=tangent[0]<0?'right':'left';textOrigin=[-distanceX*dir,-dy];break;case'insideMiddleTop':case'insideMiddle':case'insideMiddleBottom':case'middle':textPosition=[cp[0],cp[1]+dy];textAlign='center';textOrigin=[0,-dy];break;case'insideEndTop':case'insideEnd':case'insideEndBottom':textPosition=[-distanceX*dir+toPos[0],toPos[1]+dy];textAlign=tangent[0]>=0?'right':'left';textOrigin=[distanceX*dir,-dy];break;}label.attr({style:{// Use the user specified text align and baseline first\ntextVerticalAlign:label.__verticalAlign||textVerticalAlign,textAlign:label.__textAlign||textAlign},position:textPosition,scale:[invScale,invScale],origin:textOrigin});}}/**\n * @constructor\n * @extends {module:zrender/graphic/Group}\n * @alias {module:echarts/chart/helper/Line}\n */function Line$1(lineData,idx,seriesScope){Group.call(this);this._createLine(lineData,idx,seriesScope);}var lineProto=Line$1.prototype;// Update symbol position and rotation\nlineProto.beforeUpdate=updateSymbolAndLabelBeforeLineUpdate;lineProto._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);var label=new Text({name:'label',// FIXME\n// Temporary solution for `focusNodeAdjacency`.\n// line label do not use the opacity of lineStyle.\nlineLabelOriginalOpacity:1});this.add(label);each$1(SYMBOL_CATEGORIES,function(symbolCategory){var symbol=createSymbol$1(symbolCategory,lineData,idx);// symbols must added after line to make sure\n// it will be updated after line#update.\n// Or symbol position and rotation update in line#beforeUpdate will be one frame slow\nthis.add(symbol);this[makeSymbolTypeKey(symbolCategory)]=lineData.getItemVisual(idx,symbolCategory);},this);this._updateCommonStl(lineData,idx,seriesScope);};lineProto.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$1(SYMBOL_CATEGORIES,function(symbolCategory){var symbolType=lineData.getItemVisual(idx,symbolCategory);var key=makeSymbolTypeKey(symbolCategory);// Symbol changed\nif(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);};lineProto._updateCommonStl=function(lineData,idx,seriesScope){var seriesModel=lineData.hostModel;var line=this.childOfName('line');var lineStyle=seriesScope&&seriesScope.lineStyle;var hoverLineStyle=seriesScope&&seriesScope.hoverLineStyle;var labelModel=seriesScope&&seriesScope.labelModel;var hoverLabelModel=seriesScope&&seriesScope.hoverLabelModel;// Optimization for large dataset\nif(!seriesScope||lineData.hasItemOption){var itemModel=lineData.getItemModel(idx);lineStyle=itemModel.getModel('lineStyle').getLineStyle();hoverLineStyle=itemModel.getModel('emphasis.lineStyle').getLineStyle();labelModel=itemModel.getModel('label');hoverLabelModel=itemModel.getModel('emphasis.label');}var visualColor=lineData.getItemVisual(idx,'color');var visualOpacity=retrieve3(lineData.getItemVisual(idx,'opacity'),lineStyle.opacity,1);line.useStyle(defaults({strokeNoScale:true,fill:'none',stroke:visualColor,opacity:visualOpacity},lineStyle));line.hoverStyle=hoverLineStyle;// Update symbol\neach$1(SYMBOL_CATEGORIES,function(symbolCategory){var symbol=this.childOfName(symbolCategory);if(symbol){symbol.setColor(visualColor);symbol.setStyle({opacity:visualOpacity});}},this);var showLabel=labelModel.getShallow('show');var hoverShowLabel=hoverLabelModel.getShallow('show');var label=this.childOfName('label');var defaultLabelColor;var baseText;// FIXME: the logic below probably should be merged to `graphic.setLabelStyle`.\nif(showLabel||hoverShowLabel){defaultLabelColor=visualColor||'#000';baseText=seriesModel.getFormattedLabel(idx,'normal',lineData.dataType);if(baseText==null){var rawVal=seriesModel.getRawValue(idx);baseText=rawVal==null?lineData.getName(idx):isFinite(rawVal)?round$1(rawVal):rawVal;}}var normalText=showLabel?baseText:null;var emphasisText=hoverShowLabel?retrieve2(seriesModel.getFormattedLabel(idx,'emphasis',lineData.dataType),baseText):null;var labelStyle=label.style;// Always set `textStyle` even if `normalStyle.text` is null, because default\n// values have to be set on `normalStyle`.\nif(normalText!=null||emphasisText!=null){setTextStyle(label.style,labelModel,{text:normalText},{autoColor:defaultLabelColor});label.__textAlign=labelStyle.textAlign;label.__verticalAlign=labelStyle.textVerticalAlign;// 'start', 'middle', 'end'\nlabel.__position=labelModel.get('position')||'middle';var distance$$1=labelModel.get('distance');if(!isArray(distance$$1)){distance$$1=[distance$$1,distance$$1];}label.__labelDistance=distance$$1;}if(emphasisText!=null){// Only these properties supported in this emphasis style here.\nlabel.hoverStyle={text:emphasisText,textFill:hoverLabelModel.getTextColor(true),// For merging hover style to normal style, do not use\n// `hoverLabelModel.getFont()` here.\nfontStyle:hoverLabelModel.getShallow('fontStyle'),fontWeight:hoverLabelModel.getShallow('fontWeight'),fontSize:hoverLabelModel.getShallow('fontSize'),fontFamily:hoverLabelModel.getShallow('fontFamily')};}else{label.hoverStyle={text:null};}label.ignore=!showLabel&&!hoverShowLabel;setHoverStyle(this);};lineProto.highlight=function(){this.trigger('emphasis');};lineProto.downplay=function(){this.trigger('normal');};lineProto.updateLayout=function(lineData,idx){this.setLinePoints(lineData.getItemLayout(idx));};lineProto.setLinePoints=function(points){var linePath=this.childOfName('line');setLinePoints(linePath.shape,points);linePath.dirty();};inherits(Line$1,Group);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @module echarts/chart/helper/LineDraw\n */ // import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';\n/**\n * @alias module:echarts/component/marker/LineDraw\n * @constructor\n */function LineDraw(ctor){this._ctor=ctor||Line$1;this.group=new Group();}var lineDrawProto=LineDraw.prototype;lineDrawProto.isPersistent=function(){return true;};/**\n * @param {module:echarts/data/List} lineData\n */lineDrawProto.updateData=function(lineData){var lineDraw=this;var group=lineDraw.group;var oldLineData=lineDraw._lineData;lineDraw._lineData=lineData;// There is no oldLineData only when first rendering or switching from\n// stream mode to normal mode, where previous elements should be removed.\nif(!oldLineData){group.removeAll();}var seriesScope=makeSeriesScope$1(lineData);lineData.diff(oldLineData).add(function(idx){doAdd(lineDraw,lineData,idx,seriesScope);}).update(function(newIdx,oldIdx){doUpdate(lineDraw,oldLineData,lineData,oldIdx,newIdx,seriesScope);}).remove(function(idx){group.remove(oldLineData.getItemGraphicEl(idx));}).execute();};function doAdd(lineDraw,lineData,idx,seriesScope){var itemLayout=lineData.getItemLayout(idx);if(!lineNeedsDraw(itemLayout)){return;}var el=new lineDraw._ctor(lineData,idx,seriesScope);lineData.setItemGraphicEl(idx,el);lineDraw.group.add(el);}function doUpdate(lineDraw,oldLineData,newLineData,oldIdx,newIdx,seriesScope){var itemEl=oldLineData.getItemGraphicEl(oldIdx);if(!lineNeedsDraw(newLineData.getItemLayout(newIdx))){lineDraw.group.remove(itemEl);return;}if(!itemEl){itemEl=new lineDraw._ctor(newLineData,newIdx,seriesScope);}else{itemEl.updateData(newLineData,newIdx,seriesScope);}newLineData.setItemGraphicEl(newIdx,itemEl);lineDraw.group.add(itemEl);}lineDrawProto.updateLayout=function(){var lineData=this._lineData;// Do not support update layout in incremental mode.\nif(!lineData){return;}lineData.eachItemGraphicEl(function(el,idx){el.updateLayout(lineData,idx);},this);};lineDrawProto.incrementalPrepareUpdate=function(lineData){this._seriesScope=makeSeriesScope$1(lineData);this._lineData=null;this.group.removeAll();};function isEffectObject(el){return el.animators&&el.animators.length>0;}lineDrawProto.incrementalUpdate=function(taskParams,lineData){function updateIncrementalAndHover(el){if(!el.isGroup&&!isEffectObject(el)){el.incremental=el.useHoverLayer=true;}}for(var idx=taskParams.start;idx<taskParams.end;idx++){var itemLayout=lineData.getItemLayout(idx);if(lineNeedsDraw(itemLayout)){var el=new this._ctor(lineData,idx,this._seriesScope);el.traverse(updateIncrementalAndHover);this.group.add(el);lineData.setItemGraphicEl(idx,el);}}};function makeSeriesScope$1(lineData){var hostModel=lineData.hostModel;return{lineStyle:hostModel.getModel('lineStyle').getLineStyle(),hoverLineStyle:hostModel.getModel('emphasis.lineStyle').getLineStyle(),labelModel:hostModel.getModel('label'),hoverLabelModel:hostModel.getModel('emphasis.label')};}lineDrawProto.remove=function(){this._clearIncremental();this._incremental=null;this.group.removeAll();};lineDrawProto._clearIncremental=function(){var incremental=this._incremental;if(incremental){incremental.clearDisplaybles();}};function isPointNaN(pt){return isNaN(pt[0])||isNaN(pt[1]);}function lineNeedsDraw(pts){return!isPointNaN(pts[0])&&!isPointNaN(pts[1]);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var markLineTransform=function markLineTransform(seriesModel,coordSys,mlModel,item){var data=seriesModel.getData();// Special type markLine like 'min', 'max', 'average', 'median'\nvar mlType=item.type;if(!isArray(item)&&(mlType==='min'||mlType==='max'||mlType==='average'||mlType==='median'// In case\n// data: [{\n//   yAxis: 10\n// }]\n||item.xAxis!=null||item.yAxis!=null)){var valueAxis;var value;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={};mlFrom.type=null;mlFrom.coord=[];mlTo.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;item=[mlFrom,mlTo,{// Extra option for tooltip and label\ntype:mlType,valueIndex:item.valueIndex,// Force to use the value of calculated value.\nvalue:value}];}item=[dataTransform(seriesModel,item[0]),dataTransform(seriesModel,item[1]),extend({},item[2])];// Avoid line data type is extended by from(to) data type\nitem[2].type=item[2].type||'';// Merge from option and to option into line option\nmerge(item[2],item[0]);merge(item[2],item[1]);return item;};function isInifinity(val){return!isNaN(val)&&!isFinite(val);}// If a markLine has one dim\nfunction 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;// In case\n// {\n//  markLine: {\n//    data: [{ yAxis: 2 }]\n//  }\n// }\nif(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$1(itemModel.get('x'),api.getWidth());var yPx=parsePercent$1(itemModel.get('y'),api.getHeight());if(!isNaN(xPx)&&!isNaN(yPx)){point=[xPx,yPx];}else{// Chart like bar may have there own marker positioning logic\nif(seriesModel.getMarkerPosition){// Use the getMarkerPoisition\npoint=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]);}// Expand line to the edge of grid if value on one axis is Inifnity\n// In case\n//  markLine: {\n//    data: [{\n//      yAxis: 2\n//      // or\n//      type: 'average'\n//    }]\n//  }\nif(coordSys.type==='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]);}}// Use x, y if has any\nif(!isNaN(xPx)){point[0]=xPx;}if(!isNaN(yPx)){point[1]=yPx;}}data.setItemLayout(idx,point);}MarkerView.extend({type:'markLine',// updateLayout: function (markLineModel, ecModel, api) {\n//     ecModel.eachSeries(function (seriesModel) {\n//         var mlModel = seriesModel.markLineModel;\n//         if (mlModel) {\n//             var mlData = mlModel.getData();\n//             var fromData = mlModel.__from;\n//             var toData = mlModel.__to;\n//             // Update visual and layout of from symbol and to symbol\n//             fromData.each(function (idx) {\n//                 updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api);\n//                 updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api);\n//             });\n//             // Update layout of line\n//             mlData.each(function (idx) {\n//                 mlData.setItemLayout(idx, [\n//                     fromData.getItemLayout(idx),\n//                     toData.getItemLayout(idx)\n//                 ]);\n//             });\n//             this.markerGroupMap.get(seriesModel.id).updateLayout();\n//         }\n//     }, this);\n// },\nupdateTransform:function updateTransform(markLineModel,ecModel,api){ecModel.eachSeries(function(seriesModel){var mlModel=seriesModel.markLineModel;if(mlModel){var mlData=mlModel.getData();var fromData=mlModel.__from;var toData=mlModel.__to;// Update visual and layout of from symbol and to symbol\nfromData.each(function(idx){updateSingleMarkerEndLayout(fromData,idx,true,seriesModel,api);updateSingleMarkerEndLayout(toData,idx,false,seriesModel,api);});// Update layout of line\nmlData.each(function(idx){mlData.setItemLayout(idx,[fromData.getItemLayout(idx),toData.getItemLayout(idx)]);});this.markerGroupMap.get(seriesModel.id).updateLayout();}},this);},renderSeries:function renderSeries(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;mlModel.__from=fromData;mlModel.__to=toData;// Line data for tooltip and formatter\nmlModel.setData(lineData);var symbolType=mlModel.get('symbol');var symbolSize=mlModel.get('symbolSize');if(!isArray(symbolType)){symbolType=[symbolType,symbolType];}if(typeof symbolSize==='number'){symbolSize=[symbolSize,symbolSize];}// Update visual and layout of from symbol and to symbol\nmlData.from.each(function(idx){updateDataVisualAndLayout(fromData,idx,true);updateDataVisualAndLayout(toData,idx,false);});// Update visual and layout of line\nlineData.each(function(idx){var lineColor=lineData.getItemModel(idx).get('lineStyle.color');lineData.setItemVisual(idx,{color:lineColor||fromData.getItemVisual(idx,'color')});lineData.setItemLayout(idx,[fromData.getItemLayout(idx),toData.getItemLayout(idx)]);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')});});lineDraw.updateData(lineData);// Set host model for tooltip\n// FIXME\nmlData.line.eachItemGraphicEl(function(el,idx){el.traverse(function(child){child.dataModel=mlModel;});});function updateDataVisualAndLayout(data,idx,isFrom){var itemModel=data.getItemModel(idx);updateSingleMarkerEndLayout(data,idx,isFrom,seriesModel,api);data.setItemVisual(idx,{symbolRotate:itemModel.get('symbolRotate'),symbolSize:itemModel.get('symbolSize')||symbolSize[isFrom?0:1],symbol:itemModel.get('symbol',true)||symbolType[isFrom?0:1],color:itemModel.get('itemStyle.color')||seriesData.getVisual('color')});}lineDraw.__keep=true;lineDraw.group.silent=mlModel.get('silent')||seriesModel.get('silent');}});/**\n * @inner\n * @param {module:echarts/coord/*} coordSys\n * @param {module:echarts/model/Series} seriesModel\n * @param {module:echarts/model/Model} mpModel\n */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))||{};// In map series data don't have lng and lat dimension. Fallback to same with coordSys\nreturn defaults({name:coordDim},info);});}else{coordDimsInfos=[{name:'value',type:'float'}];}var fromData=new List(coordDimsInfos,mlModel);var toData=new List(coordDimsInfos,mlModel);// No dimensions\nvar 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};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/registerPreprocessor(function(opt){// Make sure markLine component is enabled\nopt.markLine=opt.markLine||{};});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/MarkerModel.extend({type:'markArea',defaultOption:{zlevel:0,// PENDING\nz:1,tooltip:{trigger:'item'},// markArea should fixed on the coordinate system\nanimation:false,label:{show:true,position:'top'},itemStyle:{// color and borderColor default to use color from series\n// color: 'auto'\n// borderColor: 'auto'\nborderWidth:0},emphasis:{label:{show:true,position:'top'}}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // TODO Better on polar\nvar markAreaTransform=function markAreaTransform(seriesModel,coordSys,maModel,item){var lt=dataTransform(seriesModel,item[0]);var rb=dataTransform(seriesModel,item[1]);var retrieve$$1=retrieve;// FIXME make sure lt is less than rb\nvar ltCoord=lt.coord;var rbCoord=rb.coord;ltCoord[0]=retrieve$$1(ltCoord[0],-Infinity);ltCoord[1]=retrieve$$1(ltCoord[1],-Infinity);rbCoord[0]=retrieve$$1(rbCoord[0],Infinity);rbCoord[1]=retrieve$$1(rbCoord[1],Infinity);// Merge option into one\nvar 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);}// If a markArea has one dim\nfunction ifMarkLineHasOnlyDim$1(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(coordSys.type==='cartesian2d'){// In case\n// {\n//  markArea: {\n//    data: [{ yAxis: 2 }]\n//  }\n// }\nif(fromCoord&&toCoord&&(ifMarkLineHasOnlyDim$1(1,fromCoord,toCoord,coordSys)||ifMarkLineHasOnlyDim$1(0,fromCoord,toCoord,coordSys))){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});}// dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0']\nfunction getSingleMarkerEndPoint(data,idx,dims,seriesModel,api){var coordSys=seriesModel.coordinateSystem;var itemModel=data.getItemModel(idx);var point;var xPx=parsePercent$1(itemModel.get(dims[0]),api.getWidth());var yPx=parsePercent$1(itemModel.get(dims[1]),api.getHeight());if(!isNaN(xPx)&&!isNaN(yPx)){point=[xPx,yPx];}else{// Chart like bar may have there own marker positioning logic\nif(seriesModel.getMarkerPosition){// Use the getMarkerPoisition\npoint=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(coordSys.type==='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]);}}// Use x, y if has any\nif(!isNaN(xPx)){point[0]=xPx;}if(!isNaN(yPx)){point[1]=yPx;}}return point;}var dimPermutations=[['x0','y0'],['x1','y0'],['x1','y1'],['x0','y1']];MarkerView.extend({type:'markArea',// updateLayout: function (markAreaModel, ecModel, api) {\n//     ecModel.eachSeries(function (seriesModel) {\n//         var maModel = seriesModel.markAreaModel;\n//         if (maModel) {\n//             var areaData = maModel.getData();\n//             areaData.each(function (idx) {\n//                 var points = zrUtil.map(dimPermutations, function (dim) {\n//                     return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);\n//                 });\n//                 // Layout\n//                 areaData.setItemLayout(idx, points);\n//                 var el = areaData.getItemGraphicEl(idx);\n//                 el.setShape('points', points);\n//             });\n//         }\n//     }, this);\n// },\nupdateTransform:function updateTransform(markAreaModel,ecModel,api){ecModel.eachSeries(function(seriesModel){var maModel=seriesModel.markAreaModel;if(maModel){var areaData=maModel.getData();areaData.each(function(idx){var points=map(dimPermutations,function(dim){return getSingleMarkerEndPoint(areaData,idx,dim,seriesModel,api);});// Layout\nareaData.setItemLayout(idx,points);var el=areaData.getItemGraphicEl(idx);el.setShape('points',points);});}},this);},renderSeries:function renderSeries(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);polygonGroup.__keep=true;var areaData=createList$3(coordSys,seriesModel,maModel);// Line data for tooltip and formatter\nmaModel.setData(areaData);// Update visual and layout of line\nareaData.each(function(idx){// Layout\nvar points=map(dimPermutations,function(dim){return getSingleMarkerEndPoint(areaData,idx,dim,seriesModel,api);});// If none of the area is inside coordSys, allClipped is set to be true\n// in layout so that label will not be displayed. See #12591\nvar allClipped=true;each$1(dimPermutations,function(dim){if(!allClipped){return;}var xValue=areaData.get(dim[0],idx);var yValue=areaData.get(dim[1],idx);// If is infinity, the axis should be considered not clipped\nif((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});// Visual\nareaData.setItemVisual(idx,{color:seriesData.getVisual('color')});});areaData.diff(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=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=polygonGroup.__data.getItemGraphicEl(idx);polygonGroup.group.remove(polygon);}).execute();areaData.eachItemGraphicEl(function(polygon,idx){var itemModel=areaData.getItemModel(idx);var labelModel=itemModel.getModel('label');var labelHoverModel=itemModel.getModel('emphasis.label');var color=areaData.getItemVisual(idx,'color');polygon.useStyle(defaults(itemModel.getModel('itemStyle').getItemStyle(),{fill:modifyAlpha(color,0.4),stroke:color}));polygon.hoverStyle=itemModel.getModel('emphasis.itemStyle').getItemStyle();setLabelStyle(polygon.style,polygon.hoverStyle,labelModel,labelHoverModel,{labelFetcher:maModel,labelDataIndex:idx,defaultText:areaData.getName(idx)||'',isRectText:true,autoColor:color});setHoverStyle(polygon,{});polygon.dataModel=maModel;});polygonGroup.__data=areaData;polygonGroup.group.silent=maModel.get('silent')||seriesModel.get('silent');}});/**\n * @inner\n * @param {module:echarts/coord/*} coordSys\n * @param {module:echarts/model/Series} seriesModel\n * @param {module:echarts/model/Model} mpModel\n */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))||{};// In map series data don't have lng and lat dimension. Fallback to same with coordSys\nreturn 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$$1=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$$1);areaData.hasItemOption=true;return areaData;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/registerPreprocessor(function(opt){// Make sure markArea component is enabled\nopt.markArea=opt.markArea||{};});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ComponentModel.registerSubTypeDefaulter('dataZoom',function(){// Default 'slider' when no type specified.\nreturn'slider';});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var AXIS_DIMS=['x','y','z','radius','angle','single'];// Supported coords.\nvar COORDS=['cartesian2d','polar','singleAxis'];/**\n * @param {string} coordType\n * @return {boolean}\n */function isCoordSupported(coordType){return indexOf(COORDS,coordType)>=0;}/**\n * Create \"each\" method to iterate names.\n *\n * @pubilc\n * @param  {Array.<string>} names\n * @param  {Array.<string>=} attrs\n * @return {Function}\n */function createNameEach(names,attrs){names=names.slice();var capitalNames=map(names,capitalFirst);attrs=(attrs||[]).slice();var capitalAttrs=map(attrs,capitalFirst);return function(callback,context){each$1(names,function(name,index){var nameObj={name:name,capital:capitalNames[index]};for(var j=0;j<attrs.length;j++){nameObj[attrs[j]]=name+capitalAttrs[j];}callback.call(context,nameObj);});};}/**\n * Iterate each dimension name.\n *\n * @public\n * @param {Function} callback The parameter is like:\n *                            {\n *                                name: 'angle',\n *                                capital: 'Angle',\n *                                axis: 'angleAxis',\n *                                axisIndex: 'angleAixs',\n *                                index: 'angleIndex'\n *                            }\n * @param {Object} context\n */var eachAxisDim$1=createNameEach(AXIS_DIMS,['axisIndex','axis','index','id']);/**\n * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'.\n * dataZoomModels and 'links' make up one or more graphics.\n * This function finds the graphic where the source dataZoomModel is in.\n *\n * @public\n * @param {Function} forEachNode Node iterator.\n * @param {Function} forEachEdgeType edgeType iterator\n * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id.\n * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}}\n */function createLinkedNodesFinder(forEachNode,forEachEdgeType,edgeIdGetter){return function(sourceNode){var result={nodes:[],records:{}// key: edgeType.name, value: Object (key: edge id, value: boolean).\n};forEachEdgeType(function(edgeType){result.records[edgeType.name]={};});if(!sourceNode){return result;}absorb(sourceNode,result);var existsLink;do{existsLink=false;forEachNode(processSingleNode);}while(existsLink);function processSingleNode(node){if(!isNodeAbsorded(node,result)&&isLinked(node,result)){absorb(node,result);existsLink=true;}}return result;};function isNodeAbsorded(node,result){return indexOf(result.nodes,node)>=0;}function isLinked(node,result){var hasLink=false;forEachEdgeType(function(edgeType){each$1(edgeIdGetter(node,edgeType)||[],function(edgeId){result.records[edgeType.name][edgeId]&&(hasLink=true);});});return hasLink;}function absorb(node,result){result.nodes.push(node);forEachEdgeType(function(edgeType){each$1(edgeIdGetter(node,edgeType)||[],function(edgeId){result.records[edgeType.name][edgeId]=true;});});}}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Calculate slider move result.\n * Usage:\n * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as\n * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`.\n * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`.\n *\n * @param {number} delta Move length.\n * @param {Array.<number>} handleEnds handleEnds[0] can be bigger then handleEnds[1].\n *              handleEnds will be modified in this method.\n * @param {Array.<number>} extent handleEnds is restricted by extent.\n *              extent[0] should less or equals than extent[1].\n * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds.\n * @param {number} [minSpan] The range of dataZoom can not be smaller than that.\n *              If not set, handle0 and cross handle1. If set as a non-negative\n *              number (including `0`), handles will push each other when reaching\n *              the minSpan.\n * @param {number} [maxSpan] The range of dataZoom can not be larger than that.\n * @return {Array.<number>} The input handleEnds.\n */var sliderMove=function sliderMove(delta,handleEnds,extent,handleIndex,minSpan,maxSpan){delta=delta||0;var extentSpan=extent[1]-extent[0];// Notice maxSpan and minSpan can be null/undefined.\nif(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;// Restrict in extent.\nvar extentMinSpan=minSpan||0;var realExtent=extent.slice();originalDistSign.sign<0?realExtent[0]+=extentMinSpan:realExtent[1]-=extentMinSpan;handleEnds[handleIndex]=restrict(handleEnds[handleIndex],realExtent);// Expand span.\nvar currDistSign=getSpanSign(handleEnds,handleIndex);if(minSpan!=null&&(currDistSign.sign!==originalDistSign.sign||currDistSign.span<minSpan)){// If minSpan exists, 'cross' is forbidden.\nhandleEnds[1-handleIndex]=handleEnds[handleIndex]+originalDistSign.sign*minSpan;}// Shrink span.\nvar 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];// If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0]\n// is at left of handleEnds[1] for non-cross case.\nreturn{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));}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$13=each$1;var asc$1=asc;/**\n * Operate single axis.\n * One axis can only operated by one axis operator.\n * Different dataZoomModels may be defined to operate the same axis.\n * (i.e. 'inside' data zoom and 'slider' data zoom components)\n * So dataZoomModels share one axisProxy in that case.\n *\n * @class\n */var AxisProxy=function AxisProxy(dimName,axisIndex,dataZoomModel,ecModel){/**\n     * @private\n     * @type {string}\n     */this._dimName=dimName;/**\n     * @private\n     */this._axisIndex=axisIndex;/**\n     * @private\n     * @type {Array.<number>}\n     */this._valueWindow;/**\n     * @private\n     * @type {Array.<number>}\n     */this._percentWindow;/**\n     * @private\n     * @type {Array.<number>}\n     */this._dataExtent;/**\n     * {minSpan, maxSpan, minValueSpan, maxValueSpan}\n     * @private\n     * @type {Object}\n     */this._minMaxSpan;/**\n     * @readOnly\n     * @type {module: echarts/model/Global}\n     */this.ecModel=ecModel;/**\n     * @private\n     * @type {module: echarts/component/dataZoom/DataZoomModel}\n     */this._dataZoomModel=dataZoomModel;// /**\n//  * @readOnly\n//  * @private\n//  */\n// this.hasSeriesStacked;\n};AxisProxy.prototype={constructor:AxisProxy,/**\n     * Whether the axisProxy is hosted by dataZoomModel.\n     *\n     * @public\n     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel\n     * @return {boolean}\n     */hostedBy:function hostedBy(dataZoomModel){return this._dataZoomModel===dataZoomModel;},/**\n     * @return {Array.<number>} Value can only be NaN or finite value.\n     */getDataValueWindow:function getDataValueWindow(){return this._valueWindow.slice();},/**\n     * @return {Array.<number>}\n     */getDataPercentWindow:function getDataPercentWindow(){return this._percentWindow.slice();},/**\n     * @public\n     * @param {number} axisIndex\n     * @return {Array} seriesModels\n     */getTargetSeriesModels:function getTargetSeriesModels(){var seriesModels=[];var ecModel=this.ecModel;ecModel.eachSeries(function(seriesModel){if(isCoordSupported(seriesModel.get('coordinateSystem'))){var dimName=this._dimName;var axisModel=ecModel.queryComponents({mainType:dimName+'Axis',index:seriesModel.get(dimName+'AxisIndex'),id:seriesModel.get(dimName+'AxisId')})[0];if(this._axisIndex===(axisModel&&axisModel.componentIndex)){seriesModels.push(seriesModel);}}},this);return seriesModels;},getAxisModel:function getAxisModel(){return this.ecModel.getComponent(this._dimName+'Axis',this._axisIndex);},getOtherAxisModel:function getOtherAxisModel(){var axisDim=this._dimName;var ecModel=this.ecModel;var axisModel=this.getAxisModel();var isCartesian=axisDim==='x'||axisDim==='y';var otherAxisDim;var coordSysIndexName;if(isCartesian){coordSysIndexName='gridIndex';otherAxisDim=axisDim==='x'?'y':'x';}else{coordSysIndexName='polarIndex';otherAxisDim=axisDim==='angle'?'radius':'angle';}var foundOtherAxisModel;ecModel.eachComponent(otherAxisDim+'Axis',function(otherAxisModel){if((otherAxisModel.get(coordSysIndexName)||0)===(axisModel.get(coordSysIndexName)||0)){foundOtherAxisModel=otherAxisModel;}});return foundOtherAxisModel;},getMinMaxSpan:function getMinMaxSpan(){return _clone(this._minMaxSpan);},/**\n     * Only calculate by given range and this._dataExtent, do not change anything.\n     *\n     * @param {Object} opt\n     * @param {number} [opt.start]\n     * @param {number} [opt.end]\n     * @param {number} [opt.startValue]\n     * @param {number} [opt.endValue]\n     */calculateDataWindow:function calculateDataWindow(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$13(['start','end'],function(prop,idx){var boundPercent=opt[prop];var boundValue=opt[prop+'Value'];// Notice: dataZoom is based either on `percentProp` ('start', 'end') or\n// on `valueProp` ('startValue', 'endValue'). (They are based on the data extent\n// but not min/max of axis, which will be calculated by data window then).\n// The former one is suitable for cases that a dataZoom component controls multiple\n// axes with different unit or extent, and the latter one is suitable for accurate\n// zoom by pixel (e.g., in dataZoomSelect).\n// we use `getRangePropMode()` to mark which prop is used. `rangePropMode` is updated\n// only when setOption or dispatchAction, otherwise it remains its original value.\n// (Why not only record `percentProp` and always map to `valueProp`? Because\n// the map `valueProp` -> `percentProp` -> `valueProp` probably not the original\n// `valueProp`. consider two axes constrolled by one dataZoom. They have different\n// data extent. All of values that are overflow the `dataExtent` will be calculated\n// to percent '100%').\nif(rangePropMode[idx]==='percent'){boundPercent==null&&(boundPercent=percentExtent[idx]);// Use scale.parse to math round for category or time axis.\nboundValue=scale.parse(linearMap(boundPercent,percentExtent,dataExtent));}else{hasPropModeValue=true;boundValue=boundValue==null?dataExtent[idx]:scale.parse(boundValue);// Calculating `percent` from `value` may be not accurate, because\n// This calculation can not be inversed, because all of values that\n// are overflow the `dataExtent` will be calculated to percent '100%'\nboundPercent=linearMap(boundValue,dataExtent,percentExtent);}// valueWindow[idx] = round(boundValue);\n// percentWindow[idx] = round(boundPercent);\nvalueWindow[idx]=boundValue;percentWindow[idx]=boundPercent;});asc$1(valueWindow);asc$1(percentWindow);// The windows from user calling of `dispatchAction` might be out of the extent,\n// or do not obey the `min/maxSpan`, `min/maxValueSpan`. But we dont restrict window\n// by `zoomLock` here, because we see `zoomLock` just as a interaction constraint,\n// where API is able to initialize/modify the window size even though `zoomLock`\n// specified.\nvar 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};},/**\n     * Notice: reset should not be called before series.restoreData() called,\n     * so it is recommanded to be called in \"process stage\" but not \"model init\n     * stage\".\n     *\n     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel\n     */reset:function reset(dataZoomModel){if(dataZoomModel!==this._dataZoomModel){return;}var targetSeries=this.getTargetSeriesModels();// Culculate data window and data extent, and record them.\nthis._dataExtent=calculateDataExtent(this,this._dimName,targetSeries);// this.hasSeriesStacked = false;\n// each(targetSeries, function (series) {\n// var data = series.getData();\n// var dataDim = data.mapDimension(this._dimName);\n// var stackedDimension = data.getCalculationInfo('stackedDimension');\n// if (stackedDimension && stackedDimension === dataDim) {\n// this.hasSeriesStacked = true;\n// }\n// }, this);\n// `calculateDataWindow` uses min/maxSpan.\nsetMinMaxSpan(this);var dataWindow=this.calculateDataWindow(dataZoomModel.settledOption);this._valueWindow=dataWindow.valueWindow;this._percentWindow=dataWindow.percentWindow;// Update axis setting then.\nsetAxisModel(this);},/**\n     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel\n     */restore:function restore(dataZoomModel){if(dataZoomModel!==this._dataZoomModel){return;}this._valueWindow=this._percentWindow=null;setAxisModel(this,true);},/**\n     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel\n     */filterData:function filterData(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;}// FIXME\n// Toolbox may has dataZoom injected. And if there are stacked bar chart\n// with NaN data, NaN will be filtered and stack will be wrong.\n// So we need to force the mode to be set empty.\n// In fect, it is not a big deal that do not support filterMode-'filter'\n// when using toolbox#dataZoom, utill tooltip#dataZoom support \"single axis\n// selection\" some day, which might need \"adapt to data extent on the\n// otherAxis\", which is disabled by filterMode-'empty'.\n// But currently, stack has been fixed to based on value but not index,\n// so this is not an issue any more.\n// var otherAxisModel = this.getOtherAxisModel();\n// if (dataZoomModel.get('$fromToolbox')\n//     && otherAxisModel\n//     && otherAxisModel.hasSeriesStacked\n// ) {\n//     filterMode = 'empty';\n// }\n// TODO\n// filterMode 'weakFilter' and 'empty' is not optimized for huge data yet.\neach$13(seriesModels,function(seriesModel){var seriesData=seriesModel.getData();var dataDims=seriesData.mapDimension(axisDim,true);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);}// If both left out and right out, do not filter.\nreturn hasValue&&leftOut&&rightOut;});}else{each$13(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;// console.time('select');\nseriesData.selectRange(range);// console.timeEnd('select');\n}});}each$13(dataDims,function(dim){seriesData.setApproximateExtent(valueWindow,dim);});});function isInWindow(value){return value>=valueWindow[0]&&value<=valueWindow[1];}}};function calculateDataExtent(axisProxy,axisDim,seriesModels){var dataExtent=[Infinity,-Infinity];each$13(seriesModels,function(seriesModel){var seriesData=seriesModel.getData();if(seriesData){each$13(seriesData.mapDimension(axisDim,true),function(dim){var seriesExtent=seriesData.getApproximateExtent(dim);seriesExtent[0]<dataExtent[0]&&(dataExtent[0]=seriesExtent[0]);seriesExtent[1]>dataExtent[1]&&(dataExtent[1]=seriesExtent[1]);});}});if(dataExtent[1]<dataExtent[0]){dataExtent=[NaN,NaN];}// It is important to get \"consistent\" extent when more then one axes is\n// controlled by a `dataZoom`, otherwise those axes will not be synchronized\n// when zooming. But it is difficult to know what is \"consistent\", considering\n// axes have different type or even different meanings (For example, two\n// time axes are used to compare data of the same date in different years).\n// So basically dataZoom just obtains extent by series.data (in category axis\n// extent can be obtained from axis.data).\n// Nevertheless, user can set min/max/scale on axes to make extent of axes\n// consistent.\nfixExtentByAxis(axisProxy,dataExtent);return dataExtent;}function fixExtentByAxis(axisProxy,dataExtent){var axisModel=axisProxy.getAxisModel();var min=axisModel.getMin(true);// For category axis, if min/max/scale are not set, extent is determined\n// by axis.data by default.\nvar isCategoryAxis=axisModel.get('type')==='category';var axisDataLen=isCategoryAxis&&axisModel.getCategories().length;if(min!=null&&min!=='dataMin'&&typeof min!=='function'){dataExtent[0]=min;}else if(isCategoryAxis){dataExtent[0]=axisDataLen>0?0:NaN;}var max=axisModel.getMax(true);if(max!=null&&max!=='dataMax'&&typeof max!=='function'){dataExtent[1]=max;}else if(isCategoryAxis){dataExtent[1]=axisDataLen>0?axisDataLen-1:NaN;}if(!axisModel.get('scale',true)){dataExtent[0]>0&&(dataExtent[0]=0);dataExtent[1]<0&&(dataExtent[1]=0);}// For value axis, if min/max/scale are not set, we just use the extent obtained\n// by series data, which may be a little different from the extent calculated by\n// `axisHelper.getScaleExtent`. But the different just affects the experience a\n// little when zooming. So it will not be fixed until some users require it strongly.\nreturn dataExtent;}function setAxisModel(axisProxy,isRestore){var axisModel=axisProxy.getAxisModel();var percentWindow=axisProxy._percentWindow;var valueWindow=axisProxy._valueWindow;if(!percentWindow){return;}// [0, 500]: arbitrary value, guess axis extent.\nvar precision=_getPixelPrecision(valueWindow,[0,500]);precision=Math.min(precision,20);// isRestore or isFull\nvar useOrigin=isRestore||percentWindow[0]===0&&percentWindow[1]===100;axisModel.setRange(useOrigin?null:+valueWindow[0].toFixed(precision),useOrigin?null:+valueWindow[1].toFixed(precision));}function setMinMaxSpan(axisProxy){var minMaxSpan=axisProxy._minMaxSpan={};var dataZoomModel=axisProxy._dataZoomModel;var dataExtent=axisProxy._dataExtent;each$13(['min','max'],function(minMax){var percentSpan=dataZoomModel.get(minMax+'Span');var valueSpan=dataZoomModel.get(minMax+'ValueSpan');valueSpan!=null&&(valueSpan=axisProxy.getAxisModel().axis.scale.parse(valueSpan));// minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan\nif(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;});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$12=each$1;var eachAxisDim=eachAxisDim$1;var DataZoomModel=extendComponentModel({type:'dataZoom',dependencies:['xAxis','yAxis','zAxis','radiusAxis','angleAxis','singleAxis','series'],/**\n     * @protected\n     */defaultOption:{zlevel:0,z:4,// Higher than normal component (z: 2).\norient:null,// Default auto by axisIndex. Possible value: 'horizontal', 'vertical'.\nxAxisIndex:null,// Default the first horizontal category axis.\nyAxisIndex:null,// Default the first vertical category axis.\nfilterMode:'filter',// Possible values: 'filter' or 'empty' or 'weakFilter'.\n// 'filter': data items which are out of window will be removed. This option is\n//          applicable when filtering outliers. For each data item, it will be\n//          filtered if one of the relevant dimensions is out of the window.\n// 'weakFilter': data items which are out of window will be removed. This option\n//          is applicable when filtering outliers. For each data item, it will be\n//          filtered only if all  of the relevant dimensions are out of the same\n//          side of the window.\n// 'empty': data items which are out of window will be set to empty.\n//          This option is applicable when user should not neglect\n//          that there are some data items out of window.\n// 'none': Do not filter.\n// Taking line chart as an example, line will be broken in\n// the filtered points when filterModel is set to 'empty', but\n// be connected when set to 'filter'.\nthrottle:null,// Dispatch action by the fixed rate, avoid frequency.\n// default 100. Do not throttle when use null/undefined.\n// If animation === true and animationDurationUpdate > 0,\n// default value is 100, otherwise 20.\nstart:0,// Start percent. 0 ~ 100\nend:100,// End percent. 0 ~ 100\nstartValue:null,// Start value. If startValue specified, start is ignored.\nendValue:null,// End value. If endValue specified, end is ignored.\nminSpan:null,// 0 ~ 100\nmaxSpan:null,// 0 ~ 100\nminValueSpan:null,// The range of dataZoom can not be smaller than that.\nmaxValueSpan:null,// The range of dataZoom can not be larger than that.\nrangeMode:null// Array, can be 'value' or 'percent'.\n},/**\n     * @override\n     */init:function init(option,parentModel,ecModel){/**\n         * key like x_0, y_1\n         * @private\n         * @type {Object}\n         */this._dataIntervalByAxis={};/**\n         * @private\n         */this._dataInfo={};/**\n         * key like x_0, y_1\n         * @private\n         */this._axisProxies={};/**\n         * @readOnly\n         */this.textStyleModel;/**\n         * @private\n         */this._autoThrottle=true;/**\n         * It is `[rangeModeForMin, rangeModeForMax]`.\n         * The optional values for `rangeMode`:\n         * + `'value'` mode: the axis extent will always be determined by\n         *     `dataZoom.startValue` and `dataZoom.endValue`, despite\n         *     how data like and how `axis.min` and `axis.max` are.\n         * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,\n         *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,\n         *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.\n         *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.\n         *\n         * For example, when users are using dynamic data (update data periodically via `setOption`),\n         * if in `'value`' mode, the window will be kept in a fixed value range despite how\n         * data are appended, while if in `'percent'` mode, whe window range will be changed alone with\n         * the appended data (suppose `axis.min` and `axis.max` are not specified).\n         *\n         * @private\n         */this._rangePropMode=['percent','percent'];var inputRawOption=retrieveRawOption(option);/**\n         * Suppose a \"main process\" start at the point that model prepared (that is,\n         * model initialized or merged or method called in `action`).\n         * We should keep the `main process` idempotent, that is, given a set of values\n         * on `option`, we get the same result.\n         *\n         * But sometimes, values on `option` will be updated for providing users\n         * a \"final calculated value\" (`dataZoomProcessor` will do that). Those value\n         * should not be the base/input of the `main process`.\n         *\n         * So in that case we should save and keep the input of the `main process`\n         * separately, called `settledOption`.\n         *\n         * For example, consider the case:\n         * (Step_1) brush zoom the grid by `toolbox.dataZoom`,\n         *     where the original input `option.startValue`, `option.endValue` are earsed by\n         *     calculated value.\n         * (Step)2) click the legend to hide and show a series,\n         *     where the new range is calculated by the earsed `startValue` and `endValue`,\n         *     which brings incorrect result.\n         *\n         * @readOnly\n         */this.settledOption=inputRawOption;this.mergeDefaultAndTheme(option,ecModel);this.doInit(inputRawOption);},/**\n     * @override\n     */mergeOption:function mergeOption(newOption){var inputRawOption=retrieveRawOption(newOption);//FIX #2591\nmerge(this.option,newOption,true);merge(this.settledOption,inputRawOption,true);this.doInit(inputRawOption);},/**\n     * @protected\n     */doInit:function doInit(inputRawOption){var thisOption=this.option;// Disable realtime view update if canvas is not supported.\nif(!env$1.canvasSupported){thisOption.realtime=false;}this._setDefaultThrottle(inputRawOption);updateRangeUse(this,inputRawOption);var settledOption=this.settledOption;each$12([['start','startValue'],['end','endValue']],function(names,index){// start/end has higher priority over startValue/endValue if they\n// both set, but we should make chart.setOption({endValue: 1000})\n// effective, rather than chart.setOption({endValue: 1000, end: null}).\nif(this._rangePropMode[index]==='value'){thisOption[names[0]]=settledOption[names[0]]=null;}// Otherwise do nothing and use the merge result.\n},this);this.textStyleModel=this.getModel('textStyle');this._resetTarget();this._giveAxisProxies();},/**\n     * @private\n     */_giveAxisProxies:function _giveAxisProxies(){var axisProxies=this._axisProxies;this.eachTargetAxis(function(dimNames,axisIndex,dataZoomModel,ecModel){var axisModel=this.dependentModels[dimNames.axis][axisIndex];// If exists, share axisProxy with other dataZoomModels.\nvar axisProxy=axisModel.__dzAxisProxy||(// Use the first dataZoomModel as the main model of axisProxy.\naxisModel.__dzAxisProxy=new AxisProxy(dimNames.name,axisIndex,this,ecModel));// FIXME\n// dispose __dzAxisProxy\naxisProxies[dimNames.name+'_'+axisIndex]=axisProxy;},this);},/**\n     * @private\n     */_resetTarget:function _resetTarget(){var thisOption=this.option;var autoMode=this._judgeAutoMode();eachAxisDim(function(dimNames){var axisIndexName=dimNames.axisIndex;thisOption[axisIndexName]=normalizeToArray(thisOption[axisIndexName]);},this);if(autoMode==='axisIndex'){this._autoSetAxisIndex();}else if(autoMode==='orient'){this._autoSetOrient();}},/**\n     * @private\n     */_judgeAutoMode:function _judgeAutoMode(){// Auto set only works for setOption at the first time.\n// The following is user's reponsibility. So using merged\n// option is OK.\nvar thisOption=this.option;var hasIndexSpecified=false;eachAxisDim(function(dimNames){// When user set axisIndex as a empty array, we think that user specify axisIndex\n// but do not want use auto mode. Because empty array may be encountered when\n// some error occured.\nif(thisOption[dimNames.axisIndex]!=null){hasIndexSpecified=true;}},this);var orient=thisOption.orient;if(orient==null&&hasIndexSpecified){return'orient';}else if(!hasIndexSpecified){if(orient==null){thisOption.orient='horizontal';}return'axisIndex';}},/**\n     * @private\n     */_autoSetAxisIndex:function _autoSetAxisIndex(){var autoAxisIndex=true;var orient=this.get('orient',true);var thisOption=this.option;var dependentModels=this.dependentModels;if(autoAxisIndex){// Find axis that parallel to dataZoom as default.\nvar dimName=orient==='vertical'?'y':'x';if(dependentModels[dimName+'Axis'].length){thisOption[dimName+'AxisIndex']=[0];autoAxisIndex=false;}else{each$12(dependentModels.singleAxis,function(singleAxisModel){if(autoAxisIndex&&singleAxisModel.get('orient',true)===orient){thisOption.singleAxisIndex=[singleAxisModel.componentIndex];autoAxisIndex=false;}});}}if(autoAxisIndex){// Find the first category axis as default. (consider polar)\neachAxisDim(function(dimNames){if(!autoAxisIndex){return;}var axisIndices=[];var axisModels=this.dependentModels[dimNames.axis];if(axisModels.length&&!axisIndices.length){for(var i=0,len=axisModels.length;i<len;i++){if(axisModels[i].get('type')==='category'){axisIndices.push(i);}}}thisOption[dimNames.axisIndex]=axisIndices;if(axisIndices.length){autoAxisIndex=false;}},this);}if(autoAxisIndex){// FIXME\n// 这里是兼容ec2的写法（没指定xAxisIndex和yAxisIndex时把scatter和双数值轴折柱纳入dataZoom控制），\n// 但是实际是否需要Grid.js#getScaleByOption来判断（考虑time，log等axis type）？\n// If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified,\n// dataZoom component auto adopts series that reference to\n// both xAxis and yAxis which type is 'value'.\nthis.ecModel.eachSeries(function(seriesModel){if(this._isSeriesHasAllAxesTypeOf(seriesModel,'value')){eachAxisDim(function(dimNames){var axisIndices=thisOption[dimNames.axisIndex];var axisIndex=seriesModel.get(dimNames.axisIndex);var axisId=seriesModel.get(dimNames.axisId);var axisModel=seriesModel.ecModel.queryComponents({mainType:dimNames.axis,index:axisIndex,id:axisId})[0];if(__DEV__){if(!axisModel){throw new Error(dimNames.axis+' \"'+retrieve(axisIndex,axisId,0)+'\" not found');}}axisIndex=axisModel.componentIndex;if(indexOf(axisIndices,axisIndex)<0){axisIndices.push(axisIndex);}});}},this);}},/**\n     * @private\n     */_autoSetOrient:function _autoSetOrient(){var dim;// Find the first axis\nthis.eachTargetAxis(function(dimNames){!dim&&(dim=dimNames.name);},this);this.option.orient=dim==='y'?'vertical':'horizontal';},/**\n     * @private\n     */_isSeriesHasAllAxesTypeOf:function _isSeriesHasAllAxesTypeOf(seriesModel,axisType){// FIXME\n// 需要series的xAxisIndex和yAxisIndex都首先自动设置上。\n// 例如series.type === scatter时。\nvar is=true;eachAxisDim(function(dimNames){var seriesAxisIndex=seriesModel.get(dimNames.axisIndex);var axisModel=this.dependentModels[dimNames.axis][seriesAxisIndex];if(!axisModel||axisModel.get('type')!==axisType){is=false;}},this);return is;},/**\n     * @private\n     */_setDefaultThrottle:function _setDefaultThrottle(inputRawOption){// When first time user set throttle, auto throttle ends.\nif(inputRawOption.hasOwnProperty('throttle')){this._autoThrottle=false;}if(this._autoThrottle){var globalOption=this.ecModel.option;this.option.throttle=globalOption.animation&&globalOption.animationDurationUpdate>0?100:20;}},/**\n     * @public\n     */getFirstTargetAxisModel:function getFirstTargetAxisModel(){var firstAxisModel;eachAxisDim(function(dimNames){if(firstAxisModel==null){var indices=this.get(dimNames.axisIndex);if(indices.length){firstAxisModel=this.dependentModels[dimNames.axis][indices[0]];}}},this);return firstAxisModel;},/**\n     * @public\n     * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel\n     */eachTargetAxis:function eachTargetAxis(callback,context){var ecModel=this.ecModel;eachAxisDim(function(dimNames){each$12(this.get(dimNames.axisIndex),function(axisIndex){callback.call(context,dimNames,axisIndex,this,ecModel);},this);},this);},/**\n     * @param {string} dimName\n     * @param {number} axisIndex\n     * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined.\n     */getAxisProxy:function getAxisProxy(dimName,axisIndex){return this._axisProxies[dimName+'_'+axisIndex];},/**\n     * @param {string} dimName\n     * @param {number} axisIndex\n     * @return {module:echarts/model/Model} If not found, return null/undefined.\n     */getAxisModel:function getAxisModel(dimName,axisIndex){var axisProxy=this.getAxisProxy(dimName,axisIndex);return axisProxy&&axisProxy.getAxisModel();},/**\n     * If not specified, set to undefined.\n     *\n     * @public\n     * @param {Object} opt\n     * @param {number} [opt.start]\n     * @param {number} [opt.end]\n     * @param {number} [opt.startValue]\n     * @param {number} [opt.endValue]\n     */setRawRange:function setRawRange(opt){var thisOption=this.option;var settledOption=this.settledOption;each$12([['start','startValue'],['end','endValue']],function(names){// Consider the pair <start, startValue>:\n// If one has value and the other one is `null/undefined`, we both set them\n// to `settledOption`. This strategy enables the feature to clear the original\n// value in `settledOption` to `null/undefined`.\n// But if both of them are `null/undefined`, we do not set them to `settledOption`\n// and keep `settledOption` with the original value. This strategy enables users to\n// only set <end or endValue> but not set <start or startValue> when calling\n// `dispatchAction`.\n// The pair <end, endValue> is treated in the same way.\nif(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);updateRangeUse(this,opt);},/**\n     * @public\n     * @param {Object} opt\n     * @param {number} [opt.start]\n     * @param {number} [opt.end]\n     * @param {number} [opt.startValue]\n     * @param {number} [opt.endValue]\n     */setCalculatedRange:function setCalculatedRange(opt){var option=this.option;each$12(['start','startValue','end','endValue'],function(name){option[name]=opt[name];});},/**\n     * @public\n     * @return {Array.<number>} [startPercent, endPercent]\n     */getPercentRange:function getPercentRange(){var axisProxy=this.findRepresentativeAxisProxy();if(axisProxy){return axisProxy.getDataPercentWindow();}},/**\n     * @public\n     * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0);\n     *\n     * @param {string} [axisDimName]\n     * @param {number} [axisIndex]\n     * @return {Array.<number>} [startValue, endValue] value can only be '-' or finite number.\n     */getValueRange:function getValueRange(axisDimName,axisIndex){if(axisDimName==null&&axisIndex==null){var axisProxy=this.findRepresentativeAxisProxy();if(axisProxy){return axisProxy.getDataValueWindow();}}else{return this.getAxisProxy(axisDimName,axisIndex).getDataValueWindow();}},/**\n     * @public\n     * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy\n     *      corresponding to the axisModel\n     * @return {module:echarts/component/dataZoom/AxisProxy}\n     */findRepresentativeAxisProxy:function findRepresentativeAxisProxy(axisModel){if(axisModel){return axisModel.__dzAxisProxy;}// Find the first hosted axisProxy\nvar axisProxies=this._axisProxies;for(var key in axisProxies){if(axisProxies.hasOwnProperty(key)&&axisProxies[key].hostedBy(this)){return axisProxies[key];}}// If no hosted axis find not hosted axisProxy.\n// Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis,\n// and the option.start or option.end settings are different. The percentRange\n// should follow axisProxy.\n// (We encounter this problem in toolbox data zoom.)\nfor(var key in axisProxies){if(axisProxies.hasOwnProperty(key)&&!axisProxies[key].hostedBy(this)){return axisProxies[key];}}},/**\n     * @return {Array.<string>}\n     */getRangePropMode:function getRangePropMode(){return this._rangePropMode.slice();}});/**\n * Retrieve the those raw params from option, which will be cached separately.\n * becasue they will be overwritten by normalized/calculated values in the main\n * process.\n */function retrieveRawOption(option){var ret={};each$12(['start','end','startValue','endValue','throttle'],function(name){option.hasOwnProperty(name)&&(ret[name]=option[name]);});return ret;}function updateRangeUse(dataZoomModel,inputRawOption){var rangePropMode=dataZoomModel._rangePropMode;var rangeModeInOption=dataZoomModel.get('rangeMode');each$12([['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){// percentSpecified && valueSpecified\nrangePropMode[index]='percent';}// else remain its original setting.\n});}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var DataZoomView=Component$1.extend({type:'dataZoom',render:function render(dataZoomModel,ecModel,api,payload){this.dataZoomModel=dataZoomModel;this.ecModel=ecModel;this.api=api;},/**\n     * Find the first target coordinate system.\n     *\n     * @protected\n     * @return {Object} {\n     *                   grid: [\n     *                       {model: coord0, axisModels: [axis1, axis3], coordIndex: 1},\n     *                       {model: coord1, axisModels: [axis0, axis2], coordIndex: 0},\n     *                       ...\n     *                   ],  // cartesians must not be null/undefined.\n     *                   polar: [\n     *                       {model: coord0, axisModels: [axis4], coordIndex: 0},\n     *                       ...\n     *                   ],  // polars must not be null/undefined.\n     *                   singleAxis: [\n     *                       {model: coord0, axisModels: [], coordIndex: 0}\n     *                   ]\n     */getTargetCoordInfo:function getTargetCoordInfo(){var dataZoomModel=this.dataZoomModel;var ecModel=this.ecModel;var coordSysLists={};dataZoomModel.eachTargetAxis(function(dimNames,axisIndex){var axisModel=ecModel.getComponent(dimNames.axis,axisIndex);if(axisModel){var coordModel=axisModel.getCoordSysModel();coordModel&&save(coordModel,axisModel,coordSysLists[coordModel.mainType]||(coordSysLists[coordModel.mainType]=[]),coordModel.componentIndex);}},this);function save(coordModel,axisModel,store,coordIndex){var item;for(var i=0;i<store.length;i++){if(store[i].model===coordModel){item=store[i];break;}}if(!item){store.push(item={model:coordModel,axisModels:[],coordIndex:coordIndex});}item.axisModels.push(axisModel);}return coordSysLists;}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var SliderZoomModel=DataZoomModel.extend({type:'dataZoom.slider',layoutMode:'box',/**\n     * @protected\n     */defaultOption:{show:true,// ph => placeholder. Using placehoder here because\n// deault value can only be drived in view stage.\nright:'ph',// Default align to grid rect.\ntop:'ph',// Default align to grid rect.\nwidth:'ph',// Default align to grid rect.\nheight:'ph',// Default align to grid rect.\nleft:null,// Default align to grid rect.\nbottom:null,// Default align to grid rect.\nbackgroundColor:'rgba(47,69,84,0)',// Background of slider zoom component.\n// dataBackgroundColor: '#ddd',         // Background coor of data shadow and border of box,\n// highest priority, remain for compatibility of\n// previous version, but not recommended any more.\ndataBackground:{lineStyle:{color:'#2f4554',width:0.5,opacity:0.3},areaStyle:{color:'rgba(47,69,84,0.3)',opacity:0.3}},borderColor:'#ddd',// border color of the box. For compatibility,\n// if dataBackgroundColor is set, borderColor\n// is ignored.\nfillerColor:'rgba(167,183,204,0.4)',// Color of selected area.\n// handleColor: 'rgba(89,170,216,0.95)',     // Color of handle.\n// handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z',\n/* eslint-disable */handleIcon:'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z',/* eslint-enable */ // Percent of the slider height\nhandleSize:'100%',handleStyle:{color:'#a7b7cc'},labelPrecision:null,labelFormatter:null,showDetail:true,showDataShadow:'auto',// Default auto decision.\nrealtime:true,zoomLock:false,// Whether disable zoom.\ntextStyle:{color:'#333'}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var Rect$1=Rect;var linearMap$1=linearMap;var asc$2=asc;var bind$3=bind;var each$14=each$1;// Constants\nvar DEFAULT_LOCATION_EDGE_GAP=7;var DEFAULT_FRAME_BORDER_WIDTH=1;var DEFAULT_FILLER_SIZE=30;var HORIZONTAL='horizontal';var VERTICAL='vertical';var LABEL_GAP=5;var SHOW_DATA_SHADOW_SERIES_TYPE=['line','bar','candlestick','scatter'];var SliderZoomView=DataZoomView.extend({type:'dataZoom.slider',init:function init(ecModel,api){/**\n         * @private\n         * @type {Object}\n         */this._displayables={};/**\n         * @private\n         * @type {string}\n         */this._orient;/**\n         * [0, 100]\n         * @private\n         */this._range;/**\n         * [coord of the first handle, coord of the second handle]\n         * @private\n         */this._handleEnds;/**\n         * [length, thick]\n         * @private\n         * @type {Array.<number>}\n         */this._size;/**\n         * @private\n         * @type {number}\n         */this._handleWidth;/**\n         * @private\n         * @type {number}\n         */this._handleHeight;/**\n         * @private\n         */this._location;/**\n         * @private\n         */this._dragging;/**\n         * @private\n         */this._dataShadowInfo;this.api=api;},/**\n     * @override\n     */render:function render(dataZoomModel,ecModel,api,payload){SliderZoomView.superApply(this,'render',arguments);createOrUpdate(this,'_dispatchZoomAction',this.dataZoomModel.get('throttle'),'fixRate');this._orient=dataZoomModel.get('orient');if(this.dataZoomModel.get('show')===false){this.group.removeAll();return;}// Notice: this._resetInterval() should not be executed when payload.type\n// is 'dataZoom', origin this._range should be maintained, otherwise 'pan'\n// or 'zoom' info will be missed because of 'throttle' of this.dispatchAction,\nif(!payload||payload.type!=='dataZoom'||payload.from!==this.uid){this._buildView();}this._updateView();},/**\n     * @override\n     */remove:function remove(){SliderZoomView.superApply(this,'remove',arguments);clear(this,'_dispatchZoomAction');},/**\n     * @override\n     */dispose:function dispose(){SliderZoomView.superApply(this,'dispose',arguments);clear(this,'_dispatchZoomAction');},_buildView:function _buildView(){var thisGroup=this.group;thisGroup.removeAll();this._resetLocation();this._resetInterval();var barGroup=this._displayables.barGroup=new Group();this._renderBackground();this._renderHandle();this._renderDataShadow();thisGroup.add(barGroup);this._positionGroup();},/**\n     * @private\n     */_resetLocation:function _resetLocation(){var dataZoomModel=this.dataZoomModel;var api=this.api;// If some of x/y/width/height are not specified,\n// auto-adapt according to target grid.\nvar coordRect=this._findCoordRect();var ecSize={width:api.getWidth(),height:api.getHeight()};// Default align by coordinate system rect.\nvar positionInfo=this._orient===HORIZONTAL?{// Why using 'right', because right should be used in vertical,\n// and it is better to be consistent for dealing with position param merge.\nright:ecSize.width-coordRect.x-coordRect.width,top:ecSize.height-DEFAULT_FILLER_SIZE-DEFAULT_LOCATION_EDGE_GAP,width:coordRect.width,height:DEFAULT_FILLER_SIZE}:{// vertical\nright:DEFAULT_LOCATION_EDGE_GAP,top:coordRect.y,width:DEFAULT_FILLER_SIZE,height:coordRect.height};// Do not write back to option and replace value 'ph', because\n// the 'ph' value should be recalculated when resize.\nvar layoutParams=getLayoutParams(dataZoomModel.option);// Replace the placeholder value.\neach$1(['right','top','width','height'],function(name){if(layoutParams[name]==='ph'){layoutParams[name]=positionInfo[name];}});var layoutRect=getLayoutRect(layoutParams,ecSize,dataZoomModel.padding);this._location={x:layoutRect.x,y:layoutRect.y};this._size=[layoutRect.width,layoutRect.height];this._orient===VERTICAL&&this._size.reverse();},/**\n     * @private\n     */_positionGroup:function _positionGroup(){var thisGroup=this.group;var location=this._location;var orient=this._orient;// Just use the first axis to determine mapping.\nvar targetAxisModel=this.dataZoomModel.getFirstTargetAxisModel();var inverse=targetAxisModel&&targetAxisModel.get('inverse');var barGroup=this._displayables.barGroup;var otherAxisInverse=(this._dataShadowInfo||{}).otherAxisInverse;// Transform barGroup.\nbarGroup.attr(orient===HORIZONTAL&&!inverse?{scale:otherAxisInverse?[1,1]:[1,-1]}:orient===HORIZONTAL&&inverse?{scale:otherAxisInverse?[-1,1]:[-1,-1]}:orient===VERTICAL&&!inverse?{scale:otherAxisInverse?[1,-1]:[1,1],rotation:Math.PI/2}// Dont use Math.PI, considering shadow direction.\n:{scale:otherAxisInverse?[-1,-1]:[-1,1],rotation:Math.PI/2});// Position barGroup\nvar rect=thisGroup.getBoundingRect([barGroup]);thisGroup.attr('position',[location.x-rect.x,location.y-rect.y]);},/**\n     * @private\n     */_getViewExtent:function _getViewExtent(){return[0,this._size[0]];},_renderBackground:function _renderBackground(){var dataZoomModel=this.dataZoomModel;var size=this._size;var barGroup=this._displayables.barGroup;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}));// Click panel, over shadow, below handles.\nbarGroup.add(new Rect$1({shape:{x:0,y:0,width:size[0],height:size[1]},style:{fill:'transparent'},z2:0,onclick:bind(this._onClickPanelClick,this)}));},_renderDataShadow:function _renderDataShadow(){var info=this._dataShadowInfo=this._prepareDataShadowInfo();if(!info){return;}var size=this._size;var seriesModel=info.series;var data=seriesModel.getRawData();var otherDim=seriesModel.getShadowDim?seriesModel.getShadowDim()// @see candlestick\n:info.otherDim;if(otherDim==null){return;}var otherDataExtent=data.getDataExtent(otherDim);// Nice extent.\nvar 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;// Optimize for large data shadow\nvar stride=Math.round(data.count()/size[0]);var lastIsEmpty;data.each([otherDim],function(value,index){if(stride>0&&index%stride){thisCoord+=step;return;}// FIXME\n// Should consider axis.min/axis.max when drawing dataShadow.\n// FIXME\n// 应该使用统一的空判断？还是在list里进行空判断？\nvar isEmpty=value==null||isNaN(value)||value==='';// See #4235.\nvar otherCoord=isEmpty?0:linearMap$1(value,otherDataExtent,otherShadowExtent,true);// Attempt to draw data shadow precisely when there are empty value.\nif(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;// var dataBackgroundModel = dataZoomModel.getModel('dataBackground');\nthis._displayables.barGroup.add(new Polygon({shape:{points:areaPoints},style:defaults({fill:dataZoomModel.get('dataBackgroundColor')},dataZoomModel.getModel('dataBackground.areaStyle').getAreaStyle()),silent:true,z2:-20}));this._displayables.barGroup.add(new Polyline({shape:{points:linePoints},style:dataZoomModel.getModel('dataBackground.lineStyle').getLineStyle(),silent:true,z2:-19}));},_prepareDataShadowInfo:function _prepareDataShadowInfo(){var dataZoomModel=this.dataZoomModel;var showDataShadow=dataZoomModel.get('showDataShadow');if(showDataShadow===false){return;}// Find a representative series.\nvar result;var ecModel=this.ecModel;dataZoomModel.eachTargetAxis(function(dimNames,axisIndex){var seriesModels=dataZoomModel.getAxisProxy(dimNames.name,axisIndex).getTargetSeriesModels();each$1(seriesModels,function(seriesModel){if(result){return;}if(showDataShadow!==true&&indexOf(SHOW_DATA_SHADOW_SERIES_TYPE,seriesModel.get('type'))<0){return;}var thisAxis=ecModel.getComponent(dimNames.axis,axisIndex).axis;var otherDim=getOtherDim(dimNames.name);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:dimNames.name,otherDim:otherDim,otherAxisInverse:otherAxisInverse};},this);},this);return result;},_renderHandle:function _renderHandle(){var displaybles=this._displayables;var handles=displaybles.handles=[];var handleLabels=displaybles.handleLabels=[];var barGroup=this._displayables.barGroup;var size=this._size;var dataZoomModel=this.dataZoomModel;barGroup.add(displaybles.filler=new Rect$1({draggable:true,cursor:getCursor(this._orient),drift:bind$3(this._onDragMove,this,'all'),ondragstart:bind$3(this._showDataInfo,this,true),ondragend:bind$3(this._onDragEnd,this),onmouseover:bind$3(this._showDataInfo,this,true),onmouseout:bind$3(this._showDataInfo,this,false),style:{fill:dataZoomModel.get('fillerColor'),textPosition:'inside'}}));// Frame border.\nbarGroup.add(new Rect$1({silent:true,subPixelOptimize:true,shape:{x:0,y:0,width:size[0],height:size[1]},style:{stroke:dataZoomModel.get('dataBackgroundColor')||dataZoomModel.get('borderColor'),lineWidth:DEFAULT_FRAME_BORDER_WIDTH,fill:'rgba(0,0,0,0)'}}));each$14([0,1],function(handleIndex){var path=createIcon(dataZoomModel.get('handleIcon'),{cursor:getCursor(this._orient),draggable:true,drift:bind$3(this._onDragMove,this,handleIndex),ondragend:bind$3(this._onDragEnd,this),onmouseover:bind$3(this._showDataInfo,this,true),onmouseout:bind$3(this._showDataInfo,this,false)},{x:-1,y:0,width:2,height:2});var bRect=path.getBoundingRect();this._handleHeight=parsePercent$1(dataZoomModel.get('handleSize'),this._size[1]);this._handleWidth=bRect.width/bRect.height*this._handleHeight;path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle());var handleColor=dataZoomModel.get('handleColor');// Compatitable with previous version\nif(handleColor!=null){path.style.fill=handleColor;}barGroup.add(handles[handleIndex]=path);var textStyleModel=dataZoomModel.textStyleModel;this.group.add(handleLabels[handleIndex]=new Text({silent:true,invisible:true,style:{x:0,y:0,text:'',textVerticalAlign:'middle',textAlign:'center',textFill:textStyleModel.getTextColor(),textFont:textStyleModel.getFont()},z2:10}));},this);},/**\n     * @private\n     */_resetInterval:function _resetInterval(){var range=this._range=this.dataZoomModel.getPercentRange();var viewExtent=this._getViewExtent();this._handleEnds=[linearMap$1(range[0],[0,100],viewExtent,true),linearMap$1(range[1],[0,100],viewExtent,true)];},/**\n     * @private\n     * @param {(number|string)} handleIndex 0 or 1 or 'all'\n     * @param {number} delta\n     * @return {boolean} changed\n     */_updateInterval:function _updateInterval(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$1(minMaxSpan.minSpan,percentExtent,viewExtend,true):null,minMaxSpan.maxSpan!=null?linearMap$1(minMaxSpan.maxSpan,percentExtent,viewExtend,true):null);var lastRange=this._range;var range=this._range=asc$2([linearMap$1(handleEnds[0],viewExtend,percentExtent,true),linearMap$1(handleEnds[1],viewExtend,percentExtent,true)]);return!lastRange||lastRange[0]!==range[0]||lastRange[1]!==range[1];},/**\n     * @private\n     */_updateView:function _updateView(nonRealtime){var displaybles=this._displayables;var handleEnds=this._handleEnds;var handleInterval=asc$2(handleEnds.slice());var size=this._size;each$14([0,1],function(handleIndex){// Handles\nvar handle=displaybles.handles[handleIndex];var handleHeight=this._handleHeight;handle.attr({scale:[handleHeight/2,handleHeight/2],position:[handleEnds[handleIndex],size[1]/2-handleHeight/2]});},this);// Filler\ndisplaybles.filler.setShape({x:handleInterval[0],y:0,width:handleInterval[1]-handleInterval[0],height:size[1]});this._updateDataInfo(nonRealtime);},/**\n     * @private\n     */_updateDataInfo:function _updateDataInfo(nonRealtime){var dataZoomModel=this.dataZoomModel;var displaybles=this._displayables;var handleLabels=displaybles.handleLabels;var orient=this._orient;var labelTexts=['',''];// FIXME\n// date型，支持formatter，autoformatter（ec2 date.getAutoFormatter）\nif(dataZoomModel.get('showDetail')){var axisProxy=dataZoomModel.findRepresentativeAxisProxy();if(axisProxy){var axis=axisProxy.getAxisModel().axis;var range=this._range;var dataInterval=nonRealtime// See #4434, data and axis are not processed and reset yet in non-realtime mode.\n?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$2(this._handleEnds.slice());setLabel.call(this,0);setLabel.call(this,1);function setLabel(handleIndex){// Label\n// Text should not transform by barGroup.\n// Ignore handlers transform\nvar 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],textVerticalAlign:orient===HORIZONTAL?'middle':direction,textAlign:orient===HORIZONTAL?direction:'center',text:labelTexts[handleIndex]});}},/**\n     * @private\n     */_formatLabel:function _formatLabel(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)?''// FIXME Glue code\n:axis.type==='category'||axis.type==='time'?axis.scale.getLabel(Math.round(value))// param of toFixed should less then 20.\n:value.toFixed(Math.min(labelPrecision,20));return isFunction$1(labelFormatter)?labelFormatter(value,valueStr):isString(labelFormatter)?labelFormatter.replace('{value}',valueStr):valueStr;},/**\n     * @private\n     * @param {boolean} showOrHide true: show, false: hide\n     */_showDataInfo:function _showDataInfo(showOrHide){// Always show when drgging.\nshowOrHide=this._dragging||showOrHide;var handleLabels=this._displayables.handleLabels;handleLabels[0].attr('invisible',!showOrHide);handleLabels[1].attr('invisible',!showOrHide);},_onDragMove:function _onDragMove(handleIndex,dx,dy,event){this._dragging=true;// For mobile device, prevent screen slider on the button.\nstop(event.event);// Transform dx, dy to bar coordination.\nvar barTransform=this._displayables.barGroup.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);// Avoid dispatch dataZoom repeatly but range not changed,\n// which cause bad visual effect when progressive enabled.\nchanged&&realtime&&this._dispatchZoomAction();},_onDragEnd:function _onDragEnd(){this._dragging=false;this._showDataInfo(false);// While in realtime mode and stream mode, dispatch action when\n// drag end will cause the whole view rerender, which is unnecessary.\nvar realtime=this.dataZoomModel.get('realtime');!realtime&&this._dispatchZoomAction();},_onClickPanelClick:function _onClickPanelClick(e){var size=this._size;var localPoint=this._displayables.barGroup.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();},/**\n     * This action will be throttled.\n     * @private\n     */_dispatchZoomAction:function _dispatchZoomAction(){var range=this._range;this.api.dispatchAction({type:'dataZoom',from:this.uid,dataZoomId:this.dataZoomModel.id,start:range[0],end:range[1]});},/**\n     * @private\n     */_findCoordRect:function _findCoordRect(){// Find the grid coresponding to the first axis referred by dataZoom.\nvar rect;each$14(this.getTargetCoordInfo(),function(coordInfoList){if(!rect&&coordInfoList.length){var coordSys=coordInfoList[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;}});function getOtherDim(thisDim){// FIXME\n// 这个逻辑和getOtherAxis里一致，但是写在这里是否不好\nvar map$$1={x:'y',y:'x',radius:'angle',angle:'radius'};return map$$1[thisDim];}function getCursor(orient){return orient==='vertical'?'ns-resize':'ew-resize';}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/registerProcessor({// `dataZoomProcessor` will only be performed in needed series. Consider if\n// there is a line series and a pie series, it is better not to update the\n// line series if only pie series is needed to be updated.\ngetTargetSeries:function getTargetSeries(ecModel){var seriesModelMap=createHashMap();ecModel.eachComponent('dataZoom',function(dataZoomModel){dataZoomModel.eachTargetAxis(function(dimNames,axisIndex,dataZoomModel){var axisProxy=dataZoomModel.getAxisProxy(dimNames.name,axisIndex);each$1(axisProxy.getTargetSeriesModels(),function(seriesModel){seriesModelMap.set(seriesModel.uid,seriesModel);});});});return seriesModelMap;},modifyOutputEnd:true,// Consider appendData, where filter should be performed. Because data process is\n// in block mode currently, it is not need to worry about that the overallProgress\n// execute every frame.\noverallReset:function overallReset(ecModel,api){ecModel.eachComponent('dataZoom',function(dataZoomModel){// We calculate window and reset axis here but not in model\n// init stage and not after action dispatch handler, because\n// reset should be called after seriesData.restoreData.\ndataZoomModel.eachTargetAxis(function(dimNames,axisIndex,dataZoomModel){dataZoomModel.getAxisProxy(dimNames.name,axisIndex).reset(dataZoomModel,api);});// Caution: data zoom filtering is order sensitive when using\n// percent range and no min/max/scale set on axis.\n// For example, we have dataZoom definition:\n// [\n//      {xAxisIndex: 0, start: 30, end: 70},\n//      {yAxisIndex: 0, start: 20, end: 80}\n// ]\n// In this case, [20, 80] of y-dataZoom should be based on data\n// that have filtered by x-dataZoom using range of [30, 70],\n// but should not be based on full raw data. Thus sliding\n// x-dataZoom will change both ranges of xAxis and yAxis,\n// while sliding y-dataZoom will only change the range of yAxis.\n// So we should filter x-axis after reset x-axis immediately,\n// and then reset y-axis and filter y-axis.\ndataZoomModel.eachTargetAxis(function(dimNames,axisIndex,dataZoomModel){dataZoomModel.getAxisProxy(dimNames.name,axisIndex).filterData(dataZoomModel,api);});});ecModel.eachComponent('dataZoom',function(dataZoomModel){// Fullfill all of the range props so that user\n// is able to get them from chart.getOption().\nvar axisProxy=dataZoomModel.findRepresentativeAxisProxy();var percentRange=axisProxy.getDataPercentWindow();var valueRange=axisProxy.getDataValueWindow();dataZoomModel.setCalculatedRange({start:percentRange[0],end:percentRange[1],startValue:valueRange[0],endValue:valueRange[1]});});}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/registerAction('dataZoom',function(payload,ecModel){var linkedNodesFinder=createLinkedNodesFinder(bind(ecModel.eachComponent,ecModel,'dataZoom'),eachAxisDim$1,function(model,dimNames){return model.get(dimNames.axisIndex);});var effectedModels=[];ecModel.eachComponent({mainType:'dataZoom',query:payload},function(model,index){effectedModels.push.apply(effectedModels,linkedNodesFinder(model).nodes);});each$1(effectedModels,function(dataZoomModel,index){dataZoomModel.setRawRange({start:payload.start,end:payload.end,startValue:payload.startValue,endValue:payload.endValue});});});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/DataZoomModel.extend({type:'dataZoom.inside',/**\n     * @protected\n     */defaultOption:{disabled:false,// Whether disable this inside zoom.\nzoomLock:false,// Whether disable zoom but only pan.\nzoomOnMouseWheel:true,// Can be: true / false / 'shift' / 'ctrl' / 'alt'.\nmoveOnMouseMove:true,// Can be: true / false / 'shift' / 'ctrl' / 'alt'.\nmoveOnMouseWheel:false,// Can be: true / false / 'shift' / 'ctrl' / 'alt'.\npreventDefaultMouseMove:true}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var ATTR$1='\\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$1]||(zr[ATTR$1]={});}/**\n * payload: {\n *     type: 'takeGlobalCursor',\n *     key: 'dataZoomSelect', or 'brush', or ...,\n *         If no userKey, release global cursor.\n * }\n */registerAction({type:'takeGlobalCursor',event:'globalCursorTaken',update:'update'},function(){});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * @alias module:echarts/component/helper/RoamController\n * @constructor\n * @mixin {module:zrender/mixin/Eventful}\n *\n * @param {module:zrender/zrender~ZRender} zr\n */function RoamController(zr){/**\n     * @type {Function}\n     */this.pointerChecker;/**\n     * @type {module:zrender}\n     */this._zr=zr;/**\n     * @type {Object}\n     */this._opt={};// Avoid two roamController bind the same handler\nvar bind$$1=bind;var mousedownHandler=bind$$1(mousedown,this);var mousemoveHandler=bind$$1(mousemove,this);var mouseupHandler=bind$$1(mouseup,this);var mousewheelHandler=bind$$1(mousewheel,this);var pinchHandler=bind$$1(pinch,this);Eventful.call(this);/**\n     * @param {Function} pointerChecker\n     *                   input: x, y\n     *                   output: boolean\n     */this.setPointerChecker=function(pointerChecker){this.pointerChecker=pointerChecker;};/**\n     * Notice: only enable needed types. For example, if 'zoom'\n     * is not needed, 'zoom' should not be enabled, otherwise\n     * default mousewheel behaviour (scroll page) will be disabled.\n     *\n     * @param  {boolean|string} [controlType=true] Specify the control type,\n     *                          which can be null/undefined or true/false\n     *                          or 'pan/move' or 'zoom'/'scale'\n     * @param {Object} [opt]\n     * @param {Object} [opt.zoomOnMouseWheel=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.\n     * @param {Object} [opt.moveOnMouseMove=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.\n     * @param {Object} [opt.moveOnMouseWheel=false] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.\n     * @param {Object} [opt.preventDefaultMouseMove=true] When pan.\n     */this.enable=function(controlType,opt){// Disable previous first\nthis.disable();this._opt=defaults(_clone(opt)||{},{zoomOnMouseWheel:true,moveOnMouseMove:true,// By default, wheel do not trigger move.\nmoveOnMouseWheel: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);};this.dispose=this.disable;this.isDragging=function(){return this._dragging;};this.isPinching=function(){return this._pinching;};}mixin(RoamController,Eventful);function mousedown(e){if(isMiddleOrRightButtonOnMouseUpDown(e)||e.target&&e.target.draggable){return;}var x=e.offsetX;var y=e.offsetY;// Only check on mosedown, but not mousemove.\n// Mouse can be out of target when mouse moving.\nif(this.pointerChecker&&this.pointerChecker(e,x,y)){this._x=x;this._y=y;this._dragging=true;}}function mousemove(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});}function mouseup(e){if(!isMiddleOrRightButtonOnMouseUpDown(e)){this._dragging=false;}}function mousewheel(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;// wheelDelta maybe -0 in chrome mac.\nif(wheelDelta===0||!shouldZoom&&!shouldMove){return;}// If both `shouldZoom` and `shouldMove` is true, trigger\n// their event both, and the final behavior is determined\n// by event listener themselves.\nif(shouldZoom){// Convenience:\n// Mac and VM Windows on Mac: scroll up: zoom out.\n// Windows: scroll up: zoom in.\n// FIXME: Should do more test in different environment.\n// wheelDelta is too complicated in difference nvironment\n// (https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel),\n// although it has been normallized by zrender.\n// wheelDelta of mouse wheel is bigger than touch pad.\nvar 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});}if(shouldMove){// FIXME: Should do more test in different environment.\nvar absDelta=Math.abs(wheelDelta);// wheelDelta of mouse wheel is bigger than touch pad.\nvar 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});}}function pinch(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});}function checkPointerAndTrigger(controller,eventName,behaviorToCheck,e,contollerEvent){if(controller.pointerChecker&&controller.pointerChecker(e,contollerEvent.originX,contollerEvent.originY)){// When mouse is out of roamController rect,\n// default befavoius should not be be disabled, otherwise\n// page sliding is disabled, contrary to expectation.\nstop(e.event);trigger(controller,eventName,behaviorToCheck,e,contollerEvent);}}function trigger(controller,eventName,behaviorToCheck,e,contollerEvent){// Also provide behavior checker for event listener, for some case that\n// multiple components share one listener.\ncontollerEvent.isAvailableBehavior=bind(isAvailableBehavior,null,behaviorToCheck,e);controller.trigger(eventName,contollerEvent);}// settings: {\n//     zoomOnMouseWheel\n//     moveOnMouseMove\n//     moveOnMouseWheel\n// }\n// The value can be: true / false / 'shift' / 'ctrl' / 'alt'.\nfunction isAvailableBehavior(behaviorToCheck,e,settings){var setting=settings[behaviorToCheck];return!behaviorToCheck||setting&&(!isString(setting)||e.event[setting+'Key']);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Only create one roam controller for each coordinate system.\n// one roam controller might be refered by two inside data zoom\n// components (for example, one for x and one for y). When user\n// pan or zoom, only dispatch one action for those data zoom\n// components.\nvar ATTR='\\0_ec_dataZoom_roams';/**\n * @public\n * @param {module:echarts/ExtensionAPI} api\n * @param {Object} dataZoomInfo\n * @param {string} dataZoomInfo.coordId\n * @param {Function} dataZoomInfo.containsPoint\n * @param {Array.<string>} dataZoomInfo.allCoordIds\n * @param {string} dataZoomInfo.dataZoomId\n * @param {Object} dataZoomInfo.getRange\n * @param {Function} dataZoomInfo.getRange.pan\n * @param {Function} dataZoomInfo.getRange.zoom\n * @param {Function} dataZoomInfo.getRange.scrollMove\n * @param {boolean} dataZoomInfo.dataZoomModel\n */function register$1(api,dataZoomInfo){var store=giveStore(api);var theDataZoomId=dataZoomInfo.dataZoomId;var theCoordId=dataZoomInfo.coordId;// Do clean when a dataZoom changes its target coordnate system.\n// Avoid memory leak, dispose all not-used-registered.\neach$1(store,function(record,coordId){var dataZoomInfos=record.dataZoomInfos;if(dataZoomInfos[theDataZoomId]&&indexOf(dataZoomInfo.allCoordIds,theCoordId)<0){delete dataZoomInfos[theDataZoomId];record.count--;}});cleanStore(store);var record=store[theCoordId];// Create if needed.\nif(!record){record=store[theCoordId]={coordId:theCoordId,dataZoomInfos:{},count:0};record.controller=createController(api,record);record.dispatchAction=curry(dispatchAction,api);}// Update reference of dataZoom.\n!record.dataZoomInfos[theDataZoomId]&&record.count++;record.dataZoomInfos[theDataZoomId]=dataZoomInfo;var controllerParams=mergeControllerParams(record.dataZoomInfos);record.controller.enable(controllerParams.controlType,controllerParams.opt);// Consider resize, area should be always updated.\nrecord.controller.setPointerChecker(dataZoomInfo.containsPoint);// Update throttle.\ncreateOrUpdate(record,'dispatchAction',dataZoomInfo.dataZoomModel.get('throttle',true),'fixRate');}/**\n * @public\n * @param {module:echarts/ExtensionAPI} api\n * @param {string} dataZoomId\n */function unregister$1(api,dataZoomId){var store=giveStore(api);each$1(store,function(record){record.controller.dispose();var dataZoomInfos=record.dataZoomInfos;if(dataZoomInfos[dataZoomId]){delete dataZoomInfos[dataZoomId];record.count--;}});cleanStore(store);}/**\n * @public\n */function generateCoordId(coordModel){return coordModel.type+'\\0_'+coordModel.id;}/**\n * Key: coordId, value: {dataZoomInfos: [], count, controller}\n * @type {Array.<Object>}\n */function giveStore(api){// Mount store on zrender instance, so that we do not\n// need to worry about dispose.\nvar zr=api.getZr();return zr[ATTR]||(zr[ATTR]={});}function createController(api,newRecord){var controller=new RoamController(api.getZr());each$1(['pan','zoom','scrollMove'],function(eventName){controller.on(eventName,function(event){var batch=[];each$1(newRecord.dataZoomInfos,function(info){// Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove,\n// moveOnMouseWheel, ...) enabled.\nif(!event.isAvailableBehavior(info.dataZoomModel.option)){return;}var method=(info.getRange||{})[eventName];var range=method&&method(newRecord.controller,event);!info.dataZoomModel.get('disabled',true)&&range&&batch.push({dataZoomId:info.dataZoomId,start:range[0],end:range[1]});});batch.length&&newRecord.dispatchAction(batch);});});return controller;}function cleanStore(store){each$1(store,function(record,coordId){if(!record.count){record.controller.dispose();delete store[coordId];}});}/**\n * This action will be throttled.\n */function dispatchAction(api,batch){api.dispatchAction({type:'dataZoom',batch:batch});}/**\n * Merge roamController settings when multiple dataZooms share one roamController.\n */function mergeControllerParams(dataZoomInfos){var controlType;// DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated\n// as string, it is probably revert to reserved word by compress tool. See #7411.\nvar prefix='type_';var typePriority={'type_true':2,'type_move':1,'type_false':0,'type_undefined':-1};var preventDefaultMouseMove=true;each$1(dataZoomInfos,function(dataZoomInfo){var dataZoomModel=dataZoomInfo.dataZoomModel;var oneType=dataZoomModel.get('disabled',true)?false:dataZoomModel.get('zoomLock',true)?'move':true;if(typePriority[prefix+oneType]>typePriority[prefix+controlType]){controlType=oneType;}// Prevent default move event by default. If one false, do not prevent. Otherwise\n// users may be confused why it does not work when multiple insideZooms exist.\npreventDefaultMouseMove&=dataZoomModel.get('preventDefaultMouseMove',true);});return{controlType:controlType,opt:{// RoamController will enable all of these functionalities,\n// and the final behavior is determined by its event listener\n// provided by each inside zoom.\nzoomOnMouseWheel:true,moveOnMouseMove:true,moveOnMouseWheel:true,preventDefaultMouseMove:!!preventDefaultMouseMove}};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var bind$4=bind;var InsideZoomView=DataZoomView.extend({type:'dataZoom.inside',/**\n     * @override\n     */init:function init(ecModel,api){/**\n         * 'throttle' is used in this.dispatchAction, so we save range\n         * to avoid missing some 'pan' info.\n         * @private\n         * @type {Array.<number>}\n         */this._range;},/**\n     * @override\n     */render:function render(dataZoomModel,ecModel,api,payload){InsideZoomView.superApply(this,'render',arguments);// Hence the `throttle` util ensures to preserve command order,\n// here simply updating range all the time will not cause missing\n// any of the the roam change.\nthis._range=dataZoomModel.getPercentRange();// Reset controllers.\neach$1(this.getTargetCoordInfo(),function(coordInfoList,coordSysName){var allCoordIds=map(coordInfoList,function(coordInfo){return generateCoordId(coordInfo.model);});each$1(coordInfoList,function(coordInfo){var coordModel=coordInfo.model;var getRange={};each$1(['pan','zoom','scrollMove'],function(eventName){getRange[eventName]=bind$4(roamHandlers[eventName],this,coordInfo,coordSysName);},this);register$1(api,{coordId:generateCoordId(coordModel),allCoordIds:allCoordIds,containsPoint:function containsPoint(e,x,y){return coordModel.coordinateSystem.containPoint([x,y]);},dataZoomId:dataZoomModel.id,dataZoomModel:dataZoomModel,getRange:getRange});},this);},this);},/**\n     * @override\n     */dispose:function dispose(){unregister$1(this.api,this.dataZoomModel.id);InsideZoomView.superApply(this,'dispose',arguments);this._range=null;}});var roamHandlers={/**\n     * @this {module:echarts/component/dataZoom/InsideZoomView}\n     */zoom:function zoom(coordInfo,coordSysName,controller,e){var lastRange=this._range;var range=lastRange.slice();// Calculate transform by the first axis.\nvar axisModel=coordInfo.axisModels[0];if(!axisModel){return;}var directionInfo=getDirectionInfo[coordSysName](null,[e.originX,e.originY],axisModel,controller,coordInfo);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;// Restrict range.\nvar 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;}},/**\n     * @this {module:echarts/component/dataZoom/InsideZoomView}\n     */pan:makeMover(function(range,axisModel,coordInfo,coordSysName,controller,e){var directionInfo=getDirectionInfo[coordSysName]([e.oldX,e.oldY],[e.newX,e.newY],axisModel,controller,coordInfo);return directionInfo.signal*(range[1]-range[0])*directionInfo.pixel/directionInfo.pixelLength;}),/**\n     * @this {module:echarts/component/dataZoom/InsideZoomView}\n     */scrollMove:makeMover(function(range,axisModel,coordInfo,coordSysName,controller,e){var directionInfo=getDirectionInfo[coordSysName]([0,0],[e.scrollDelta,e.scrollDelta],axisModel,controller,coordInfo);return directionInfo.signal*(range[1]-range[0])*e.scrollDelta;})};function makeMover(getPercentDelta){return function(coordInfo,coordSysName,controller,e){var lastRange=this._range;var range=lastRange.slice();// Calculate transform by the first axis.\nvar axisModel=coordInfo.axisModels[0];if(!axisModel){return;}var percentDelta=getPercentDelta(range,axisModel,coordInfo,coordSysName,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 grid(oldPoint,newPoint,axisModel,controller,coordInfo){var axis=axisModel.axis;var ret={};var rect=coordInfo.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{// axis.dim === 'y'\nret.pixel=newPoint[1]-oldPoint[1];ret.pixelLength=rect.height;ret.pixelStart=rect.y;ret.signal=axis.inverse?-1:1;}return ret;},polar:function polar(oldPoint,newPoint,axisModel,controller,coordInfo){var axis=axisModel.axis;var ret={};var polar=coordInfo.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 = Math.abs(radiusExtent[1] - radiusExtent[0]);\n// ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]);\nret.pixelLength=radiusExtent[1]-radiusExtent[0];ret.pixelStart=radiusExtent[0];ret.signal=axis.inverse?1:-1;}else{// 'angleAxis'\nret.pixel=newPoint[1]-oldPoint[1];// ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]);\n// ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]);\nret.pixelLength=angleExtent[1]-angleExtent[0];ret.pixelStart=angleExtent[0];ret.signal=axis.inverse?-1:1;}return ret;},singleAxis:function singleAxis(oldPoint,newPoint,axisModel,controller,coordInfo){var axis=axisModel.axis;var rect=coordInfo.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{// 'vertical'\nret.pixel=newPoint[1]-oldPoint[1];ret.pixelLength=rect.height;ret.pixelStart=rect.y;ret.signal=axis.inverse?-1:1;}return ret;}};/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Do not include './dataZoomSelect',\n// since it only work for toolbox dataZoom.\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var features={};function register$2(name,ctor){features[name]=ctor;}function get$1(name){return features[name];}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var ToolboxModel=extendComponentModel({type:'toolbox',layoutMode:{type:'box',ignoreSize:true},optionUpdated:function optionUpdated(){ToolboxModel.superApply(this,'optionUpdated',arguments);each$1(this.option.feature,function(featureOpt,featureName){var Feature=get$1(featureName);Feature&&merge(featureOpt,Feature.defaultOption);});},defaultOption:{show:true,z:6,zlevel:0,orient:'horizontal',left:'right',top:'top',// right\n// bottom\nbackgroundColor:'transparent',borderColor:'#ccc',borderRadius:0,borderWidth:0,padding:5,itemSize:15,itemGap:8,showTitle:true,iconStyle:{borderColor:'#666',color:'none'},emphasis:{iconStyle:{borderColor:'#3E98C5'}},// textStyle: {},\n// feature\ntooltip:{show:false}}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/extendComponentView({type:'toolbox',render:function render(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$1(featureOpts,function(opt,name){featureNames.push(name);});new DataDiffer(this._featureNames||[],featureNames).add(processFeature).update(processFeature).remove(curry(processFeature,null)).execute();// Keep for diff.\nthis._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;// FIX#11236, merge feature title from MagicType newOption. TODO: consider seriesIndex ?\nif(payload&&payload.newTitle!=null&&payload.featureName===featureName){featureOpt.title=payload.newTitle;}if(featureName&&!oldName){// Create\nif(isUserFeatureName(featureName)){feature={model:featureModel,onclick:featureModel.option.onclick,featureName:featureName};}else{var Feature=get$1(featureName);if(!Feature){return;}feature=new Feature(featureModel,ecModel,api);}features[featureName]=feature;}else{feature=features[oldName];// If feature does not exsit.\nif(!feature){return;}feature.model=featureModel;feature.ecModel=ecModel;feature.api=api;}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;// FIXME\niconPaths[iconName]&&iconPaths[iconName].trigger(status);};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');// If one feature has mutiple icon. they are orginaized as\n// {\n//     icon: {\n//         foo: '',\n//         bar: ''\n//     },\n//     title: {\n//         foo: '',\n//         bar: ''\n//     }\n// }\nvar icons=feature.getIcons?feature.getIcons():featureModel.get('icon');var titles=featureModel.get('title')||{};if(typeof icons==='string'){var icon=icons;var title=titles;icons={};titles={};icons[featureName]=icon;titles[featureName]=title;}var iconPaths=featureModel.iconPaths={};each$1(icons,function(iconStr,iconName){var path=createIcon(iconStr,{},{x:-itemSize/2,y:-itemSize/2,width:itemSize,height:itemSize});path.setStyle(iconStyleModel.getItemStyle());path.hoverStyle=iconStyleEmphasisModel.getItemStyle();// Text position calculation\npath.setStyle({text:titles[iconName],textAlign:iconStyleEmphasisModel.get('textAlign'),textBorderRadius:iconStyleEmphasisModel.get('textBorderRadius'),textPadding:iconStyleEmphasisModel.get('textPadding'),textFill:null});var tooltipModel=toolboxModel.getModel('tooltip');if(tooltipModel&&tooltipModel.get('show')){path.attr('tooltip',extend({content:titles[iconName],formatter:tooltipModel.get('formatter',true)||function(){return titles[iconName];},formatterParams:{componentType:'toolbox',name:iconName,title:titles[iconName],$vars:['name','title']},position:tooltipModel.get('position',true)||'bottom'},tooltipModel.option));}setHoverStyle(path);if(toolboxModel.get('showTitle')){path.__title=titles[iconName];path.on('mouseover',function(){// Should not reuse above hoverStyle, which might be modified.\nvar hoverStyle=iconStyleEmphasisModel.getItemStyle();var defaultTextPosition=toolboxModel.get('orient')==='vertical'?toolboxModel.get('right')==null?'right':'left':toolboxModel.get('bottom')==null?'bottom':'top';path.setStyle({textFill:iconStyleEmphasisModel.get('textFill')||hoverStyle.fill||hoverStyle.stroke||'#000',textBackgroundColor:iconStyleEmphasisModel.get('textBackgroundColor'),textPosition:iconStyleEmphasisModel.get('textPosition')||defaultTextPosition});}).on('mouseout',function(){path.setStyle({textFill:null,textBackgroundColor:null});});}path.trigger(featureModel.get('iconStatus.'+iconName)||'normal');group.add(path);path.on('click',bind(feature.onclick,feature,ecModel,api,iconName));iconPaths[iconName]=path;});}layout$2(group,toolboxModel,api);// Render background after group is layout\n// FIXME\ngroup.add(makeBackground(group.getBoundingRect(),toolboxModel));// Adjust icon title positions to avoid them out of screen\ngroup.eachChild(function(icon){var titleText=icon.__title;var hoverStyle=icon.hoverStyle;// May be background element\nif(hoverStyle&&titleText){var rect=_getBoundingRect(titleText,makeFont(hoverStyle));var offsetX=icon.position[0]+group.position[0];var offsetY=icon.position[1]+group.position[1]+itemSize;var needPutOnTop=false;if(offsetY+rect.height>api.getHeight()){hoverStyle.textPosition='top';needPutOnTop=true;}var topOffset=needPutOnTop?-5-rect.height:itemSize+8;if(offsetX+rect.width/2>api.getWidth()){hoverStyle.textPosition=['100%',topOffset];hoverStyle.textAlign='right';}else if(offsetX-rect.width/2<0){hoverStyle.textPosition=[0,topOffset];hoverStyle.textAlign='left';}}});},updateView:function updateView(toolboxModel,ecModel,api,payload){each$1(this._features,function(feature){feature.updateView&&feature.updateView(feature.model,ecModel,api,payload);});},// updateLayout: function (toolboxModel, ecModel, api, payload) {\n//     zrUtil.each(this._features, function (feature) {\n//         feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload);\n//     });\n// },\nremove:function remove(ecModel,api){each$1(this._features,function(feature){feature.remove&&feature.remove(ecModel,api);});this.group.removeAll();},dispose:function dispose(ecModel,api){each$1(this._features,function(feature){feature.dispose&&feature.dispose(ecModel,api);});}});function isUserFeatureName(featureName){return featureName.indexOf('my')===0;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /* global Uint8Array */var saveAsImageLang=lang.toolbox.saveAsImage;function SaveAsImage(model){this.model=model;}SaveAsImage.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:saveAsImageLang.title,type:'png',// Default use option.backgroundColor\n// backgroundColor: '#fff',\nconnectedBackgroundColor:'#fff',name:'',excludeComponents:['toolbox'],pixelRatio:1,lang:saveAsImageLang.lang.slice()};SaveAsImage.prototype.unusable=!env$1.canvasSupported;var proto$2=SaveAsImage.prototype;proto$2.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')});// Chrome and Firefox\nif(typeof MouseEvent==='function'&&!env$1.browser.ie&&!env$1.browser.edge){var $a=document.createElement('a');$a.download=title+'.'+type;$a.target='_blank';$a.href=url;var evt=new MouseEvent('click',{// some micro front-end framework， window maybe is a Proxy\nview:document.defaultView,bubbles:true,cancelable:false});$a.dispatchEvent(evt);}// IE\nelse{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$$1=model.get('lang');var html=''+'<body style=\"margin:0;\">'+'<img src=\"'+url+'\" style=\"max-width:100%;\" title=\"'+(lang$$1&&lang$$1[0]||'')+'\" />'+'</body>';var tab=window.open();tab.document.write(html);}}};register$2('saveAsImage',SaveAsImage);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var magicTypeLang=lang.toolbox.magicType;var INNER_STACK_KEYWORD='__ec_magicType_stack__';function MagicType(model){this.model=model;}MagicType.defaultOption={show:true,type:[],// Icon group\nicon:{/* eslint-disable */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'// jshint ignore:line\n/* eslint-enable */},// `line`, `bar`, `stack`, `tiled`\ntitle:_clone(magicTypeLang.title),option:{},seriesIndex:{}};var proto$3=MagicType.prototype;proto$3.getIcons=function(){var model=this.model;var availableIcons=model.get('icon');var icons={};each$1(model.get('type'),function(type){if(availableIcons[type]){icons[type]=availableIcons[type];}});return icons;};var seriesOptGenreator={'line':function line(seriesType,seriesId,seriesModel,model){if(seriesType==='bar'){return merge({id:seriesId,type:'line',// Preserve data related option\ndata:seriesModel.get('data'),stack:seriesModel.get('stack'),markPoint:seriesModel.get('markPoint'),markLine:seriesModel.get('markLine')},model.get('option.line')||{},true);}},'bar':function bar(seriesType,seriesId,seriesModel,model){if(seriesType==='line'){return merge({id:seriesId,type:'bar',// Preserve data related option\ndata:seriesModel.get('data'),stack:seriesModel.get('stack'),markPoint:seriesModel.get('markPoint'),markLine:seriesModel.get('markLine')},model.get('option.bar')||{},true);}},'stack':function stack(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);}}};var radioTypes=[['line','bar'],['stack']];proto$3.onclick=function(ecModel,api,type){var model=this.model;var seriesIndex=model.get('seriesIndex.'+type);// Not supported magicType\nif(!seriesOptGenreator[type]){return;}var newOption={series:[]};var generateNewSeriesTypes=function generateNewSeriesTypes(seriesModel){var seriesType=seriesModel.subType;var seriesId=seriesModel.id;var newSeriesOpt=seriesOptGenreator[type](seriesType,seriesId,seriesModel,model);if(newSeriesOpt){// PENDING If merge original option?\ndefaults(newSeriesOpt,seriesModel.option);newOption.series.push(newSeriesOpt);}// Modify boundaryGap\nvar 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=ecModel.queryComponents({mainType:axisType,index:seriesModel.get(name+'Index'),id:seriesModel.get(name+'Id')})[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$1(radioTypes,function(radio){if(indexOf(radio,type)>=0){each$1(radio,function(item){model.setIconStatus(item,'normal');});}});model.setIconStatus(type,'emphasis');ecModel.eachComponent({mainType:'series',query:seriesIndex==null?null:{seriesIndex:seriesIndex}},generateNewSeriesTypes);var newTitle;// Change title of stack\nif(type==='stack'){var isStack=newOption.series&&newOption.series[0]&&newOption.series[0].stack===INNER_STACK_KEYWORD;newTitle=isStack?merge({stack:magicTypeLang.title.tiled},magicTypeLang.title):_clone(magicTypeLang.title);}api.dispatchAction({type:'changeMagicType',currentType:type,newOption:newOption,newTitle:newTitle,featureName:'magicType'});};registerAction({type:'changeMagicType',event:'magicTypeChanged',update:'prepareAndUpdate'},function(payload,ecModel){ecModel.mergeOption(payload.newOption);});register$2('magicType',MagicType);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var dataViewLang=lang.toolbox.dataView;var BLOCK_SPLITER=new Array(60).join('-');var ITEM_SPLITER='\\t';/**\n * Group series into two types\n *  1. on category axis, like line, bar\n *  2. others, like scatter, pie\n * @param {module:echarts/model/Global} ecModel\n * @return {Object}\n * @inner\n */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};}/**\n * Assemble content of series on cateogory axis\n * @param {Array.<module:echarts/model/Series>} series\n * @return {string}\n * @inner\n */function assembleSeriesWithCategoryAxis(series){var tables=[];each$1(series,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$1(group.series,function(series){var rawData=series.getRawData();columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim),function(val){return val;}));});// Assemble table content\nvar 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');}/**\n * Assemble content of other series\n * @param {Array.<module:echarts/model/Series>} series\n * @return {string}\n * @inner\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');}/**\n * @param {module:echarts/model/Global}\n * @return {Object}\n * @inner\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*$/,'');}/**\n * If a block is tsv format\n */function isTSVFormat(block){// Simple method to find out if a block is tsv format\nvar firstLine=block.slice(0,block.indexOf('\\n'));if(firstLine.indexOf(ITEM_SPLITER)>=0){return true;}}var itemSplitRegex=new RegExp('['+ITEM_SPLITER+']+','g');/**\n * @param {string} tsv\n * @return {Object}\n */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};}/**\n * @param {string} str\n * @return {Array.<Object>}\n * @inner\n */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++){// if line is empty, ignore it.\n// there is a case that a user forgot to delete `\\n`.\nvar line=trim$1(lines[i]);if(!line){continue;}var items=line.split(itemSplitRegex);var name='';var value;var hasName=false;if(isNaN(items[0])){// First item is name\nhasName=true;name=items[0];items=items.slice(1);data[i]={name:name,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};}/**\n * @param {string} str\n * @param {Array.<Object>} blockMetaList\n * @return {Object}\n * @inner\n */function parseContents(str,blockMetaList){var blocks=str.split(new RegExp('\\n*'+BLOCK_SPLITER+'\\n*','g'));var newOption={series:[]};each$1(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;}/**\n * @alias {module:echarts/component/toolbox/feature/DataView}\n * @constructor\n * @param {module:echarts/model/Model} model\n */function DataView(model){this._dom=null;this.model=model;}DataView.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:_clone(dataViewLang.title),lang:_clone(dataViewLang.lang),backgroundColor:'#fff',textColor:'#000',textareaColor:'#fff',textareaBorderColor:'#333',buttonColor:'#c23531',buttonTextColor:'#fff'};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';// Create elements\nvar header=document.createElement('h4');var lang$$1=model.get('lang')||[];header.innerHTML=lang$$1[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{// Use default textarea\nviewMain.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(){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[1];refreshButton.innerHTML=lang$$1[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);};/**\n * @inner\n */function tryMergeDataOption(newData,originalData){return map(newData,function(newVal,idx){var original=originalData&&originalData[idx];if(isObject$1(original)&&!isArray(original)){var newValIsObject=isObject$1(newVal)&&!isArray(newVal);if(!newValIsObject){newVal={value:newVal};}// original data has name but new data has no name\nvar shouldDeleteName=original.name!=null&&newVal.name==null;// Original data has option\nnewVal=defaults(newVal,original);shouldDeleteName&&delete newVal.name;return newVal;}else{return newVal;}});}register$2('dataView',DataView);registerAction({type:'changeDataView',event:'dataViewChanged',update:'prepareAndUpdate'},function(payload,ecModel){var newSeriesOptList=[];each$1(payload.newOption.series,function(seriesOpt){var seriesModel=ecModel.getSeriesByName(seriesOpt.name)[0];if(!seriesModel){// New created series\n// Geuss the series type\nnewSeriesOptList.push(extend({// Default is scatter\ntype:'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));});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var curry$5=curry;var each$16=each$1;var map$2=map;var mathMin$5=Math.min;var mathMax$5=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(0,0,0,0.3)',fill:'rgba(0,0,0,0.1)'},transformable:true,brushMode:'single',removeOnClick:false};var baseUID=0;/**\n * @alias module:echarts/component/helper/BrushController\n * @constructor\n * @mixin {module:zrender/mixin/Eventful}\n * @event module:echarts/component/helper/BrushController#brush\n *        params:\n *            areas: Array.<Array>, coord relates to container group,\n *                                    If no container specified, to global.\n *            opt {\n *                isEnd: boolean,\n *                removeOnClick: boolean\n *            }\n *\n * @param {module:zrender/zrender~ZRender} zr\n */function BrushController(zr){if(__DEV__){assert$1(zr);}Eventful.call(this);/**\n     * @type {module:zrender/zrender~ZRender}\n     * @private\n     */this._zr=zr;/**\n     * @type {module:zrender/container/Group}\n     * @readOnly\n     */this.group=new Group();/**\n     * Only for drawing (after enabledBrush).\n     *     'line', 'rect', 'polygon' or false\n     *     If passing false/null/undefined, disable brush.\n     *     If passing 'auto', determined by panel.defaultBrushType\n     * @private\n     * @type {string}\n     */this._brushType;/**\n     * Only for drawing (after enabledBrush).\n     *\n     * @private\n     * @type {Object}\n     */this._brushOption;/**\n     * @private\n     * @type {Object}\n     */this._panels;/**\n     * @private\n     * @type {Array.<nubmer>}\n     */this._track=[];/**\n     * @private\n     * @type {boolean}\n     */this._dragging;/**\n     * @private\n     * @type {Array}\n     */this._covers=[];/**\n     * @private\n     * @type {moudule:zrender/container/Group}\n     */this._creatingCover;/**\n     * `true` means global panel\n     * @private\n     * @type {module:zrender/container/Group|boolean}\n     */this._creatingPanel;/**\n     * @private\n     * @type {boolean}\n     */this._enableGlobalPan;/**\n     * @private\n     * @type {boolean}\n     */if(__DEV__){this._mounted;}/**\n     * @private\n     * @type {string}\n     */this._uid='brushController_'+baseUID++;/**\n     * @private\n     * @type {Object}\n     */this._handlers={};each$16(pointerHandlers,function(handler,eventName){this._handlers[eventName]=bind(handler,this);},this);}BrushController.prototype={constructor:BrushController,/**\n     * If set to null/undefined/false, select disabled.\n     * @param {Object} brushOption\n     * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false\n     *                          If passing false/null/undefined, disable brush.\n     *                          If passing 'auto', determined by panel.defaultBrushType.\n     *                              ('auto' can not be used in global panel)\n     * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple'\n     * @param {boolean} [brushOption.transformable=true]\n     * @param {boolean} [brushOption.removeOnClick=false]\n     * @param {Object} [brushOption.brushStyle]\n     * @param {number} [brushOption.brushStyle.width]\n     * @param {number} [brushOption.brushStyle.lineWidth]\n     * @param {string} [brushOption.brushStyle.stroke]\n     * @param {string} [brushOption.brushStyle.fill]\n     * @param {number} [brushOption.z]\n     */enableBrush:function enableBrush(brushOption){if(__DEV__){assert$1(this._mounted);}this._brushType&&doDisableBrush(this);brushOption.brushType&&doEnableBrush(this,brushOption);return this;},/**\n     * @param {Array.<Object>} panelOpts If not pass, it is global brush.\n     *        Each items: {\n     *            panelId, // mandatory.\n     *            clipPath, // mandatory. function.\n     *            isTargetByCursor, // mandatory. function.\n     *            defaultBrushType, // optional, only used when brushType is 'auto'.\n     *            getLinearBrushOtherExtent, // optional. function.\n     *        }\n     */setPanels:function setPanels(panelOpts){if(panelOpts&&panelOpts.length){var panels=this._panels={};each$1(panelOpts,function(panelOpts){panels[panelOpts.panelId]=_clone(panelOpts);});}else{this._panels=null;}return this;},/**\n     * @param {Object} [opt]\n     * @return {boolean} [opt.enableGlobalPan=false]\n     */mount:function mount(opt){opt=opt||{};if(__DEV__){this._mounted=true;// should be at first.\n}this._enableGlobalPan=opt.enableGlobalPan;var thisGroup=this.group;this._zr.add(thisGroup);thisGroup.attr({position:opt.position||[0,0],rotation:opt.rotation||0,scale:opt.scale||[1,1]});this._transform=thisGroup.getLocalTransform();return this;},eachCover:function eachCover(cb,context){each$16(this._covers,cb,context);},/**\n     * Update covers.\n     * @param {Array.<Object>} brushOptionList Like:\n     *        [\n     *            {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable},\n     *            {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]},\n     *            ...\n     *        ]\n     *        `brushType` is required in each cover info. (can not be 'auto')\n     *        `id` is not mandatory.\n     *        `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.\n     *        If brushOptionList is null/undefined, all covers removed.\n     */updateCovers:function updateCovers(brushOptionList){if(__DEV__){assert$1(this._mounted);}brushOptionList=map(brushOptionList,function(brushOption){return merge(_clone(DEFAULT_BRUSH_OPT),brushOption,true);});var tmpIdPrefix='\\0-brush-index-';var oldCovers=this._covers;var newCovers=this._covers=[];var controller=this;var creatingCover=this._creatingCover;new DataDiffer(oldCovers,brushOptionList,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 newBrushOption=brushOptionList[newIndex];// Consider setOption in event listener of brushSelect,\n// where updating cover when creating should be forbiden.\nif(oldIndex!=null&&oldCovers[oldIndex]===creatingCover){newCovers[newIndex]=oldCovers[oldIndex];}else{var cover=newCovers[newIndex]=oldIndex!=null?(oldCovers[oldIndex].__brushOption=newBrushOption,oldCovers[oldIndex]):endCreating(controller,createCover(controller,newBrushOption));updateCoverAfterCreation(controller,cover);}}function remove(oldIndex){if(oldCovers[oldIndex]!==creatingCover){controller.group.remove(oldCovers[oldIndex]);}}},unmount:function unmount(){if(__DEV__){if(!this._mounted){return;}}this.enableBrush(false);// container may 'removeAll' outside.\nclearCovers(this);this._zr.remove(this.group);if(__DEV__){this._mounted=false;// should be at last.\n}return this;},dispose:function dispose(){this.unmount();this.off();}};mixin(BrushController,Eventful);function doEnableBrush(controller,brushOption){var zr=controller._zr;// Consider roam, which takes globalPan too.\nif(!controller._enableGlobalPan){take(zr,MUTEX_RESOURCE_KEY,controller._uid);}mountHandlers(zr,controller._handlers);controller._brushType=brushOption.brushType;controller._brushOption=merge(_clone(DEFAULT_BRUSH_OPT),brushOption,true);}function doDisableBrush(controller){var zr=controller._zr;release(zr,MUTEX_RESOURCE_KEY,controller._uid);unmountHandlers(zr,controller._handlers);controller._brushType=controller._brushOption=null;}function mountHandlers(zr,handlers){each$16(handlers,function(handler,eventName){zr.on(eventName,handler);});}function unmountHandlers(zr,handlers){each$16(handlers,function(handler,eventName){zr.off(eventName,handler);});}function createCover(controller,brushOption){var cover=coverRenderers[brushOption.brushType].createCover(controller,brushOption);cover.__brushOption=brushOption;updateZ$1(cover,brushOption);controller.group.add(cover);return cover;}function endCreating(controller,creatingCover){var coverRenderer=getCoverRenderer(creatingCover);if(coverRenderer.endCreating){coverRenderer.endCreating(controller,creatingCover);updateZ$1(creatingCover,creatingCover.__brushOption);}return creatingCover;}function updateCoverShape(controller,cover){var brushOption=cover.__brushOption;getCoverRenderer(cover).updateCoverShape(controller,cover,brushOption.range,brushOption);}function updateZ$1(cover,brushOption){var z=brushOption.z;z==null&&(z=COVER_Z);cover.traverse(function(el){el.z=z;el.z2=z;// Consider in given container.\n});}function updateCoverAfterCreation(controller,cover){getCoverRenderer(cover).updateCommon(controller,cover);updateCoverShape(controller,cover);}function getCoverRenderer(cover){return coverRenderers[cover.__brushOption.brushType];}// return target panel or `true` (means global panel)\nfunction getPanelByPoint(controller,e,localCursorPoint){var panels=controller._panels;if(!panels){return true;// Global panel\n}var panel;var transform=controller._transform;each$16(panels,function(pn){pn.isTargetByCursor(e,localCursorPoint,transform)&&(panel=pn);});return panel;}// Return a panel or true\nfunction getPanelByCover(controller,cover){var panels=controller._panels;if(!panels){return true;// Global panel\n}var panelId=cover.__brushOption.panelId;// User may give cover without coord sys info,\n// which is then treated as global panel.\nreturn panelId!=null?panels[panelId]:true;}function clearCovers(controller){var covers=controller._covers;var originalLength=covers.length;each$16(covers,function(cover){controller.group.remove(cover);},controller);covers.length=0;return!!originalLength;}function trigger$1(controller,opt){var areas=map$2(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,{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(doDrift,controller,brushOption,edgeNames){var cover=new Group();cover.add(new Rect({name:'main',style:makeStyle(brushOption),silent:true,draggable:true,cursor:'move',drift:curry$5(doDrift,controller,cover,'nswe'),ondragend:curry$5(trigger$1,controller,{isEnd:true})}));each$16(edgeNames,function(name){cover.add(new Rect({name:name,style:{opacity:0},draggable:true,silent:true,invisible:true,drift:curry$5(doDrift,controller,cover,name),ondragend:curry$5(trigger$1,controller,{isEnd:true})}));});return cover;}function updateBaseRect(controller,cover,localRange,brushOption){var lineWidth=brushOption.brushStyle.lineWidth||0;var handleSize=mathMax$5(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$16(['w','e','n','s','se','sw','ne','nw'],function(name){var el=cover.childOfName(name);var globalDir=getGlobalDirection(controller,name);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$5(x,x2),mathMin$5(y,y2)];var max=[mathMax$5(x,x2),mathMax$5(y,y2)];return[[min[0],max[0]],// x range\n[min[1],max[1]]// y range\n];}function getTransform$1(controller){return getTransform(controller.group);}function getGlobalDirection(controller,localDirection){if(localDirection.length>1){localDirection=localDirection.split('');var globalDir=[getGlobalDirection(controller,localDirection[0]),getGlobalDirection(controller,localDirection[1])];(globalDir[0]==='e'||globalDir[0]==='w')&&globalDir.reverse();return globalDir.join('');}else{var map$$1={w:'left',e:'right',n:'top',s:'bottom'};var inverseMap={left:'w',right:'e',top:'n',bottom:'s'};var globalDir=transformDirection(map$$1[localDirection],getTransform$1(controller));return inverseMap[globalDir];}}function driftRect(toRectRange,fromRectRange,controller,cover,name,dx,dy,e){var brushOption=cover.__brushOption;var rectRange=toRectRange(brushOption.range);var localDelta=toLocalDelta(controller,dx,dy);each$16(name.split(''),function(namePart){var ind=DIRECTION_MAP[namePart];rectRange[ind[0]][ind[1]]+=localDelta[ind[0]];});brushOption.range=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,e){var range=cover.__brushOption.range;var localDelta=toLocalDelta(controller,dx,dy);each$16(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!==true?panel.clipPath(data,controller._transform):_clone(data);}function pointsToRect(points){var xmin=mathMin$5(points[0][0],points[1][0]);var ymin=mathMin$5(points[0][1],points[1][1]);var xmax=mathMax$5(points[0][0],points[1][0]);var ymax=mathMax$5(points[0][1],points[1][1]);return{x:xmin,y:ymin,width:xmax-xmin,height:ymax-ymin};}function resetCursor(controller,e,localCursorPoint){if(// Check active\n!controller._brushType// resetCursor should be always called when mouse is in zr area,\n// but not called when mouse is out of zr area to avoid bad influence\n// if `mousemove`, `mouseup` are triggered from `document` event.\n||isOutsideZrArea(controller,e)){return;}var zr=controller._zr;var covers=controller._covers;var currPanel=getPanelByPoint(controller,e,localCursorPoint);// Check whether in covers.\nif(!controller._dragging){for(var i=0;i<covers.length;i++){var brushOption=covers[i].__brushOption;if(currPanel&&(currPanel===true||brushOption.panelId===currPanel.panelId)&&coverRenderers[brushOption.brushType].contain(covers[i],localCursorPoint[0],localCursorPoint[1])){// Use cursor style set on cover.\nreturn;}}}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===true?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){// Help user to remove covers easily, only by a tiny drag, in 'single' mode.\n// But a single click do not clear covers, because user may have casual\n// clicks (for example, click on other component and do not expect covers\n// disappear).\n// Only some cover removed, trigger action, but not every click trigger action.\nif(getPanelByPoint(controller,e,localCursorPoint)&&clearCovers(controller)){eventParams={isEnd:isEnd,removeOnClick:true};}}return eventParams;}function determineBrushType(brushType,panel){if(brushType==='auto'){if(__DEV__){assert$1(panel&&panel.defaultBrushType,'MUST have defaultBrushType when brushType is \"atuo\"');}return panel.defaultBrushType;}return brushType;}var pointerHandlers={mousedown:function mousedown(e){if(this._dragging){// In case some browser do not support globalOut,\n// and release mose out side the browser.\nhandleDragEnd(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 mousemove(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 mouseup(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;// trigger event shoule be at final, after procedure will be nested.\neventParams&&trigger$1(controller,eventParams);}}function isOutsideZrArea(controller,x,y){var zr=controller._zr;return x<0||x>zr.getWidth()||y<0||y>zr.getHeight();}/**\n * key: brushType\n * @type {Object}\n */var coverRenderers={lineX:getLineRenderer(0),lineY:getLineRenderer(1),rect:{createCover:function createCover(controller,brushOption){return createBaseRectCover(curry$5(driftRect,function(range){return range;},function(range){return range;}),controller,brushOption,['w','e','n','s','se','sw','ne','nw']);},getCreatingRange:function getCreatingRange(localTrack){var ends=getTrackEnds(localTrack);return formatRectRange(ends[1][0],ends[1][1],ends[0][0],ends[0][1]);},updateCoverShape:function updateCoverShape(controller,cover,localRange,brushOption){updateBaseRect(controller,cover,localRange,brushOption);},updateCommon:updateCommon,contain:mainShapeContain},polygon:{createCover:function createCover(controller,brushOption){var cover=new Group();// Do not use graphic.Polygon because graphic.Polyline do not close the\n// border of the shape when drawing, which is a better experience for user.\ncover.add(new Polyline({name:'main',style:makeStyle(brushOption),silent:true}));return cover;},getCreatingRange:function getCreatingRange(localTrack){return localTrack;},endCreating:function endCreating(controller,cover){cover.remove(cover.childAt(0));// Use graphic.Polygon close the shape.\ncover.add(new Polygon({name:'main',draggable:true,drift:curry$5(driftPolygon,controller,cover),ondragend:curry$5(trigger$1,controller,{isEnd:true})}));},updateCoverShape:function updateCoverShape(controller,cover,localRange,brushOption){cover.childAt(0).setShape({points:clipByPanel(controller,cover,localRange)});},updateCommon:updateCommon,contain:mainShapeContain}};function getLineRenderer(xyIndex){return{createCover:function createCover(controller,brushOption){return createBaseRectCover(curry$5(driftRect,function(range){var rectRange=[range,[0,100]];xyIndex&&rectRange.reverse();return rectRange;},function(rectRange){return rectRange[xyIndex];}),controller,brushOption,[['w','e'],['n','s']][xyIndex]);},getCreatingRange:function getCreatingRange(localTrack){var ends=getTrackEnds(localTrack);var min=mathMin$5(ends[0][xyIndex],ends[1][xyIndex]);var max=mathMax$5(ends[0][xyIndex],ends[1][xyIndex]);return[min,max];},updateCoverShape:function updateCoverShape(controller,cover,localRange,brushOption){var otherExtent;// If brushWidth not specified, fit the panel.\nvar panel=getPanelByCover(controller,cover);if(panel!==true&&panel.getLinearBrushOtherExtent){otherExtent=panel.getLinearBrushOtherExtent(xyIndex,controller._transform);}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};}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var IRRELEVANT_EXCLUDES={'axisPointer':1,'tooltip':1,'brush':1};/**\n * Avoid that: mouse click on a elements that is over geo or graph,\n * but roam is triggered.\n */function onIrrelevantElement(e,api,targetCoordSysModel){var model=api.getComponentByElement(e.topTarget);// If model is axisModel, it works only if it is injected with coordinateSystem.\nvar coordSys=model&&model.coordinateSystem;return model&&model!==targetCoordSysModel&&!IRRELEVANT_EXCLUDES[model.mainType]&&coordSys&&coordSys.model!==targetCoordSysModel;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/function makeRectPanelClipPath(rect){rect=normalizeRect(rect);return function(localPoints,transform){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){rect=normalizeRect(rect);return function(e,localCursorPoint,transform){return rect.contain(localCursorPoint[0],localCursorPoint[1])&&!onIrrelevantElement(e,api,targetModel);};}// Consider width/height is negative.\nfunction normalizeRect(rect){return BoundingRect.create(rect);}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$17=each$1;var indexOf$2=indexOf;var curry$6=curry;var COORD_CONVERTS=['dataToPoint','pointToData'];// FIXME\n// how to genarialize to more coordinate systems.\nvar INCLUDE_FINDER_MAIN_TYPES=['grid','xAxis','yAxis','geo','graph','polar','radiusAxis','angleAxis','bmap'];/**\n * [option in constructor]:\n * {\n *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.\n * }\n *\n *\n * [targetInfo]:\n *\n * There can be multiple axes in a single targetInfo. Consider the case\n * of `grid` component, a targetInfo represents a grid which contains one or more\n * cartesian and one or more axes. And consider the case of parallel system,\n * which has multiple axes in a coordinate system.\n * Can be {\n *     panelId: ...,\n *     coordSys: <a representitive cartesian in grid (first cartesian by default)>,\n *     coordSyses: all cartesians.\n *     gridModel: <grid component>\n *     xAxes: correspond to coordSyses on index\n *     yAxes: correspond to coordSyses on index\n * }\n * or {\n *     panelId: ...,\n *     coordSys: <geo coord sys>\n *     coordSyses: [<geo coord sys>]\n *     geoModel: <geo component>\n * }\n *\n *\n * [panelOpt]:\n *\n * Make from targetInfo. Input to BrushController.\n * {\n *     panelId: ...,\n *     rect: ...\n * }\n *\n *\n * [area]:\n *\n * Generated by BrushController or user input.\n * {\n *     panelId: Used to locate coordInfo directly. If user inpput, no panelId.\n *     brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y').\n *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.\n *     range: pixel range.\n *     coordRange: representitive coord range (the first one of coordRanges).\n *     coordRanges: <Array> coord ranges, used in multiple cartesian in one grid.\n * }\n */ /**\n * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid\n *        Each can be {number|Array.<number>}. like: {xAxisIndex: [3, 4]}\n * @param {module:echarts/model/Global} ecModel\n * @param {Object} [opt]\n * @param {Array.<string>} [opt.include] include coordinate system types.\n */function BrushTargetManager(option,ecModel,opt){/**\n     * @private\n     * @type {Array.<Object>}\n     */var targetInfoList=this._targetInfoList=[];var info={};var foundCpts=parseFinder$1(ecModel,option);each$17(targetInfoBuilders,function(builder,type){if(!opt||!opt.include||indexOf$2(opt.include,type)>=0){builder(foundCpts,targetInfoList,info);}});}var proto$5=BrushTargetManager.prototype;proto$5.setOutputRanges=function(areas,ecModel){this.matchOutputRanges(areas,ecModel,function(area,coordRange,coordSys){(area.coordRanges||(area.coordRanges=[])).push(coordRange);// area.coordRange is the first of area.coordRanges\nif(!area.coordRange){area.coordRange=coordRange;// In 'category' axis, coord to pixel is not reversible, so we can not\n// rebuild range by coordRange accrately, which may bring trouble when\n// brushing only one item. So we use __rangeOffset to rebuilding range\n// by coordRange. And this it only used in brush component so it is no\n// need to be adapted to coordRanges.\nvar result=coordConvert[area.brushType](0,coordSys,coordRange);area.__rangeOffset={offset:diffProcessor[area.brushType](result.values,area.range,[1,1]),xyMinMax:result.xyMinMax};}});};proto$5.matchOutputRanges=function(areas,ecModel,cb){each$17(areas,function(area){var targetInfo=this.findTargetInfo(area,ecModel);if(targetInfo&&targetInfo!==true){each$1(targetInfo.coordSyses,function(coordSys){var result=coordConvert[area.brushType](1,coordSys,area.range);cb(area,result.values,coordSys,ecModel);});}},this);};proto$5.setInputRanges=function(areas,ecModel){each$17(areas,function(area){var targetInfo=this.findTargetInfo(area,ecModel);if(__DEV__){assert$1(!targetInfo||targetInfo===true||area.coordRange,'coordRange must be specified when coord index specified.');assert$1(!targetInfo||targetInfo!==true||area.range,'range must be specified in global brush.');}area.range=area.range||[];// convert coordRange to global range and set panelId.\nif(targetInfo&&targetInfo!==true){area.panelId=targetInfo.panelId;// (1) area.range shoule always be calculate from coordRange but does\n// not keep its original value, for the sake of the dataZoom scenario,\n// where area.coordRange remains unchanged but area.range may be changed.\n// (2) Only support converting one coordRange to pixel range in brush\n// component. So do not consider `coordRanges`.\n// (3) About __rangeOffset, see comment above.\nvar 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);};proto$5.makePanelOpts=function(api,getDefaultBrushType){return map(this._targetInfoList,function(targetInfo){var rect=targetInfo.getPanelRect();return{panelId:targetInfo.panelId,defaultBrushType:getDefaultBrushType&&getDefaultBrushType(targetInfo),clipPath:makeRectPanelClipPath(rect),isTargetByCursor:makeRectIsTargetByCursor(rect,api,targetInfo.coordSysModel),getLinearBrushOtherExtent:makeLinearBrushOtherExtent(rect)};});};proto$5.controlSeries=function(area,seriesModel,ecModel){// Check whether area is bound in coord, and series do not belong to that coord.\n// If do not do this check, some brush (like lineX) will controll all axes.\nvar targetInfo=this.findTargetInfo(area,ecModel);return targetInfo===true||targetInfo&&indexOf$2(targetInfo.coordSyses,seriesModel.coordinateSystem)>=0;};/**\n * If return Object, a coord found.\n * If reutrn true, global found.\n * Otherwise nothing found.\n *\n * @param {Object} area\n * @param {Array} targetInfoList\n * @return {Object|boolean}\n */proto$5.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 i=0;i<targetInfoMatchers.length;i++){if(targetInfoMatchers[i](foundCpts,targetInfo)){return targetInfo;}}}}return true;};function formatMinMax(minMax){minMax[0]>minMax[1]&&minMax.reverse();return minMax;}function parseFinder$1(ecModel,option){return parseFinder(ecModel,option,{includeMainTypes:INCLUDE_FINDER_MAIN_TYPES});}var targetInfoBuilders={grid:function grid(foundCpts,targetInfoList){var xAxisModels=foundCpts.xAxisModels;var yAxisModels=foundCpts.yAxisModels;var gridModels=foundCpts.gridModels;// Remove duplicated.\nvar gridModelMap=createHashMap();var xAxesHas={};var yAxesHas={};if(!xAxisModels&&!yAxisModels&&!gridModels){return;}each$17(xAxisModels,function(axisModel){var gridModel=axisModel.axis.grid.model;gridModelMap.set(gridModel.id,gridModel);xAxesHas[gridModel.id]=true;});each$17(yAxisModels,function(axisModel){var gridModel=axisModel.axis.grid.model;gridModelMap.set(gridModel.id,gridModel);yAxesHas[gridModel.id]=true;});each$17(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$17(grid.getCartesians(),function(cartesian,index){if(indexOf$2(xAxisModels,cartesian.getAxis('x').model)>=0||indexOf$2(yAxisModels,cartesian.getAxis('y').model)>=0){cartesians.push(cartesian);}});targetInfoList.push({panelId:'grid--'+gridModel.id,gridModel:gridModel,coordSysModel:gridModel,// Use the first one as the representitive coordSys.\ncoordSys:cartesians[0],coordSyses:cartesians,getPanelRect:panelRectBuilder.grid,xAxisDeclared:xAxesHas[gridModel.id],yAxisDeclared:yAxesHas[gridModel.id]});});},geo:function geo(foundCpts,targetInfoList){each$17(foundCpts.geoModels,function(geoModel){var coordSys=geoModel.coordinateSystem;targetInfoList.push({panelId:'geo--'+geoModel.id,geoModel:geoModel,coordSysModel:geoModel,coordSys:coordSys,coordSyses:[coordSys],getPanelRect:panelRectBuilder.geo});});}};var targetInfoMatchers=[// grid\nfunction(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;},// geo\nfunction(foundCpts,targetInfo){var geoModel=foundCpts.geoModel;return geoModel&&geoModel===targetInfo.geoModel;}];var panelRectBuilder={grid:function grid(){// grid is not Transformable.\nreturn this.coordSys.grid.getRect().clone();},geo:function geo(){var coordSys=this.coordSys;var rect=coordSys.getBoundingRect().clone();// geo roam and zoom transform\nrect.applyTransform(getTransform(coordSys));return rect;}};var coordConvert={lineX:curry$6(axisConvert,0),lineY:curry$6(axisConvert,1),rect:function rect(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 polygon(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(__DEV__){assert$1(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$6(axisDiffProcessor,0),lineY:curry$6(axisDiffProcessor,1),rect:function rect(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 polygon(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]];}// We have to process scale caused by dataZoom manually,\n// although it might be not accurate.\nfunction 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];}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var each$18=each$1;var ATTR$2='\\0_ec_hist_store';/**\n * @param {module:echarts/model/Global} ecModel\n * @param {Object} newSnapshot {dataZoomId, batch: [payloadInfo, ...]}\n */function push(ecModel,newSnapshot){var store=giveStore$1(ecModel);// If previous dataZoom can not be found,\n// complete an range with current range.\neach$18(newSnapshot,function(batchItem,dataZoomId){var i=store.length-1;for(;i>=0;i--){var snapshot=store[i];if(snapshot[dataZoomId]){break;}}if(i<0){// No origin range set, create one by current range.\nvar dataZoomModel=ecModel.queryComponents({mainType:'dataZoom',subType:'select',id:dataZoomId})[0];if(dataZoomModel){var percentRange=dataZoomModel.getPercentRange();store[0][dataZoomId]={dataZoomId:dataZoomId,start:percentRange[0],end:percentRange[1]};}}});store.push(newSnapshot);}/**\n * @param {module:echarts/model/Global} ecModel\n * @return {Object} snapshot\n */function pop(ecModel){var store=giveStore$1(ecModel);var head=store[store.length-1];store.length>1&&store.pop();// Find top for all dataZoom.\nvar snapshot={};each$18(head,function(batchItem,dataZoomId){for(var i=store.length-1;i>=0;i--){var batchItem=store[i][dataZoomId];if(batchItem){snapshot[dataZoomId]=batchItem;break;}}});return snapshot;}/**\n * @param {module:echarts/model/Global} ecModel\n */function clear$1(ecModel){ecModel[ATTR$2]=null;}/**\n * @param {module:echarts/model/Global} ecModel\n * @return {number} records. always >= 1.\n */function count(ecModel){return giveStore$1(ecModel).length;}/**\n * [{key: dataZoomId, value: {dataZoomId, range}}, ...]\n * History length of each dataZoom may be different.\n * this._history[0] is used to store origin range.\n * @type {Array.<Object>}\n */function giveStore$1(ecModel){var store=ecModel[ATTR$2];if(!store){store=ecModel[ATTR$2]=[{}];}return store;}/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/DataZoomModel.extend({type:'dataZoom.select'});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/DataZoomView.extend({type:'dataZoom.select'});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ /**\n * Only work for toolbox dataZoom. User\n * MUST NOT import this module directly.\n */ /*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/ // Use dataZoomSelect\nvar dataZoomLang=lang.toolbox.dataZoom;var each$15=each$1;// Spectial component id start with \\0ec\\0, see echarts/model/Global.js~hasInnerId\nvar DATA_ZOOM_ID_BASE='\\0_ec_\\0toolbox-dataZoom_';function DataZoom(model,ecModel,api){/**\n     * @private\n     * @type {module:echarts/component/helper/BrushController}\n     */(this._brushController=new BrushController(api.getZr())).on('brush',bind(this._onBrush,this)).mount();/**\n     * @private\n     * @type {boolean}\n     */this._isZoomActive;}DataZoom.defaultOption={show:true,filterMode:'filter',// Icon group\nicon:{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'},// `zoom`, `back`\ntitle:_clone(dataZoomLang.title),brushStyle:{borderWidth:0,color:'rgba(0,0,0,0.2)'}};var proto$4=DataZoom.prototype;proto$4.render=function(featureModel,ecModel,api,payload){this.model=featureModel;this.ecModel=ecModel;this.api=api;updateZoomBtnStatus(featureModel,ecModel,this,payload,api);updateBackBtnStatus(featureModel,ecModel);};proto$4.onclick=function(ecModel,api,type){handlers[type].call(this);};proto$4.remove=function(ecModel,api){this._brushController.unmount();};proto$4.dispose=function(ecModel,api){this._brushController.dispose();};/**\n * @private\n */var handlers={zoom:function zoom(){var nextActive=!this._isZoomActive;this.api.dispatchAction({type:'takeGlobalCursor',key:'dataZoomSelect',dataZoomSelectActive:nextActive});},back:function back(){this._dispatchZoomAction(pop(this.ecModel));}};/**\n * @private\n */proto$4._onBrush=function(areas,opt){if(!opt.isEnd||!areas.length){return;}var snapshot={};var ecModel=this.ecModel;this._brushController.updateCovers([]);// remove cover\nvar brushTargetManager=new BrushTargetManager(retrieveAxisSetting(this.model.option),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);// Restrict range.\nvar 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;}};/**\n * @private\n */proto$4._dispatchZoomAction=function(snapshot){var batch=[];// Convert from hash map to array.\neach$15(snapshot,function(batchItem,dataZoomId){batch.push(_clone(batchItem));});batch.length&&this.api.dispatchAction({type:'dataZoom',from:this.uid,batch:batch});};function retrieveAxisSetting(option){var setting={};// Compatible with previous setting: null => all axis, false => no axis.\neach$1(['xAxisIndex','yAxisIndex'],function(name){setting[name]=option[name];setting[name]==null&&(setting[name]='all');(setting[name]===false||setting[name]==='none')&&(setting[name]=[]);});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(retrieveAxisSetting(featureModel.option),ecModel,{include:['grid']});view._brushController.setPanels(brushTargetManager.makePanelOpts(api,function(targetInfo){return targetInfo.xAxisDeclared&&!targetInfo.yAxisDeclared?'lineX':!targetInfo.xAxisDeclared&&targetInfo.yAxisDeclared?'lineY':'rect';})).enableBrush(zoomActive?{brushType:'auto',brushStyle:featureModel.getModel('brushStyle').getItemStyle()}:false);}register$2('dataZoom',DataZoom);// Create special dataZoom option for select\n// FIXME consider the case of merge option, where axes options are not exists.\nregisterPreprocessor(function(option){if(!option){return;}var dataZoomOpts=option.dataZoom||(option.dataZoom=[]);if(!isArray(dataZoomOpts)){option.dataZoom=dataZoomOpts=[dataZoomOpts];}var toolboxOpt=option.toolbox;if(toolboxOpt){// Assume there is only one toolbox\nif(isArray(toolboxOpt)){toolboxOpt=toolboxOpt[0];}if(toolboxOpt&&toolboxOpt.feature){var dataZoomOpt=toolboxOpt.feature.dataZoom;// FIXME: If add dataZoom when setOption in merge mode,\n// no axis info to be added. See `test/dataZoom-extreme.html`\naddForAxis('xAxis',dataZoomOpt);addForAxis('yAxis',dataZoomOpt);}}function addForAxis(axisName,dataZoomOpt){if(!dataZoomOpt){return;}// Try not to modify model, because it is not merged yet.\nvar axisIndicesName=axisName+'Index';var givenAxisIndices=dataZoomOpt[axisIndicesName];if(givenAxisIndices!=null&&givenAxisIndices!=='all'&&!isArray(givenAxisIndices)){givenAxisIndices=givenAxisIndices===false||givenAxisIndices==='none'?[]:[givenAxisIndices];}forEachComponent(axisName,function(axisOpt,axisIndex){if(givenAxisIndices!=null&&givenAxisIndices!=='all'&&indexOf(givenAxisIndices,axisIndex)===-1){return;}var newOpt={type:'select',$fromToolbox:true,// Default to be filter\nfilterMode:dataZoomOpt.filterMode||'filter',// Id for merge mapping.\nid:DATA_ZOOM_ID_BASE+axisName+axisIndex};// FIXME\n// Only support one axis now.\nnewOpt[axisIndicesName]=axisIndex;dataZoomOpts.push(newOpt);});}function forEachComponent(mainType,cb){var opts=option[mainType];if(!isArray(opts)){opts=opts?[opts]:[];}each$15(opts,cb);}});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var restoreLang=lang.toolbox.restore;function Restore(model){this.model=model;}Restore.defaultOption={show:true,/* eslint-disable */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',/* eslint-enable */title:restoreLang.title};var proto$6=Restore.prototype;proto$6.onclick=function(ecModel,api,type){clear$1(ecModel);api.dispatchAction({type:'restore',from:this.uid});};register$2('restore',Restore);registerAction({type:'restore',event:'restore',update:'prepareAndUpdate'},function(payload,ecModel){ecModel.resetOption('recreate');});/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/var urn='urn:schemas-microsoft-com:vml';var win=typeof window==='undefined'?null:window;var vmlInited=false;var doc=win&&win.document;function createNode(tagName){return doCreateNode(tagName);}// Avoid assign to an exported variable, for transforming to cjs.\nvar doCreateNode;if(doc&&!env$1.canvasSupported){try{!doc.namespaces.zrvml&&doc.namespaces.add('zrvml',urn);doCreateNode=function doCreateNode(tagName){return doc.createElement('<zrvml:'+tagName+' class=\"zrvml\">');};}catch(e){doCreateNode=function doCreateNode(tagName){return doc.createElement('<'+tagName+' xmlns=\"'+urn+'\" class=\"zrvml\">');};}}// From raphael\nfunction initVML(){if(vmlInited||!doc){return;}vmlInited=true;var styleSheets=doc.styleSheets;if(styleSheets.length<31){doc.createStyleSheet().addRule('.zrvml','behavior:url(#default#VML)');}else{// http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx\nstyleSheets[0].addRule('.zrvml','behavior:url(#default#VML)');}}// http://www.w3.org/TR/NOTE-VML\n// TODO Use proxy like svg instead of overwrite brush methods\nvar CMD$3=PathProxy.CMD;var round$2=Math.round;var sqrt=Math.sqrt;var abs$1=Math.abs;var cos=Math.cos;var sin=Math.sin;var mathMax$6=Math.max;if(!env$1.canvasSupported){var comma=',';var imageTransformPrefix='progid:DXImageTransform.Microsoft';var Z=21600;var Z2=Z/2;var ZLEVEL_BASE=100000;var Z_BASE=1000;var initRootElStyle=function initRootElStyle(el){el.style.cssText='position:absolute;left:0;top:0;width:1px;height:1px;';el.coordsize=Z+','+Z;el.coordorigin='0,0';};var encodeHtmlAttribute=function encodeHtmlAttribute(s){return String(s).replace(/&/g,'&amp;').replace(/\"/g,'&quot;');};var rgb2Str=function rgb2Str(r,g,b){return'rgb('+[r,g,b].join(',')+')';};var append=function append(parent,child){if(child&&parent&&child.parentNode!==parent){parent.appendChild(child);}};var remove=function remove(parent,child){if(child&&parent&&child.parentNode===parent){parent.removeChild(child);}};var getZIndex=function getZIndex(zlevel,z,z2){// z 的取值范围为 [0, 1000]\nreturn(parseFloat(zlevel)||0)*ZLEVEL_BASE+(parseFloat(z)||0)*Z_BASE+z2;};var parsePercent$3=parsePercent;/***************************************************\n     * PATH\n     **************************************************/var setColorAndOpacity=function setColorAndOpacity(el,color,opacity){var colorArr=parse(color);opacity=+opacity;if(isNaN(opacity)){opacity=1;}if(colorArr){el.color=rgb2Str(colorArr[0],colorArr[1],colorArr[2]);el.opacity=opacity*colorArr[3];}};var getColorAndAlpha=function getColorAndAlpha(color){var colorArr=parse(color);return[rgb2Str(colorArr[0],colorArr[1],colorArr[2]),colorArr[3]];};var updateFillNode=function updateFillNode(el,style,zrEl){// TODO pattern\nvar fill=style.fill;if(fill!=null){// Modified from excanvas\nif(fill instanceof Gradient){var gradientType;var angle=0;var focus=[0,0];// additional offset\nvar shift=0;// scale factor for offset\nvar expansion=1;var rect=zrEl.getBoundingRect();var rectWidth=rect.width;var rectHeight=rect.height;if(fill.type==='linear'){gradientType='gradient';var transform=zrEl.transform;var p0=[fill.x*rectWidth,fill.y*rectHeight];var p1=[fill.x2*rectWidth,fill.y2*rectHeight];if(transform){applyTransform(p0,p0,transform);applyTransform(p1,p1,transform);}var dx=p1[0]-p0[0];var dy=p1[1]-p0[1];angle=Math.atan2(dx,dy)*180/Math.PI;// The angle should be a non-negative number.\nif(angle<0){angle+=360;}// Very small angles produce an unexpected result because they are\n// converted to a scientific notation string.\nif(angle<1e-6){angle=0;}}else{gradientType='gradientradial';var p0=[fill.x*rectWidth,fill.y*rectHeight];var transform=zrEl.transform;var scale$$1=zrEl.scale;var width=rectWidth;var height=rectHeight;focus=[// Percent in bounding rect\n(p0[0]-rect.x)/width,(p0[1]-rect.y)/height];if(transform){applyTransform(p0,p0,transform);}width/=scale$$1[0]*Z;height/=scale$$1[1]*Z;var dimension=mathMax$6(width,height);shift=2*0/dimension;expansion=2*fill.r/dimension-shift;}// We need to sort the color stops in ascending order by offset,\n// otherwise IE won't interpret it correctly.\nvar stops=fill.colorStops.slice();stops.sort(function(cs1,cs2){return cs1.offset-cs2.offset;});var length$$1=stops.length;// Color and alpha list of first and last stop\nvar colorAndAlphaList=[];var colors=[];for(var i=0;i<length$$1;i++){var stop=stops[i];var colorAndAlpha=getColorAndAlpha(stop.color);colors.push(stop.offset*expansion+shift+' '+colorAndAlpha[0]);if(i===0||i===length$$1-1){colorAndAlphaList.push(colorAndAlpha);}}if(length$$1>=2){var color1=colorAndAlphaList[0][0];var color2=colorAndAlphaList[1][0];var opacity1=colorAndAlphaList[0][1]*style.opacity;var opacity2=colorAndAlphaList[1][1]*style.opacity;el.type=gradientType;el.method='none';el.focus='100%';el.angle=angle;el.color=color1;el.color2=color2;el.colors=colors.join(',');// When colors attribute is used, the meanings of opacity and o:opacity2\n// are reversed.\nel.opacity=opacity2;// FIXME g_o_:opacity ?\nel.opacity2=opacity1;}if(gradientType==='radial'){el.focusposition=focus.join(',');}}else{// FIXME Change from Gradient fill to color fill\nsetColorAndOpacity(el,fill,style.opacity);}}};var updateStrokeNode=function updateStrokeNode(el,style){// if (style.lineJoin != null) {\n//     el.joinstyle = style.lineJoin;\n// }\n// if (style.miterLimit != null) {\n//     el.miterlimit = style.miterLimit * Z;\n// }\n// if (style.lineCap != null) {\n//     el.endcap = style.lineCap;\n// }\nif(style.lineDash){el.dashstyle=style.lineDash.join(' ');}if(style.stroke!=null&&!(style.stroke instanceof Gradient)){setColorAndOpacity(el,style.stroke,style.opacity);}};var updateFillAndStroke=function updateFillAndStroke(vmlEl,type,style,zrEl){var isFill=type==='fill';var el=vmlEl.getElementsByTagName(type)[0];// Stroke must have lineWidth\nif(style[type]!=null&&style[type]!=='none'&&(isFill||!isFill&&style.lineWidth)){vmlEl[isFill?'filled':'stroked']='true';// FIXME Remove before updating, or set `colors` will throw error\nif(style[type]instanceof Gradient){remove(vmlEl,el);}if(!el){el=createNode(type);}isFill?updateFillNode(el,style,zrEl):updateStrokeNode(el,style);append(vmlEl,el);}else{vmlEl[isFill?'filled':'stroked']='false';remove(vmlEl,el);}};var points$1=[[],[],[]];var pathDataToString=function pathDataToString(path,m){var M=CMD$3.M;var C=CMD$3.C;var L=CMD$3.L;var A=CMD$3.A;var Q=CMD$3.Q;var str=[];var nPoint;var cmdStr;var cmd;var i;var xi;var yi;var data=path.data;var dataLength=path.len();for(i=0;i<dataLength;){cmd=data[i++];cmdStr='';nPoint=0;switch(cmd){case M:cmdStr=' m ';nPoint=1;xi=data[i++];yi=data[i++];points$1[0][0]=xi;points$1[0][1]=yi;break;case L:cmdStr=' l ';nPoint=1;xi=data[i++];yi=data[i++];points$1[0][0]=xi;points$1[0][1]=yi;break;case Q:case C:cmdStr=' c ';nPoint=3;var x1=data[i++];var y1=data[i++];var x2=data[i++];var y2=data[i++];var x3;var y3;if(cmd===Q){// Convert quadratic to cubic using degree elevation\nx3=x2;y3=y2;x2=(x2+2*x1)/3;y2=(y2+2*y1)/3;x1=(xi+2*x1)/3;y1=(yi+2*y1)/3;}else{x3=data[i++];y3=data[i++];}points$1[0][0]=x1;points$1[0][1]=y1;points$1[1][0]=x2;points$1[1][1]=y2;points$1[2][0]=x3;points$1[2][1]=y3;xi=x3;yi=y3;break;case A:var x=0;var y=0;var sx=1;var sy=1;var angle=0;if(m){// Extract SRT from matrix\nx=m[4];y=m[5];sx=sqrt(m[0]*m[0]+m[1]*m[1]);sy=sqrt(m[2]*m[2]+m[3]*m[3]);angle=Math.atan2(-m[1]/sy,m[0]/sx);}var cx=data[i++];var cy=data[i++];var rx=data[i++];var ry=data[i++];var startAngle=data[i++]+angle;var endAngle=data[i++]+startAngle+angle;// FIXME\n// var psi = data[i++];\ni++;var clockwise=data[i++];var x0=cx+cos(startAngle)*rx;var y0=cy+sin(startAngle)*ry;var x1=cx+cos(endAngle)*rx;var y1=cy+sin(endAngle)*ry;var type=clockwise?' wa ':' at ';if(Math.abs(x0-x1)<1e-4){// IE won't render arches drawn counter clockwise if x0 == x1.\nif(Math.abs(endAngle-startAngle)>1e-2){// Offset x0 by 1/80 of a pixel. Use something\n// that can be represented in binary\nif(clockwise){x0+=270/Z;}}else{// Avoid case draw full circle\nif(Math.abs(y0-cy)<1e-4){if(clockwise&&x0<cx||!clockwise&&x0>cx){y1-=270/Z;}else{y1+=270/Z;}}else if(clockwise&&y0<cy||!clockwise&&y0>cy){x1+=270/Z;}else{x1-=270/Z;}}}str.push(type,round$2(((cx-rx)*sx+x)*Z-Z2),comma,round$2(((cy-ry)*sy+y)*Z-Z2),comma,round$2(((cx+rx)*sx+x)*Z-Z2),comma,round$2(((cy+ry)*sy+y)*Z-Z2),comma,round$2((x0*sx+x)*Z-Z2),comma,round$2((y0*sy+y)*Z-Z2),comma,round$2((x1*sx+x)*Z-Z2),comma,round$2((y1*sy+y)*Z-Z2));xi=x1;yi=y1;break;case CMD$3.R:var p0=points$1[0];var p1=points$1[1];// x0, y0\np0[0]=data[i++];p0[1]=data[i++];// x1, y1\np1[0]=p0[0]+data[i++];p1[1]=p0[1]+data[i++];if(m){applyTransform(p0,p0,m);applyTransform(p1,p1,m);}p0[0]=round$2(p0[0]*Z-Z2);p1[0]=round$2(p1[0]*Z-Z2);p0[1]=round$2(p0[1]*Z-Z2);p1[1]=round$2(p1[1]*Z-Z2);str.push(// x0, y0\n' m ',p0[0],comma,p0[1],// x1, y0\n' l ',p1[0],comma,p0[1],// x1, y1\n' l ',p1[0],comma,p1[1],// x0, y1\n' l ',p0[0],comma,p1[1]);break;case CMD$3.Z:// FIXME Update xi, yi\nstr.push(' x ');}if(nPoint>0){str.push(cmdStr);for(var k=0;k<nPoint;k++){var p=points$1[k];m&&applyTransform(p,p,m);// 不 round 会非常慢\nstr.push(round$2(p[0]*Z-Z2),comma,round$2(p[1]*Z-Z2),k<nPoint-1?comma:'');}}}return str.join('');};// Rewrite the original path method\nPath.prototype.brushVML=function(vmlRoot){var style=this.style;var vmlEl=this._vmlEl;if(!vmlEl){vmlEl=createNode('shape');initRootElStyle(vmlEl);this._vmlEl=vmlEl;}updateFillAndStroke(vmlEl,'fill',style,this);updateFillAndStroke(vmlEl,'stroke',style,this);var m=this.transform;var needTransform=m!=null;var strokeEl=vmlEl.getElementsByTagName('stroke')[0];if(strokeEl){var lineWidth=style.lineWidth;// Get the line scale.\n// Determinant of this.m_ means how much the area is enlarged by the\n// transformation. So its square root can be used as a scale factor\n// for width.\nif(needTransform&&!style.strokeNoScale){var det=m[0]*m[3]-m[1]*m[2];lineWidth*=sqrt(abs$1(det));}strokeEl.weight=lineWidth+'px';}var path=this.path||(this.path=new PathProxy());if(this.__dirtyPath){path.beginPath();path.subPixelOptimize=false;this.buildPath(path,this.shape);path.toStatic();this.__dirtyPath=false;}vmlEl.path=pathDataToString(path,this.transform);vmlEl.style.zIndex=getZIndex(this.zlevel,this.z,this.z2);// Append to root\nappend(vmlRoot,vmlEl);// Text\nif(style.text!=null){this.drawRectText(vmlRoot,this.getBoundingRect());}else{this.removeRectText(vmlRoot);}};Path.prototype.onRemove=function(vmlRoot){remove(vmlRoot,this._vmlEl);this.removeRectText(vmlRoot);};Path.prototype.onAdd=function(vmlRoot){append(vmlRoot,this._vmlEl);this.appendRectText(vmlRoot);};/***************************************************\n     * IMAGE\n     **************************************************/var isImage=function isImage(img){// FIXME img instanceof Image 如果 img 是一个字符串的时候，IE8 下会报错\nreturn _typeof(img)==='object'&&img.tagName&&img.tagName.toUpperCase()==='IMG';// return img instanceof Image;\n};// Rewrite the original path method\nZImage.prototype.brushVML=function(vmlRoot){var style=this.style;var image=style.image;// Image original width, height\nvar ow;var oh;if(isImage(image)){var src=image.src;if(src===this._imageSrc){ow=this._imageWidth;oh=this._imageHeight;}else{var imageRuntimeStyle=image.runtimeStyle;var oldRuntimeWidth=imageRuntimeStyle.width;var oldRuntimeHeight=imageRuntimeStyle.height;imageRuntimeStyle.width='auto';imageRuntimeStyle.height='auto';// get the original size\now=image.width;oh=image.height;// and remove overides\nimageRuntimeStyle.width=oldRuntimeWidth;imageRuntimeStyle.height=oldRuntimeHeight;// Caching image original width, height and src\nthis._imageSrc=src;this._imageWidth=ow;this._imageHeight=oh;}image=src;}else{if(image===this._imageSrc){ow=this._imageWidth;oh=this._imageHeight;}}if(!image){return;}var x=style.x||0;var y=style.y||0;var dw=style.width;var dh=style.height;var sw=style.sWidth;var sh=style.sHeight;var sx=style.sx||0;var sy=style.sy||0;var hasCrop=sw&&sh;var vmlEl=this._vmlEl;if(!vmlEl){// FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。\n// vmlEl = vmlCore.createNode('group');\nvmlEl=doc.createElement('div');initRootElStyle(vmlEl);this._vmlEl=vmlEl;}var vmlElStyle=vmlEl.style;var hasRotation=false;var m;var scaleX=1;var scaleY=1;if(this.transform){m=this.transform;scaleX=sqrt(m[0]*m[0]+m[1]*m[1]);scaleY=sqrt(m[2]*m[2]+m[3]*m[3]);hasRotation=m[1]||m[2];}if(hasRotation){// If filters are necessary (rotation exists), create them\n// filters are bog-slow, so only create them if abbsolutely necessary\n// The following check doesn't account for skews (which don't exist\n// in the canvas spec (yet) anyway.\n// From excanvas\nvar p0=[x,y];var p1=[x+dw,y];var p2=[x,y+dh];var p3=[x+dw,y+dh];applyTransform(p0,p0,m);applyTransform(p1,p1,m);applyTransform(p2,p2,m);applyTransform(p3,p3,m);var maxX=mathMax$6(p0[0],p1[0],p2[0],p3[0]);var maxY=mathMax$6(p0[1],p1[1],p2[1],p3[1]);var transformFilter=[];transformFilter.push('M11=',m[0]/scaleX,comma,'M12=',m[2]/scaleY,comma,'M21=',m[1]/scaleX,comma,'M22=',m[3]/scaleY,comma,'Dx=',round$2(x*scaleX+m[4]),comma,'Dy=',round$2(y*scaleY+m[5]));vmlElStyle.padding='0 '+round$2(maxX)+'px '+round$2(maxY)+'px 0';// FIXME DXImageTransform 在 IE11 的兼容模式下不起作用\nvmlElStyle.filter=imageTransformPrefix+'.Matrix('+transformFilter.join('')+', SizingMethod=clip)';}else{if(m){x=x*scaleX+m[4];y=y*scaleY+m[5];}vmlElStyle.filter='';vmlElStyle.left=round$2(x)+'px';vmlElStyle.top=round$2(y)+'px';}var imageEl=this._imageEl;var cropEl=this._cropEl;if(!imageEl){imageEl=doc.createElement('div');this._imageEl=imageEl;}var imageELStyle=imageEl.style;if(hasCrop){// Needs know image original width and height\nif(!(ow&&oh)){var tmpImage=new Image();var self=this;tmpImage.onload=function(){tmpImage.onload=null;ow=tmpImage.width;oh=tmpImage.height;// Adjust image width and height to fit the ratio destinationSize / sourceSize\nimageELStyle.width=round$2(scaleX*ow*dw/sw)+'px';imageELStyle.height=round$2(scaleY*oh*dh/sh)+'px';// Caching image original width, height and src\nself._imageWidth=ow;self._imageHeight=oh;self._imageSrc=image;};tmpImage.src=image;}else{imageELStyle.width=round$2(scaleX*ow*dw/sw)+'px';imageELStyle.height=round$2(scaleY*oh*dh/sh)+'px';}if(!cropEl){cropEl=doc.createElement('div');cropEl.style.overflow='hidden';this._cropEl=cropEl;}var cropElStyle=cropEl.style;cropElStyle.width=round$2((dw+sx*dw/sw)*scaleX);cropElStyle.height=round$2((dh+sy*dh/sh)*scaleY);cropElStyle.filter=imageTransformPrefix+'.Matrix(Dx='+-sx*dw/sw*scaleX+',Dy='+-sy*dh/sh*scaleY+')';if(!cropEl.parentNode){vmlEl.appendChild(cropEl);}if(imageEl.parentNode!==cropEl){cropEl.appendChild(imageEl);}}else{imageELStyle.width=round$2(scaleX*dw)+'px';imageELStyle.height=round$2(scaleY*dh)+'px';vmlEl.appendChild(imageEl);if(cropEl&&cropEl.parentNode){vmlEl.removeChild(cropEl);this._cropEl=null;}}var filterStr='';var alpha=style.opacity;if(alpha<1){filterStr+='.Alpha(opacity='+round$2(alpha*100)+') ';}filterStr+=imageTransformPrefix+'.AlphaImageLoader(src='+image+', SizingMethod=scale)';imageELStyle.filter=filterStr;vmlEl.style.zIndex=getZIndex(this.zlevel,this.z,this.z2);// Append to root\nappend(vmlRoot,vmlEl);// Text\nif(style.text!=null){this.drawRectText(vmlRoot,this.getBoundingRect());}};ZImage.prototype.onRemove=function(vmlRoot){remove(vmlRoot,this._vmlEl);this._vmlEl=null;this._cropEl=null;this._imageEl=null;this.removeRectText(vmlRoot);};ZImage.prototype.onAdd=function(vmlRoot){append(vmlRoot,this._vmlEl);this.appendRectText(vmlRoot);};/***************************************************\n     * TEXT\n     **************************************************/var DEFAULT_STYLE_NORMAL='normal';var fontStyleCache={};var fontStyleCacheCount=0;var MAX_FONT_CACHE_SIZE=100;var fontEl=document.createElement('div');var getFontStyle=function getFontStyle(fontString){var fontStyle=fontStyleCache[fontString];if(!fontStyle){// Clear cache\nif(fontStyleCacheCount>MAX_FONT_CACHE_SIZE){fontStyleCacheCount=0;fontStyleCache={};}var style=fontEl.style;var fontFamily;try{style.font=fontString;fontFamily=style.fontFamily.split(',')[0];}catch(e){}fontStyle={style:style.fontStyle||DEFAULT_STYLE_NORMAL,variant:style.fontVariant||DEFAULT_STYLE_NORMAL,weight:style.fontWeight||DEFAULT_STYLE_NORMAL,size:parseFloat(style.fontSize||12)|0,family:fontFamily||'Microsoft YaHei'};fontStyleCache[fontString]=fontStyle;fontStyleCacheCount++;}return fontStyle;};var textMeasureEl;// Overwrite measure text method\n$override$1('measureText',function(text,textFont){var doc$$1=doc;if(!textMeasureEl){textMeasureEl=doc$$1.createElement('div');textMeasureEl.style.cssText='position:absolute;top:-20000px;left:0;'+'padding:0;margin:0;border:none;white-space:pre;';doc.body.appendChild(textMeasureEl);}try{textMeasureEl.style.font=textFont;}catch(ex){// Ignore failures to set to invalid font.\n}textMeasureEl.innerHTML='';// Don't use innerHTML or innerText because they allow markup/whitespace.\ntextMeasureEl.appendChild(doc$$1.createTextNode(text));return{width:textMeasureEl.offsetWidth};});var tmpRect$2=new BoundingRect();var drawRectText=function drawRectText(vmlRoot,rect,textRect,fromTextEl){var style=this.style;// Optimize, avoid normalize every time.\nthis.__dirty&&normalizeTextStyle(style,true);var text=style.text;// Convert to string\ntext!=null&&(text+='');if(!text){return;}// Convert rich text to plain text. Rich text is not supported in\n// IE8-, but tags in rich text template will be removed.\nif(style.rich){var contentBlock=parseRichText(text,style);text=[];for(var i=0;i<contentBlock.lines.length;i++){var tokens=contentBlock.lines[i].tokens;var textLine=[];for(var j=0;j<tokens.length;j++){textLine.push(tokens[j].text);}text.push(textLine.join(''));}text=text.join('\\n');}var x;var y;var align=style.textAlign;var verticalAlign=style.textVerticalAlign;var fontStyle=getFontStyle(style.font);// FIXME encodeHtmlAttribute ?\nvar font=fontStyle.style+' '+fontStyle.variant+' '+fontStyle.weight+' '+fontStyle.size+'px \"'+fontStyle.family+'\"';textRect=textRect||_getBoundingRect(text,font,align,verticalAlign,style.textPadding,style.textLineHeight);// Transform rect to view space\nvar m=this.transform;// Ignore transform for text in other element\nif(m&&!fromTextEl){tmpRect$2.copy(rect);tmpRect$2.applyTransform(m);rect=tmpRect$2;}if(!fromTextEl){var textPosition=style.textPosition;// Text position represented by coord\nif(textPosition instanceof Array){x=rect.x+parsePercent$3(textPosition[0],rect.width);y=rect.y+parsePercent$3(textPosition[1],rect.height);align=align||'left';}else{var res=this.calculateTextPosition?this.calculateTextPosition({},style,rect):_calculateTextPosition({},style,rect);x=res.x;y=res.y;// Default align and baseline when has textPosition\nalign=align||res.textAlign;verticalAlign=verticalAlign||res.textVerticalAlign;}}else{x=rect.x;y=rect.y;}x=adjustTextX(x,textRect.width,align);y=adjustTextY(y,textRect.height,verticalAlign);// Force baseline 'middle'\ny+=textRect.height/2;// var fontSize = fontStyle.size;\n// 1.75 is an arbitrary number, as there is no info about the text baseline\n// switch (baseline) {\n// case 'hanging':\n// case 'top':\n//     y += fontSize / 1.75;\n//     break;\n//     case 'middle':\n//         break;\n//     default:\n//     // case null:\n//     // case 'alphabetic':\n//     // case 'ideographic':\n//     // case 'bottom':\n//         y -= fontSize / 2.25;\n//         break;\n// }\n// switch (align) {\n//     case 'left':\n//         break;\n//     case 'center':\n//         x -= textRect.width / 2;\n//         break;\n//     case 'right':\n//         x -= textRect.width;\n//         break;\n// case 'end':\n// align = elementStyle.direction == 'ltr' ? 'right' : 'left';\n// break;\n// case 'start':\n// align = elementStyle.direction == 'rtl' ? 'right' : 'left';\n// break;\n// default:\n//     align = 'left';\n// }\nvar createNode$$1=createNode;var textVmlEl=this._textVmlEl;var pathEl;var textPathEl;var skewEl;if(!textVmlEl){textVmlEl=createNode$$1('line');pathEl=createNode$$1('path');textPathEl=createNode$$1('textpath');skewEl=createNode$$1('skew');// FIXME Why here is not cammel case\n// Align 'center' seems wrong\ntextPathEl.style['v-text-align']='left';initRootElStyle(textVmlEl);pathEl.textpathok=true;textPathEl.on=true;textVmlEl.from='0 0';textVmlEl.to='1000 0.05';append(textVmlEl,skewEl);append(textVmlEl,pathEl);append(textVmlEl,textPathEl);this._textVmlEl=textVmlEl;}else{// 这里是在前面 appendChild 保证顺序的前提下\nskewEl=textVmlEl.firstChild;pathEl=skewEl.nextSibling;textPathEl=pathEl.nextSibling;}var coords=[x,y];var textVmlElStyle=textVmlEl.style;// Ignore transform for text in other element\nif(m&&fromTextEl){applyTransform(coords,coords,m);skewEl.on=true;skewEl.matrix=m[0].toFixed(3)+comma+m[2].toFixed(3)+comma+m[1].toFixed(3)+comma+m[3].toFixed(3)+',0,0';// Text position\nskewEl.offset=(round$2(coords[0])||0)+','+(round$2(coords[1])||0);// Left top point as origin\nskewEl.origin='0 0';textVmlElStyle.left='0px';textVmlElStyle.top='0px';}else{skewEl.on=false;textVmlElStyle.left=round$2(x)+'px';textVmlElStyle.top=round$2(y)+'px';}textPathEl.string=encodeHtmlAttribute(text);// TODO\ntry{textPathEl.style.font=font;}// Error font format\ncatch(e){}updateFillAndStroke(textVmlEl,'fill',{fill:style.textFill,opacity:style.opacity},this);updateFillAndStroke(textVmlEl,'stroke',{stroke:style.textStroke,opacity:style.opacity,lineDash:style.lineDash||null// style.lineDash can be `false`.\n},this);textVmlEl.style.zIndex=getZIndex(this.zlevel,this.z,this.z2);// Attached to root\nappend(vmlRoot,textVmlEl);};var removeRectText=function removeRectText(vmlRoot){remove(vmlRoot,this._textVmlEl);this._textVmlEl=null;};var appendRectText=function appendRectText(vmlRoot){append(vmlRoot,this._textVmlEl);};var list=[RectText,Displayable,ZImage,Path,Text];// In case Displayable has been mixed in RectText\nfor(var i$1=0;i$1<list.length;i$1++){var proto$7=list[i$1].prototype;proto$7.drawRectText=drawRectText;proto$7.removeRectText=removeRectText;proto$7.appendRectText=appendRectText;}Text.prototype.brushVML=function(vmlRoot){var style=this.style;if(style.text!=null){this.drawRectText(vmlRoot,{x:style.x||0,y:style.y||0,width:0,height:0},this.getBoundingRect(),true);}else{this.removeRectText(vmlRoot);}};Text.prototype.onRemove=function(vmlRoot){this.removeRectText(vmlRoot);};Text.prototype.onAdd=function(vmlRoot){this.appendRectText(vmlRoot);};}/**\n * VML Painter.\n *\n * @module zrender/vml/Painter\n */function parseInt10$1(val){return parseInt(val,10);}/**\n * @alias module:zrender/vml/Painter\n */function VMLPainter(root,storage){initVML();this.root=root;this.storage=storage;var vmlViewport=document.createElement('div');var vmlRoot=document.createElement('div');vmlViewport.style.cssText='display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;';vmlRoot.style.cssText='position:absolute;left:0;top:0;';root.appendChild(vmlViewport);this._vmlRoot=vmlRoot;this._vmlViewport=vmlViewport;this.resize();// Modify storage\nvar oldDelFromStorage=storage.delFromStorage;var oldAddToStorage=storage.addToStorage;storage.delFromStorage=function(el){oldDelFromStorage.call(storage,el);if(el){el.onRemove&&el.onRemove(vmlRoot);}};storage.addToStorage=function(el){// Displayable already has a vml node\nel.onAdd&&el.onAdd(vmlRoot);oldAddToStorage.call(storage,el);};this._firstPaint=true;}VMLPainter.prototype={constructor:VMLPainter,getType:function getType(){return'vml';},/**\n     * @return {HTMLDivElement}\n     */getViewportRoot:function getViewportRoot(){return this._vmlViewport;},getViewportRootOffset:function getViewportRootOffset(){var viewportRoot=this.getViewportRoot();if(viewportRoot){return{offsetLeft:viewportRoot.offsetLeft||0,offsetTop:viewportRoot.offsetTop||0};}},/**\n     * 刷新\n     */refresh:function refresh(){var list=this.storage.getDisplayList(true,true);this._paintList(list);},_paintList:function _paintList(list){var vmlRoot=this._vmlRoot;for(var i=0;i<list.length;i++){var el=list[i];if(el.invisible||el.ignore){if(!el.__alreadyNotVisible){el.onRemove(vmlRoot);}// Set as already invisible\nel.__alreadyNotVisible=true;}else{if(el.__alreadyNotVisible){el.onAdd(vmlRoot);}el.__alreadyNotVisible=false;if(el.__dirty){el.beforeBrush&&el.beforeBrush();(el.brushVML||el.brush).call(el,vmlRoot);el.afterBrush&&el.afterBrush();}}el.__dirty=false;}if(this._firstPaint){// Detached from document at first time\n// to avoid page refreshing too many times\n// FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变\nthis._vmlViewport.appendChild(vmlRoot);this._firstPaint=false;}},resize:function resize(width,height){var width=width==null?this._getWidth():width;var height=height==null?this._getHeight():height;if(this._width!==width||this._height!==height){this._width=width;this._height=height;var vmlViewportStyle=this._vmlViewport.style;vmlViewportStyle.width=width+'px';vmlViewportStyle.height=height+'px';}},dispose:function dispose(){this.root.innerHTML='';this._vmlRoot=this._vmlViewport=this.storage=null;},getWidth:function getWidth(){return this._width;},getHeight:function getHeight(){return this._height;},clear:function clear(){if(this._vmlViewport){this.root.removeChild(this._vmlViewport);}},_getWidth:function _getWidth(){var root=this.root;var stl=root.currentStyle;return(root.clientWidth||parseInt10$1(stl.width))-parseInt10$1(stl.paddingLeft)-parseInt10$1(stl.paddingRight)|0;},_getHeight:function _getHeight(){var root=this.root;var stl=root.currentStyle;return(root.clientHeight||parseInt10$1(stl.height))-parseInt10$1(stl.paddingTop)-parseInt10$1(stl.paddingBottom)|0;}};// Not supported methods\nfunction createMethodNotSupport(method){return function(){logError$1('In IE8.0 VML mode painter not support method \"'+method+'\"');};}// Unsupported methods\neach$1(['getLayer','insertLayer','eachLayer','eachBuiltinLayer','eachOtherLayer','getLayers','modLayer','delLayer','clearLayer','toDataURL','pathToImage'],function(name){VMLPainter.prototype[name]=createMethodNotSupport(name);});registerPainter('vml',VMLPainter);var svgURI='http://www.w3.org/2000/svg';function createElement(name){return document.createElementNS(svgURI,name);}// TODO\n// 1. shadow\n// 2. Image: sx, sy, sw, sh\nvar CMD$4=PathProxy.CMD;var arrayJoin=Array.prototype.join;var NONE='none';var mathRound=Math.round;var mathSin$3=Math.sin;var mathCos$3=Math.cos;var PI$3=Math.PI;var PI2$5=Math.PI*2;var degree=180/PI$3;var EPSILON$4=1e-4;function round4(val){return mathRound(val*1e4)/1e4;}function isAroundZero$1(val){return val<EPSILON$4&&val>-EPSILON$4;}function pathHasFill(style,isText){var fill=isText?style.textFill:style.fill;return fill!=null&&fill!==NONE;}function pathHasStroke(style,isText){var stroke=isText?style.textStroke:style.stroke;return stroke!=null&&stroke!==NONE;}function setTransform(svgEl,m){if(m){attr(svgEl,'transform','matrix('+arrayJoin.call(m,',')+')');}}function attr(el,key,val){if(!val||val.type!=='linear'&&val.type!=='radial'){// Don't set attribute for gradient, since it need new dom nodes\nel.setAttribute(key,val);}}function attrXLink(el,key,val){el.setAttributeNS('http://www.w3.org/1999/xlink',key,val);}function bindStyle(svgEl,style,isText,el){if(pathHasFill(style,isText)){var fill=isText?style.textFill:style.fill;fill=fill==='transparent'?NONE:fill;attr(svgEl,'fill',fill);attr(svgEl,'fill-opacity',style.fillOpacity!=null?style.fillOpacity*style.opacity:style.opacity);}else{attr(svgEl,'fill',NONE);}if(pathHasStroke(style,isText)){var stroke=isText?style.textStroke:style.stroke;stroke=stroke==='transparent'?NONE:stroke;attr(svgEl,'stroke',stroke);var strokeWidth=isText?style.textStrokeWidth:style.lineWidth;var strokeScale=!isText&&style.strokeNoScale?el.getLineScale():1;attr(svgEl,'stroke-width',strokeWidth/strokeScale);// stroke then fill for text; fill then stroke for others\nattr(svgEl,'paint-order',isText?'stroke':'fill');attr(svgEl,'stroke-opacity',style.strokeOpacity!=null?style.strokeOpacity:style.opacity);var lineDash=style.lineDash;if(lineDash){attr(svgEl,'stroke-dasharray',style.lineDash.join(','));attr(svgEl,'stroke-dashoffset',mathRound(style.lineDashOffset||0));}else{attr(svgEl,'stroke-dasharray','');}// PENDING\nstyle.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);}}/***************************************************\n * PATH\n **************************************************/function pathDataToString$1(path){var str=[];var data=path.data;var dataLength=path.len();for(var i=0;i<dataLength;){var cmd=data[i++];var cmdStr='';var nData=0;switch(cmd){case CMD$4.M:cmdStr='M';nData=2;break;case CMD$4.L:cmdStr='L';nData=2;break;case CMD$4.Q:cmdStr='Q';nData=4;break;case CMD$4.C:cmdStr='C';nData=6;break;case CMD$4.A:var cx=data[i++];var cy=data[i++];var rx=data[i++];var ry=data[i++];var theta=data[i++];var dTheta=data[i++];var psi=data[i++];var clockwise=data[i++];var dThetaPositive=Math.abs(dTheta);var isCircle=isAroundZero$1(dThetaPositive-PI2$5)||(clockwise?dTheta>=PI2$5:-dTheta>=PI2$5);// Mapping to 0~2PI\nvar unifiedTheta=dTheta>0?dTheta%PI2$5:dTheta%PI2$5+PI2$5;var large=false;if(isCircle){large=true;}else if(isAroundZero$1(dThetaPositive)){large=false;}else{large=unifiedTheta>=PI$3===!!clockwise;}var x0=round4(cx+rx*mathCos$3(theta));var y0=round4(cy+ry*mathSin$3(theta));// It will not draw if start point and end point are exactly the same\n// We need to shift the end point with a small value\n// FIXME A better way to draw circle ?\nif(isCircle){if(clockwise){dTheta=PI2$5-1e-4;}else{dTheta=-PI2$5+1e-4;}large=true;if(i===9){// Move to (x0, y0) only when CMD.A comes at the\n// first position of a shape.\n// For instance, when drawing a ring, CMD.A comes\n// after CMD.M, so it's unnecessary to move to\n// (x0, y0).\nstr.push('M',x0,y0);}}var x=round4(cx+rx*mathCos$3(theta+dTheta));var y=round4(cy+ry*mathSin$3(theta+dTheta));// FIXME Ellipse\nstr.push('A',round4(rx),round4(ry),mathRound(psi*degree),+large,+clockwise,x,y);break;case CMD$4.Z:cmdStr='Z';break;case CMD$4.R:var x=round4(data[i++]);var y=round4(data[i++]);var w=round4(data[i++]);var h=round4(data[i++]);str.push('M',x,y,'L',x+w,y,'L',x+w,y+h,'L',x,y+h,'L',x,y);break;}cmdStr&&str.push(cmdStr);for(var j=0;j<nData;j++){// PENDING With scale\nstr.push(round4(data[i++]));}}return str.join(' ');}var svgPath={};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.__dirtyPath){path.beginPath();path.subPixelOptimize=false;el.buildPath(path,el.shape);el.__dirtyPath=false;var pathStr=pathDataToString$1(path);if(pathStr.indexOf('NaN')<0){// Ignore illegal path, which may happen such in out-of-range\n// data in Calendar series.\nattr(svgEl,'d',pathStr);}}bindStyle(svgEl,style,false,el);setTransform(svgEl,el.transform);if(style.text!=null){svgTextDrawRectText(el,el.getBoundingRect());}else{removeOldTextNode(el);}};/***************************************************\n * IMAGE\n **************************************************/var svgImage={};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);// Caching image src\nel.__imageSrc=image;}attr(svgEl,'width',dw);attr(svgEl,'height',dh);attr(svgEl,'x',x);attr(svgEl,'y',y);setTransform(svgEl,el.transform);if(style.text!=null){svgTextDrawRectText(el,el.getBoundingRect());}else{removeOldTextNode(el);}};/***************************************************\n * TEXT\n **************************************************/var svgText={};var _tmpTextHostRect=new BoundingRect();var _tmpTextBoxPos={};var _tmpTextTransform=[];var TEXT_ALIGN_TO_ANCHRO={left:'start',right:'end',center:'middle',middle:'middle'};/**\n * @param {module:zrender/Element} el\n * @param {Object|boolean} [hostRect] {x, y, width, height}\n *        If set false, rect text is not used.\n */var svgTextDrawRectText=function svgTextDrawRectText(el,hostRect){var style=el.style;var elTransform=el.transform;var needTransformTextByHostEl=el instanceof Text||style.transformText;el.__dirty&&normalizeTextStyle(style,true);var text=style.text;// Convert to string\ntext!=null&&(text+='');if(!needDrawText(text,style)){return;}// render empty text for svg if no text but need draw text.\ntext==null&&(text='');// Follow the setting in the canvas renderer, if not transform the\n// text, transform the hostRect, by which the text is located.\nif(!needTransformTextByHostEl&&elTransform){_tmpTextHostRect.copy(hostRect);_tmpTextHostRect.applyTransform(elTransform);hostRect=_tmpTextHostRect;}var textSvgEl=el.__textSvgEl;if(!textSvgEl){textSvgEl=createElement('text');el.__textSvgEl=textSvgEl;}// style.font has been normalized by `normalizeTextStyle`.\nvar textSvgElStyle=textSvgEl.style;var font=style.font||DEFAULT_FONT$1;var computedFont=textSvgEl.__computedFont;if(font!==textSvgEl.__styleFont){textSvgElStyle.font=textSvgEl.__styleFont=font;// The computedFont might not be the orginal font if it is illegal font.\ncomputedFont=textSvgEl.__computedFont=textSvgElStyle.font;}var textPadding=style.textPadding;var textLineHeight=style.textLineHeight;var contentBlock=el.__textCotentBlock;if(!contentBlock||el.__dirtyText){contentBlock=el.__textCotentBlock=parsePlainText(text,computedFont,textPadding,textLineHeight,style.truncate);}var outerHeight=contentBlock.outerHeight;var lineHeight=contentBlock.lineHeight;getBoxPosition(_tmpTextBoxPos,el,style,hostRect);var baseX=_tmpTextBoxPos.baseX;var baseY=_tmpTextBoxPos.baseY;var textAlign=_tmpTextBoxPos.textAlign||'left';var textVerticalAlign=_tmpTextBoxPos.textVerticalAlign;setTextTransform(textSvgEl,needTransformTextByHostEl,elTransform,style,hostRect,baseX,baseY);var boxY=adjustTextY(baseY,outerHeight,textVerticalAlign);var textX=baseX;var textY=boxY;// TODO needDrawBg\nif(textPadding){textX=getTextXForPadding$1(baseX,textAlign,textPadding);textY+=textPadding[0];}// `textBaseline` is set as 'middle'.\ntextY+=lineHeight/2;bindStyle(textSvgEl,style,true,el);// FIXME\n// Add a <style> to reset all of the text font as inherit?\n// otherwise the outer <style> may set the unexpected style.\n// Font may affect position of each tspan elements\nvar canCacheByTextString=contentBlock.canCacheByTextString;var tspanList=el.__tspanList||(el.__tspanList=[]);var tspanOriginLen=tspanList.length;// Optimize for most cases, just compare text string to determine change.\nif(canCacheByTextString&&el.__canCacheByTextString&&el.__text===text){if(el.__dirtyText&&tspanOriginLen){for(var idx=0;idx<tspanOriginLen;++idx){updateTextLocation(tspanList[idx],textAlign,textX,textY+idx*lineHeight);}}}else{el.__text=text;el.__canCacheByTextString=canCacheByTextString;var textLines=contentBlock.lines;var nTextLines=textLines.length;var idx=0;for(;idx<nTextLines;idx++){// Using cached tspan elements\nvar tspan=tspanList[idx];var singleLineText=textLines[idx];if(!tspan){tspan=tspanList[idx]=createElement('tspan');textSvgEl.appendChild(tspan);tspan.appendChild(document.createTextNode(singleLineText));}else if(tspan.__zrText!==singleLineText){tspan.innerHTML='';tspan.appendChild(document.createTextNode(singleLineText));}updateTextLocation(tspan,textAlign,textX,textY+idx*lineHeight);}// Remove unused tspan elements\nif(tspanOriginLen>nTextLines){for(;idx<tspanOriginLen;idx++){textSvgEl.removeChild(tspanList[idx]);}tspanList.length=nTextLines;}}};function setTextTransform(textSvgEl,needTransformTextByHostEl,elTransform,style,hostRect,baseX,baseY){identity(_tmpTextTransform);if(needTransformTextByHostEl&&elTransform){copy$1(_tmpTextTransform,elTransform);}// textRotation only apply in RectText.\nvar textRotation=style.textRotation;if(hostRect&&textRotation){var origin=style.textOrigin;if(origin==='center'){baseX=hostRect.width/2+hostRect.x;baseY=hostRect.height/2+hostRect.y;}else if(origin){baseX=origin[0]+hostRect.x;baseY=origin[1]+hostRect.y;}_tmpTextTransform[4]-=baseX;_tmpTextTransform[5]-=baseY;// Positive: anticlockwise\nrotate(_tmpTextTransform,_tmpTextTransform,textRotation);_tmpTextTransform[4]+=baseX;_tmpTextTransform[5]+=baseY;}// See the definition in `Style.js#textOrigin`, the default\n// origin is from the result of `getBoxPosition`.\nsetTransform(textSvgEl,_tmpTextTransform);}// FIXME merge the same code with `helper/text.js#getTextXForPadding`;\nfunction getTextXForPadding$1(x,textAlign,textPadding){return textAlign==='right'?x-textPadding[1]:textAlign==='center'?x+textPadding[3]/2-textPadding[1]/2:x+textPadding[3];}function updateTextLocation(tspan,textAlign,x,y){// Consider different font display differently in vertial align, we always\n// set vertialAlign as 'middle', and use 'y' to locate text vertically.\nattr(tspan,'dominant-baseline','middle');attr(tspan,'text-anchor',TEXT_ALIGN_TO_ANCHRO[textAlign]);attr(tspan,'x',x);attr(tspan,'y',y);}function removeOldTextNode(el){if(el&&el.__textSvgEl){// textSvgEl may has no parentNode if el has been removed temporary.\nif(el.__textSvgEl.parentNode){el.__textSvgEl.parentNode.removeChild(el.__textSvgEl);}el.__textSvgEl=null;el.__tspanList=[];el.__text=null;}}svgText.drawRectText=svgTextDrawRectText;svgText.brush=function(el){var style=el.style;if(style.text!=null){svgTextDrawRectText(el,false);}else{removeOldTextNode(el);}};// Myers' Diff Algorithm\n// Modified from https://github.com/kpdecker/jsdiff/blob/master/src/diff/base.js\nfunction Diff(){}Diff.prototype={diff:function diff(oldArr,newArr,equals){if(!equals){equals=function equals(a,b){return a===b;};}this.equals=equals;var self=this;oldArr=oldArr.slice();newArr=newArr.slice();// Allow subclasses to massage the input prior to running\nvar newLen=newArr.length;var oldLen=oldArr.length;var editLength=1;var maxEditLength=newLen+oldLen;var bestPath=[{newPos:-1,components:[]}];// Seed editLength = 0, i.e. the content starts with the same values\nvar oldPos=this.extractCommon(bestPath[0],newArr,oldArr,0);if(bestPath[0].newPos+1>=newLen&&oldPos+1>=oldLen){var indices=[];for(var i=0;i<newArr.length;i++){indices.push(i);}// Identity per the equality and tokenizer\nreturn[{indices:indices,count:newArr.length}];}// Main worker method. checks all permutations of a given edit length for acceptance.\nfunction 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){// No one else is going to attempt to use this value, clear it\nbestPath[diagonalPath-1]=undefined;}var canAdd=addPath&&addPath.newPos+1<newLen;var canRemove=removePath&&0<=oldPos&&oldPos<oldLen;if(!canAdd&&!canRemove){// If this path is a terminal then prune\nbestPath[diagonalPath]=undefined;continue;}// Select the diagonal that we want to branch from. We select the prior\n// path whose position in the new string is the farthest from the origin\n// and does not pass the bounds of the diff graph\nif(!canAdd||canRemove&&addPath.newPos<removePath.newPos){basePath=clonePath(removePath);self.pushComponent(basePath.components,undefined,true);}else{basePath=addPath;// No need to clone, we've pulled it from the list\nbasePath.newPos++;self.pushComponent(basePath.components,true,undefined);}oldPos=self.extractCommon(basePath,newArr,oldArr,diagonalPath);// If we have hit the end of both strings, then we are done\nif(basePath.newPos+1>=newLen&&oldPos+1>=oldLen){return buildValues(self,basePath.components,newArr,oldArr);}else{// Otherwise track this path as a potential candidate and continue.\nbestPath[diagonalPath]=basePath;}}editLength++;}while(editLength<=maxEditLength){var ret=execEditLength();if(ret){return ret;}}},pushComponent:function pushComponent(components,added,removed){var last=components[components.length-1];if(last&&last.added===added&&last.removed===removed){// We need to clone here as the component clone operation is just\n// as shallow array clone\ncomponents[components.length-1]={count:last.count+1,added:added,removed:removed};}else{components.push({count:1,added:added,removed:removed});}},extractCommon:function extractCommon(basePath,newArr,oldArr,diagonalPath){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&&this.equals(newArr[newPos+1],oldArr[oldPos+1])){newPos++;oldPos++;commonCount++;}if(commonCount){basePath.components.push({count:commonCount});}basePath.newPos=newPos;return oldPos;},tokenize:function tokenize(value){return value.slice();},join:function join(value){return value.slice();}};function buildValues(diff,components,newArr,oldArr){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;// Common case\nif(!component.added){oldPos+=component.count;}}else{var indices=[];for(var i=oldPos;i<oldPos+component.count;i++){indices.push(i);}component.indices=indices;oldPos+=component.count;}}return components;}function clonePath(path){return{newPos:path.newPos,components:path.components.slice(0)};}var arrayDiff=new Diff();var arrayDiff$1=function arrayDiff$1(oldArr,newArr,callback){return arrayDiff.diff(oldArr,newArr,callback);};/**\n * @file Manages elements that can be defined in <defs> in SVG,\n *       e.g., gradients, clip path, etc.\n * @author Zhang Wenli\n */var MARK_UNUSED='0';var MARK_USED='1';/**\n * Manages elements that can be defined in <defs> in SVG,\n * e.g., gradients, clip path, etc.\n *\n * @class\n * @param {number}          zrId      zrender instance id\n * @param {SVGElement}      svgRoot   root of SVG document\n * @param {string|string[]} tagNames  possible tag names\n * @param {string}          markLabel label name to make if the element\n *                                    is used\n */function Definable(zrId,svgRoot,tagNames,markLabel,domName){this._zrId=zrId;this._svgRoot=svgRoot;this._tagNames=typeof tagNames==='string'?[tagNames]:tagNames;this._markLabel=markLabel;this._domName=domName||'_dom';this.nextId=0;}Definable.prototype.createElement=createElement;/**\n * Get the <defs> tag for svgRoot; optionally creates one if not exists.\n *\n * @param {boolean} isForceCreating if need to create when not exists\n * @return {SVGDefsElement} SVG <defs> element, null if it doesn't\n * exist and isForceCreating is false\n */Definable.prototype.getDefs=function(isForceCreating){var svgRoot=this._svgRoot;var defs=this._svgRoot.getElementsByTagName('defs');if(defs.length===0){// Not exist\nif(isForceCreating){defs=svgRoot.insertBefore(this.createElement('defs'),// Create new tag\nsvgRoot.firstChild// Insert in the front of svg\n);if(!defs.contains){// IE doesn't support contains method\ndefs.contains=function(el){var children=defs.children;if(!children){return false;}for(var i=children.length-1;i>=0;--i){if(children[i]===el){return true;}}return false;};}return defs;}else{return null;}}else{return defs[0];}};/**\n * Update DOM element if necessary.\n *\n * @param {Object|string} element style element. e.g., for gradient,\n *                                it may be '#ccc' or {type: 'linear', ...}\n * @param {Function|undefined} onUpdate update callback\n */Definable.prototype.update=function(element,onUpdate){if(!element){return;}var defs=this.getDefs(false);if(element[this._domName]&&defs.contains(element[this._domName])){// Update DOM\nif(typeof onUpdate==='function'){onUpdate(element);}}else{// No previous dom, create new\nvar dom=this.add(element);if(dom){element[this._domName]=dom;}}};/**\n * Add gradient dom to defs\n *\n * @param {SVGElement} dom DOM to be added to <defs>\n */Definable.prototype.addDom=function(dom){var defs=this.getDefs(true);defs.appendChild(dom);};/**\n * Remove DOM of a given element.\n *\n * @param {SVGElement} element element to remove dom\n */Definable.prototype.removeDom=function(element){var defs=this.getDefs(false);if(defs&&element[this._domName]){defs.removeChild(element[this._domName]);element[this._domName]=null;}};/**\n * Get DOMs of this element.\n *\n * @return {HTMLDomElement} doms of this defineable elements in <defs>\n */Definable.prototype.getDoms=function(){var defs=this.getDefs(false);if(!defs){// No dom when defs is not defined\nreturn[];}var doms=[];each$1(this._tagNames,function(tagName){var tags=defs.getElementsByTagName(tagName);// Note that tags is HTMLCollection, which is array-like\n// rather than real array.\n// So `doms.concat(tags)` add tags as one object.\ndoms=doms.concat([].slice.call(tags));});return doms;};/**\n * Mark DOMs to be unused before painting, and clear unused ones at the end\n * of the painting.\n */Definable.prototype.markAllUnused=function(){var doms=this.getDoms();var that=this;each$1(doms,function(dom){dom[that._markLabel]=MARK_UNUSED;});};/**\n * Mark a single DOM to be used.\n *\n * @param {SVGElement} dom DOM to mark\n */Definable.prototype.markUsed=function(dom){if(dom){dom[this._markLabel]=MARK_USED;}};/**\n * Remove unused DOMs defined in <defs>\n */Definable.prototype.removeUnused=function(){var defs=this.getDefs(false);if(!defs){// Nothing to remove\nreturn;}var doms=this.getDoms();var that=this;each$1(doms,function(dom){if(dom[that._markLabel]!==MARK_USED){// Remove gradient\ndefs.removeChild(dom);}});};/**\n * Get SVG proxy.\n *\n * @param {Displayable} displayable displayable element\n * @return {Path|Image|Text} svg proxy of given element\n */Definable.prototype.getSvgProxy=function(displayable){if(displayable instanceof Path){return svgPath;}else if(displayable instanceof ZImage){return svgImage;}else if(displayable instanceof Text){return svgText;}else{return svgPath;}};/**\n * Get text SVG element.\n *\n * @param {Displayable} displayable displayable element\n * @return {SVGElement} SVG element of text\n */Definable.prototype.getTextSvgElement=function(displayable){return displayable.__textSvgEl;};/**\n * Get SVG element.\n *\n * @param {Displayable} displayable displayable element\n * @return {SVGElement} SVG element\n */Definable.prototype.getSvgElement=function(displayable){return displayable.__svgEl;};/**\n * @file Manages SVG gradient elements.\n * @author Zhang Wenli\n */ /**\n * Manages SVG gradient elements.\n *\n * @class\n * @extends Definable\n * @param   {number}     zrId    zrender instance id\n * @param   {SVGElement} svgRoot root of SVG document\n */function GradientManager(zrId,svgRoot){Definable.call(this,zrId,svgRoot,['linearGradient','radialGradient'],'__gradient_in_use__');}inherits(GradientManager,Definable);/**\n * Create new gradient DOM for fill or stroke if not exist,\n * but will not update gradient if exists.\n *\n * @param {SvgElement}  svgElement   SVG element to paint\n * @param {Displayable} displayable  zrender displayable element\n */GradientManager.prototype.addWithoutUpdate=function(svgElement,displayable){if(displayable&&displayable.style){var that=this;each$1(['fill','stroke'],function(fillOrStroke){if(displayable.style[fillOrStroke]&&(displayable.style[fillOrStroke].type==='linear'||displayable.style[fillOrStroke].type==='radial')){var gradient=displayable.style[fillOrStroke];var defs=that.getDefs(true);// Create dom in <defs> if not exists\nvar dom;if(gradient._dom){// Gradient exists\ndom=gradient._dom;if(!defs.contains(gradient._dom)){// _dom is no longer in defs, recreate\nthat.addDom(dom);}}else{// New dom\ndom=that.add(gradient);}that.markUsed(displayable);var id=dom.getAttribute('id');svgElement.setAttribute(fillOrStroke,'url(#'+id+')');}});}};/**\n * Add a new gradient tag in <defs>\n *\n * @param   {Gradient} gradient zr gradient instance\n * @return {SVGLinearGradientElement | SVGRadialGradientElement}\n *                            created DOM\n */GradientManager.prototype.add=function(gradient){var dom;if(gradient.type==='linear'){dom=this.createElement('linearGradient');}else if(gradient.type==='radial'){dom=this.createElement('radialGradient');}else{logError$1('Illegal gradient type.');return null;}// Set dom id with gradient id, since each gradient instance\n// will have no more than one dom element.\n// id may exists before for those dirty elements, in which case\n// id should remain the same, and other attributes should be\n// updated.\ngradient.id=gradient.id||this.nextId++;dom.setAttribute('id','zr'+this._zrId+'-gradient-'+gradient.id);this.updateDom(gradient,dom);this.addDom(dom);return dom;};/**\n * Update gradient.\n *\n * @param {Gradient} gradient zr gradient instance\n */GradientManager.prototype.update=function(gradient){var that=this;Definable.prototype.update.call(this,gradient,function(){var type=gradient.type;var tagName=gradient._dom.tagName;if(type==='linear'&&tagName==='linearGradient'||type==='radial'&&tagName==='radialGradient'){// Gradient type is not changed, update gradient\nthat.updateDom(gradient,gradient._dom);}else{// Remove and re-create if type is changed\nthat.removeDom(gradient);that.add(gradient);}});};/**\n * Update gradient dom\n *\n * @param {Gradient} gradient zr gradient instance\n * @param {SVGLinearGradientElement | SVGRadialGradientElement} dom\n *                            DOM to update\n */GradientManager.prototype.updateDom=function(gradient,dom){if(gradient.type==='linear'){dom.setAttribute('x1',gradient.x);dom.setAttribute('y1',gradient.y);dom.setAttribute('x2',gradient.x2);dom.setAttribute('y2',gradient.y2);}else if(gradient.type==='radial'){dom.setAttribute('cx',gradient.x);dom.setAttribute('cy',gradient.y);dom.setAttribute('r',gradient.r);}else{logError$1('Illegal gradient type.');return;}if(gradient.global){// x1, x2, y1, y2 in range of 0 to canvas width or height\ndom.setAttribute('gradientUnits','userSpaceOnUse');}else{// x1, x2, y1, y2 in range of 0 to 1\ndom.setAttribute('gradientUnits','objectBoundingBox');}// Remove color stops if exists\ndom.innerHTML='';// Add color stops\nvar colors=gradient.colorStops;for(var i=0,len=colors.length;i<len;++i){var stop=this.createElement('stop');stop.setAttribute('offset',colors[i].offset*100+'%');var color=colors[i].color;if(color.indexOf('rgba')>-1){// Fix Safari bug that stop-color not recognizing alpha #9014\nvar opacity=parse(color)[3];var hex=toHex(color);// stop-color cannot be color, since:\n// The opacity value used for the gradient calculation is the\n// *product* of the value of stop-opacity and the opacity of the\n// value of stop-color.\n// See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty\nstop.setAttribute('stop-color','#'+hex);stop.setAttribute('stop-opacity',opacity);}else{stop.setAttribute('stop-color',colors[i].color);}dom.appendChild(stop);}// Store dom element in gradient, to avoid creating multiple\n// dom instances for the same gradient element\ngradient._dom=dom;};/**\n * Mark a single gradient to be used\n *\n * @param {Displayable} displayable displayable element\n */GradientManager.prototype.markUsed=function(displayable){if(displayable.style){var gradient=displayable.style.fill;if(gradient&&gradient._dom){Definable.prototype.markUsed.call(this,gradient._dom);}gradient=displayable.style.stroke;if(gradient&&gradient._dom){Definable.prototype.markUsed.call(this,gradient._dom);}}};/**\n * @file Manages SVG clipPath elements.\n * @author Zhang Wenli\n */ /**\n * Manages SVG clipPath elements.\n *\n * @class\n * @extends Definable\n * @param   {number}     zrId    zrender instance id\n * @param   {SVGElement} svgRoot root of SVG document\n */function ClippathManager(zrId,svgRoot){Definable.call(this,zrId,svgRoot,'clipPath','__clippath_in_use__');}inherits(ClippathManager,Definable);/**\n * Update clipPath.\n *\n * @param {Displayable} displayable displayable element\n */ClippathManager.prototype.update=function(displayable){var svgEl=this.getSvgElement(displayable);if(svgEl){this.updateDom(svgEl,displayable.__clipPaths,false);}var textEl=this.getTextSvgElement(displayable);if(textEl){// Make another clipPath for text, since it's transform\n// matrix is not the same with svgElement\nthis.updateDom(textEl,displayable.__clipPaths,true);}this.markUsed(displayable);};/**\n * Create an SVGElement of displayable and create a <clipPath> of its\n * clipPath\n *\n * @param {Displayable} parentEl  parent element\n * @param {ClipPath[]}  clipPaths clipPaths of parent element\n * @param {boolean}     isText    if parent element is Text\n */ClippathManager.prototype.updateDom=function(parentEl,clipPaths,isText){if(clipPaths&&clipPaths.length>0){// Has clipPath, create <clipPath> with the first clipPath\nvar defs=this.getDefs(true);var clipPath=clipPaths[0];var clipPathEl;var id;var dom=isText?'_textDom':'_dom';if(clipPath[dom]){// Use a dom that is already in <defs>\nid=clipPath[dom].getAttribute('id');clipPathEl=clipPath[dom];// Use a dom that is already in <defs>\nif(!defs.contains(clipPathEl)){// This happens when set old clipPath that has\n// been previously removed\ndefs.appendChild(clipPathEl);}}else{// New <clipPath>\nid='zr'+this._zrId+'-clip-'+this.nextId;++this.nextId;clipPathEl=this.createElement('clipPath');clipPathEl.setAttribute('id',id);defs.appendChild(clipPathEl);clipPath[dom]=clipPathEl;}// Build path and add to <clipPath>\nvar svgProxy=this.getSvgProxy(clipPath);if(clipPath.transform&&clipPath.parent.invTransform&&!isText){/**\n             * If a clipPath has a parent with transform, the transform\n             * of parent should not be considered when setting transform\n             * of clipPath. So we need to transform back from parent's\n             * transform, which is done by multiplying parent's inverse\n             * transform.\n             */ // Store old transform\nvar transform=Array.prototype.slice.call(clipPath.transform);// Transform back from parent, and brush path\nmul$1(clipPath.transform,clipPath.parent.invTransform,clipPath.transform);svgProxy.brush(clipPath);// Set back transform of clipPath\nclipPath.transform=transform;}else{svgProxy.brush(clipPath);}var pathEl=this.getSvgElement(clipPath);clipPathEl.innerHTML='';/**\n         * Use `cloneNode()` here to appendChild to multiple parents,\n         * which may happend when Text and other shapes are using the same\n         * clipPath. Since Text will create an extra clipPath DOM due to\n         * different transform rules.\n         */clipPathEl.appendChild(pathEl.cloneNode());parentEl.setAttribute('clip-path','url(#'+id+')');if(clipPaths.length>1){// Make the other clipPaths recursively\nthis.updateDom(clipPathEl,clipPaths.slice(1),isText);}}else{// No clipPath\nif(parentEl){parentEl.setAttribute('clip-path','none');}}};/**\n * Mark a single clipPath to be used\n *\n * @param {Displayable} displayable displayable element\n */ClippathManager.prototype.markUsed=function(displayable){var that=this;// displayable.__clipPaths can only be `null`/`undefined` or an non-empty array.\nif(displayable.__clipPaths){each$1(displayable.__clipPaths,function(clipPath){if(clipPath._dom){Definable.prototype.markUsed.call(that,clipPath._dom);}if(clipPath._textDom){Definable.prototype.markUsed.call(that,clipPath._textDom);}});}};/**\n * @file Manages SVG shadow elements.\n * @author Zhang Wenli\n */ /**\n * Manages SVG shadow elements.\n *\n * @class\n * @extends Definable\n * @param   {number}     zrId    zrender instance id\n * @param   {SVGElement} svgRoot root of SVG document\n */function ShadowManager(zrId,svgRoot){Definable.call(this,zrId,svgRoot,['filter'],'__filter_in_use__','_shadowDom');}inherits(ShadowManager,Definable);/**\n * Create new shadow DOM for fill or stroke if not exist,\n * but will not update shadow if exists.\n *\n * @param {SvgElement}  svgElement   SVG element to paint\n * @param {Displayable} displayable  zrender displayable element\n */ShadowManager.prototype.addWithoutUpdate=function(svgElement,displayable){if(displayable&&hasShadow(displayable.style)){// Create dom in <defs> if not exists\nvar dom;if(displayable._shadowDom){// Gradient exists\ndom=displayable._shadowDom;var defs=this.getDefs(true);if(!defs.contains(displayable._shadowDom)){// _shadowDom is no longer in defs, recreate\nthis.addDom(dom);}}else{// New dom\ndom=this.add(displayable);}this.markUsed(displayable);var id=dom.getAttribute('id');svgElement.style.filter='url(#'+id+')';}};/**\n * Add a new shadow tag in <defs>\n *\n * @param {Displayable} displayable  zrender displayable element\n * @return {SVGFilterElement} created DOM\n */ShadowManager.prototype.add=function(displayable){var dom=this.createElement('filter');// Set dom id with shadow id, since each shadow instance\n// will have no more than one dom element.\n// id may exists before for those dirty elements, in which case\n// id should remain the same, and other attributes should be\n// updated.\ndisplayable._shadowDomId=displayable._shadowDomId||this.nextId++;dom.setAttribute('id','zr'+this._zrId+'-shadow-'+displayable._shadowDomId);this.updateDom(displayable,dom);this.addDom(dom);return dom;};/**\n * Update shadow.\n *\n * @param {Displayable} displayable  zrender displayable element\n */ShadowManager.prototype.update=function(svgElement,displayable){var style=displayable.style;if(hasShadow(style)){var that=this;Definable.prototype.update.call(this,displayable,function(){that.updateDom(displayable,displayable._shadowDom);});}else{// Remove shadow\nthis.remove(svgElement,displayable);}};/**\n * Remove DOM and clear parent filter\n */ShadowManager.prototype.remove=function(svgElement,displayable){if(displayable._shadowDomId!=null){this.removeDom(svgElement);svgElement.style.filter='';}};/**\n * Update shadow dom\n *\n * @param {Displayable} displayable  zrender displayable element\n * @param {SVGFilterElement} dom DOM to update\n */ShadowManager.prototype.updateDom=function(displayable,dom){var domChild=dom.getElementsByTagName('feDropShadow');if(domChild.length===0){domChild=this.createElement('feDropShadow');}else{domChild=domChild[0];}var style=displayable.style;var scaleX=displayable.scale?displayable.scale[0]||1:1;var scaleY=displayable.scale?displayable.scale[1]||1:1;// TODO: textBoxShadowBlur is not supported yet\nvar offsetX;var offsetY;var blur;var color;if(style.shadowBlur||style.shadowOffsetX||style.shadowOffsetY){offsetX=style.shadowOffsetX||0;offsetY=style.shadowOffsetY||0;blur=style.shadowBlur;color=style.shadowColor;}else if(style.textShadowBlur){offsetX=style.textShadowOffsetX||0;offsetY=style.textShadowOffsetY||0;blur=style.textShadowBlur;color=style.textShadowColor;}else{// Remove shadow\nthis.removeDom(dom,style);return;}domChild.setAttribute('dx',offsetX/scaleX);domChild.setAttribute('dy',offsetY/scaleY);domChild.setAttribute('flood-color',color);// Divide by two here so that it looks the same as in canvas\n// See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur\nvar stdDx=blur/2/scaleX;var stdDy=blur/2/scaleY;var stdDeviation=stdDx+' '+stdDy;domChild.setAttribute('stdDeviation',stdDeviation);// Fix filter clipping problem\ndom.setAttribute('x','-100%');dom.setAttribute('y','-100%');dom.setAttribute('width',Math.ceil(blur/2*200)+'%');dom.setAttribute('height',Math.ceil(blur/2*200)+'%');dom.appendChild(domChild);// Store dom element in shadow, to avoid creating multiple\n// dom instances for the same shadow element\ndisplayable._shadowDom=dom;};/**\n * Mark a single shadow to be used\n *\n * @param {Displayable} displayable displayable element\n */ShadowManager.prototype.markUsed=function(displayable){if(displayable._shadowDom){Definable.prototype.markUsed.call(this,displayable._shadowDom);}};function hasShadow(style){// TODO: textBoxShadowBlur is not supported yet\nreturn style&&(style.shadowBlur||style.shadowOffsetX||style.shadowOffsetY||style.textShadowBlur||style.textShadowOffsetX||style.textShadowOffsetY);}/**\n * SVG Painter\n * @module zrender/svg/Painter\n */function parseInt10$2(val){return parseInt(val,10);}function getSvgProxy(el){if(el instanceof Path){return svgPath;}else if(el instanceof ZImage){return svgImage;}else if(el instanceof Text){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 append(parent, child) {\n//     if (checkParentAvailable(parent, child)) {\n//         parent.appendChild(child);\n//     }\n// }\nfunction remove$1(parent,child){if(child&&parent&&child.parentNode===parent){parent.removeChild(child);}}function getTextSvgElement(displayable){return displayable.__textSvgEl;}function getSvgElement(displayable){return displayable.__svgEl;}/**\n * @alias module:zrender/svg/Painter\n * @constructor\n * @param {HTMLElement} root 绘图容器\n * @param {module:zrender/Storage} storage\n * @param {Object} opts\n */var SVGPainter=function SVGPainter(root,storage,opts,zrId){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.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={constructor:SVGPainter,getType:function getType(){return'svg';},getViewportRoot:function getViewportRoot(){return this._viewport;},getSvgDom:function getSvgDom(){return this._svgDom;},getSvgRoot:function getSvgRoot(){return this._svgRoot;},getViewportRootOffset:function getViewportRootOffset(){var viewportRoot=this.getViewportRoot();if(viewportRoot){return{offsetLeft:viewportRoot.offsetLeft||0,offsetTop:viewportRoot.offsetTop||0};}},refresh:function refresh(){var list=this.storage.getDisplayList(true);this._paintList(list);},setBackgroundColor:function setBackgroundColor(backgroundColor){// TODO gradient\n// Insert a bg rect instead of setting background to viewport.\n// Otherwise, the exported SVG don't have background.\nif(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;},_paintList:function _paintList(list){this.gradientManager.markAllUnused();this.clipPathManager.markAllUnused();this.shadowManager.markAllUnused();var svgRoot=this._svgRoot;var visibleList=this._visibleList;var listLen=list.length;var newVisibleList=[];var i;for(i=0;i<listLen;i++){var displayable=list[i];var svgProxy=getSvgProxy(displayable);var svgElement=getSvgElement(displayable)||getTextSvgElement(displayable);if(!displayable.invisible){if(displayable.__dirty){svgProxy&&svgProxy.brush(displayable);// Update clipPath\nthis.clipPathManager.update(displayable);// Update gradient and shadow\nif(displayable.style){this.gradientManager.update(displayable.style.fill);this.gradientManager.update(displayable.style.stroke);this.shadowManager.update(svgElement,displayable);}displayable.__dirty=false;}newVisibleList.push(displayable);}}var diff=arrayDiff$1(visibleList,newVisibleList);var prevSvgElement;// First do remove, in case element moved to the head and do remove\n// after add\nfor(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);var textSvgElement=getTextSvgElement(displayable);remove$1(svgRoot,svgElement);remove$1(svgRoot,textSvgElement);}}}for(i=0;i<diff.length;i++){var item=diff[i];if(item.added){for(var k=0;k<item.count;k++){var displayable=newVisibleList[item.indices[k]];var svgElement=getSvgElement(displayable);var textSvgElement=getTextSvgElement(displayable);prevSvgElement?insertAfter(svgRoot,svgElement,prevSvgElement):prepend(svgRoot,svgElement);if(svgElement){insertAfter(svgRoot,textSvgElement,svgElement);}else if(prevSvgElement){insertAfter(svgRoot,textSvgElement,prevSvgElement);}else{prepend(svgRoot,textSvgElement);}// Insert text\ninsertAfter(svgRoot,textSvgElement,svgElement);prevSvgElement=textSvgElement||svgElement||prevSvgElement;// zrender.Text only create textSvgElement.\nthis.gradientManager.addWithoutUpdate(svgElement||textSvgElement,displayable);this.shadowManager.addWithoutUpdate(svgElement||textSvgElement,displayable);this.clipPathManager.markUsed(displayable);}}else if(!item.removed){for(var k=0;k<item.count;k++){var displayable=newVisibleList[item.indices[k]];var svgElement=getSvgElement(displayable);var textSvgElement=getTextSvgElement(displayable);var svgElement=getSvgElement(displayable);var textSvgElement=getTextSvgElement(displayable);this.gradientManager.markUsed(displayable);this.gradientManager.addWithoutUpdate(svgElement||textSvgElement,displayable);this.shadowManager.markUsed(displayable);this.shadowManager.addWithoutUpdate(svgElement||textSvgElement,displayable);this.clipPathManager.markUsed(displayable);if(textSvgElement){// Insert text.\ninsertAfter(svgRoot,textSvgElement,svgElement);}prevSvgElement=svgElement||textSvgElement||prevSvgElement;}}}this.gradientManager.removeUnused();this.clipPathManager.removeUnused();this.shadowManager.removeUnused();this._visibleList=newVisibleList;},_getDefs:function _getDefs(isForceCreating){var svgRoot=this._svgDom;var defs=svgRoot.getElementsByTagName('defs');if(defs.length===0){// Not exist\nif(isForceCreating){var defs=svgRoot.insertBefore(createElement('defs'),// Create new tag\nsvgRoot.firstChild// Insert in the front of svg\n);if(!defs.contains){// IE doesn't support contains method\ndefs.contains=function(el){var children=defs.children;if(!children){return false;}for(var i=children.length-1;i>=0;--i){if(children[i]===el){return true;}}return false;};}return defs;}else{return null;}}else{return defs[0];}},resize:function resize(width,height){var viewport=this._viewport;// FIXME Why ?\nviewport.style.display='none';// Save input w/h\nvar 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;// Set width by 'svgRoot.width = width' is invalid\nsvgRoot.setAttribute('width',width);svgRoot.setAttribute('height',height);}if(this._backgroundNode){this._backgroundNode.setAttribute('width',width);this._backgroundNode.setAttribute('height',height);}},/**\n     * 获取绘图区域宽度\n     */getWidth:function getWidth(){return this._width;},/**\n     * 获取绘图区域高度\n     */getHeight:function getHeight(){return this._height;},_getSize:function _getSize(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;// IE8 does not support getComputedStyle, but it use VML.\nvar stl=document.defaultView.getComputedStyle(root);return(root[cwh]||parseInt10$2(stl[wh])||parseInt10$2(root.style[wh]))-(parseInt10$2(stl[plt])||0)-(parseInt10$2(stl[prb])||0)|0;},dispose:function dispose(){this.root.innerHTML='';this._svgRoot=this._backgroundRoot=this._svgDom=this._backgroundNode=this._viewport=this.storage=null;},clear:function clear(){if(this._viewport){this.root.removeChild(this._viewport);}},toDataURL:function toDataURL(){this.refresh();var html=encodeURIComponent(this._svgDom.outerHTML.replace(/></g,'>\\n\\r<'));return'data:image/svg+xml;charset=UTF-8,'+html;}};// Not supported methods\nfunction createMethodNotSupport$1(method){return function(){logError$1('In SVG mode painter not support method \"'+method+'\"');};}// Unsuppoted methods\neach$1(['getLayer','insertLayer','eachLayer','eachBuiltinLayer','eachOtherLayer','getLayers','modLayer','delLayer','clearLayer','pathToImage'],function(name){SVGPainter.prototype[name]=createMethodNotSupport$1(name);});registerPainter('svg',SVGPainter);/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements.  See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership.  The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License.  You may obtain a copy of the License at\n*\n*   http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/exports.version=version;exports.dependencies=dependencies;exports.PRIORITY=PRIORITY;exports.init=init;exports.connect=connect;exports.disConnect=disConnect;exports.disconnect=disconnect;exports.dispose=dispose;exports.getInstanceByDom=getInstanceByDom;exports.getInstanceById=getInstanceById;exports.registerTheme=registerTheme;exports.registerPreprocessor=registerPreprocessor;exports.registerProcessor=registerProcessor;exports.registerPostUpdate=registerPostUpdate;exports.registerAction=registerAction;exports.registerCoordinateSystem=registerCoordinateSystem;exports.getCoordinateSystemDimensions=getCoordinateSystemDimensions;exports.registerLayout=registerLayout;exports.registerVisual=registerVisual;exports.registerLoading=registerLoading;exports.extendComponentModel=extendComponentModel;exports.extendComponentView=extendComponentView;exports.extendSeriesModel=extendSeriesModel;exports.extendChartView=extendChartView;exports.setCanvasCreator=setCanvasCreator;exports.registerMap=registerMap;exports.getMap=getMap;exports.dataTool=dataTool;exports.zrender=zrender;exports.number=number;exports.format=format;exports.throttle=throttle;exports.helper=helper;exports.matrix=matrix;exports.vector=vector;exports.color=color;exports.parseGeoJSON=parseGeoJSON;exports.parseGeoJson=parseGeoJson;exports.util=ecUtil;exports.graphic=graphic$1;exports.List=List;exports.Model=Model;exports.Axis=Axis;exports.env=env$1;});\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))\n\n//# sourceURL=webpack:///./node_modules/echarts/dist/echarts-en.common.js?");

/***/ })

}]);