(function(global,base_factory){typeofexports==='object'&&typeofmodule!=='undefined'?base_factory(exports):typeofdefine==='function'&&define.amd?define(['exports'],base_factory):(base_factory((global.echarts={})));}(this,(function(exports){'use strict';/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///(1)Thecode`if(__DEV__)...`canberemovedbybuildtool.// (2) If intend to use `__DEV__`, this module should be imported. Use a global// variable `__DEV__` may cause that miss the declaration (see #6535), or the// declaration is behind of the using position (for example in `Model.extent`,// And tools like rollup can not analysis the dependency if not import).vardev;// In browserif(typeofwindow!=='undefined'){dev=window.__DEV__;}// In nodeelseif(typeofglobal!=='undefined'){dev=global.__DEV__;}if(typeofdev==='undefined'){dev=true;}var__DEV__=dev;/** * zrender: 生成唯一id * * @author errorrik (errorrik@gmail.com) */varidStart=0x0907;varguid=function(){returnidStart++;};/** * echarts设备环境识别 * * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 * @author firede[firede@firede.us] * @desc thanks zepto. */varenv={};if(typeofwx==='object'&&typeofwx.getSystemInfoSync==='function'){// In Weixin Applicationenv={browser:{},os:{},node:false,wxa:true,// Weixin ApplicationcanvasSupported:true,svgSupported:false,touchEventsSupported:true,domSupported:false};}elseif(typeofdocument==='undefined'&&typeofself!=='undefined'){// In workerenv={browser:{},os:{},node:false,worker:true,canvasSupported:true,domSupported:false};}elseif(typeofnavigator==='undefined'){// In nodeenv={browser:{},os:{},node:true,worker:false,// Assume canvas is supportedcanvasSupported:true,svgSupported:true,domSupported:false};}else{env=detect(navigator.userAgent);}varenv$1=env;// Zepto.js// (c) 2010-2013 Thomas Fuchs// Zepto.js may be freely distributed under the MIT license.functiondetect(ua){varos={};varbrowser={};// var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/);// var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);// var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);// var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);// var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);// var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/);// var touchpad = webos && ua.match(/TouchPad/);// var kindle = ua.match(/Kindle\/([\d.]+)/);// var silk = ua.match(/Silk\/([\d._]+)/);// var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/);// var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/);// var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/);// var playbook = ua.match(/PlayBook/);// var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/);varfirefox=ua.match(/Firefox\/([\d.]+)/);// var safari = webkit && ua.match(/Mobile\//) && !chrome;// var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome;varie=ua.match(/MSIE\s([\d.]+)/)// IE 11 Trident/7.0; rv:11.0||ua.match(/Trident\/.+?rv:(([\d.]+))/);varedge=ua.match(/Edge\/([\d.]+)/);// IE 12 and 12+varweChat=(/micromessenger/i).test(ua);// Todo: clean this up with a better OS/browser seperation:// - discern (more) between multiple browsers on android// - decide if kindle fire in silk mode is android or not// - Firefox on Android doesn't specify the Android version// - possibly devide in os, device and browser hashes// if (browser.webkit = !!webkit) browser.version = webkit[1];// if (android) os.android = true, os.version = android[2];// if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');// if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');// if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;// if (webos) os.webos = true, os.version = webos[2];// if (touchpad) os.touchpad = true;// if (blackberry) os.blackberry = true, os.version = blackberry[2];// if (bb10) os.bb10 = true, os.version = bb10[2];// if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2];// if (playbook) browser.playbook = true;// if (kindle) os.kindle = true, os.version = kindle[1];// if (silk) browser.silk = true, browser.version = silk[1];// if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;// if (chrome) browser.chrome = true, browser.version = chrome[1];if(firefox){browser.firefox=true;browser.version=firefox[1];}// if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true;// if (webview) browser.webview = true;if(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// not be set on win phone. So we do not consider Win Phone.if(weChat){browser.weChat=true;}// os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||// (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)));// os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos ||// (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) ||// (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))));return{browser:browser,os:os,node:false,// 原生canvas支持,改极端点了// canvasSupported : !(browser.ie && parseFloat(browser.version) < 9)canvasSupported:!!document.createElement('canvas').getContext,svgSupported:typeofSVGRect!=='undefined',// works on most browsers// IE10/11 does not support touch event, and MS Edge supports them but not by// default, so we dont check navigator.maxTouchPoints for them here.touchEventsSupported:'ontouchstart'inwindow&&!browser.ie&&!browser.edge,// <http://caniuse.com/#search=pointer%20event>.pointerEventsSupported:'onpointerdown'inwindow// Firefox supports pointer but not by default, only MS browsers are reliable on pointer// events currently. So we dont use that on other browsers unless tested sufficiently.// Although IE 10 supports pointer event, it use old style and is different from the// standard. So we exclude that. (IE 10 is hardly used on touch device)&&(browser.edge||(browser.ie&&browser.version>=11)),// passiveSupported: detectPassiveSupport()domSupported:typeofdocument!=='undefined'};}// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection// function detectPassiveSupport() {// // Test via a getter in the options object to see if the passive property is accessed// var supportsPassive = false;// try {// var opts = Object.defineProperty({}, 'passive', {// get: function() {// supportsPassive = true;// }// });// window.addEventListener('testPassive', function() {}, opts);// } catch (e) {// }// return supportsPassive;// }/** * @module zrender/core/util*///用于处理merge时无法遍历Date等对象的问题varBUILTIN_OBJECT={'[object Function]':1,'[object RegExp]':1,'[object Date]':1,'[object Error]':1,'[object CanvasGradient]':1,'[object CanvasPattern]':1,// For node-canvas'[object Image]':1,'[object Canvas]':1};varTYPED_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};varobjToString=Object.prototype.toString;vararrayProto=Array.prototype;varnativeForEach=arrayProto.forEach;varnativeFilter=arrayProto.filter;varnativeSlice=arrayProto.slice;varnativeMap=arrayProto.map;varnativeReduce=arrayProto.reduce;// Avoid assign to an exported variable, for transforming to cjs.varmethods={};function$override(name,fn){// Clear ctx instance for different environmentif(name==='createCanvas'){_ctx=null;}methods[name]=fn;}/** * Those data types can be cloned: * Plain object, Array, TypedArray, number, string, null, undefined. * Those data types will be assgined using the orginal data: * BUILTIN_OBJECT * Instance of user defined class will be cloned to a plain object, without * properties in prototype. * Other data types is not supported (not sure what will happen). * * Caution: do not support clone Date, for performance consideration. * (There might be a large number of date in `series.data`). * So date should not be modified in and out of echarts. * * @param {*} source * @return {*} new */functionclone(source){if(source==null||typeofsource!='object'){returnsource;}varresult=source;vartypeStr=objToString.call(source);if(typeStr==='[object Array]'){if(!isPrimitive(source)){result=[];for(vari=0,len=source.length;i<len;i++){result[i]=clone(source[i]);}}}elseif(TYPED_ARRAY[typeStr]){if(!isPrimitive(source)){varCtor=source.constructor;if(source.constructor.from){result=Ctor.from(source);}else{result=newCtor(source.length);for(vari=0,len=source.length;i<len;i++){result[i]=clone(source[i]);}}}}elseif(!BUILTIN_OBJECT[typeStr]&&!isPrimitive(source)&&!isDom(source)){result={};for(varkeyinsource){if(source.hasOwnProperty(key)){result[key]=clone(source[key]);}}}returnresult;}/** * @memberOf module:zrender/core/util*@param{*}target*@param{*}source*@param{boolean}[overwrite=false]*/function merge(target, source, overwrite) { //Weshouldescapsethatsourceisstring// and enter for ... in ...if(!isObject$1(source)||!isObject$1(target)){returnoverwrite?clone(source):target;}for(varkeyinsource){if(source.hasOwnProperty(key)){vartargetProp=target[key];varsourceProp=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)){// 如果需要递归覆盖,就递归调用mergemerge(targetProp,sourceProp,overwrite);}elseif(overwrite||!(keyintarget)){// 否则只处理overwrite为true,或者在目标对象中没有此属性的情况// NOTE,在 target[key] 不存在的时候也是直接覆盖target[key]=clone(source[key],true);}}}returntarget;}/** * @param {Array} targetAndSources The first item is target, and the rests are source. * @param {boolean} [overwrite=false] * @return {*} target */functionmergeAll(targetAndSources,overwrite){varresult=targetAndSources[0];for(vari=1,len=targetAndSources.length;i<len;i++){result=merge(result,targetAndSources[i],overwrite);}returnresult;}/** * @param {*} target * @param {*} source * @memberOf module:zrender/core/util*/function extend(target, source) { for (var key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } } return target;}/***@param{*}target*@param{*}source*@param{boolean}[overlay=false]*@memberOfmodule:zrender/core/util*/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 () { return methods.createCanvas();};methods.createCanvas = function () { return document.createElement('canvas');};//FIXMEvar_ctx;functiongetContext(){if(!_ctx){// Use util.createCanvas instead of createCanvas// because createCanvas may be overwritten in different environment_ctx=createCanvas().getContext('2d');}return_ctx;}/** * 查询数组中元素的index * @memberOf module:zrender/core/util*/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;}/***构造类继承关系**@memberOfmodule:zrender/core/util*@param{Function}clazz源类*@param{Function}baseClazz基类*/function inherits(clazz, baseClazz) { var clazzPrototype = clazz.prototype; function F() {} F.prototype = baseClazz.prototype; clazz.prototype = new F(); for (var prop in clazzPrototype) { clazz.prototype[prop] = clazzPrototype[prop]; } clazz.prototype.constructor = clazz; clazz.superClass = baseClazz;}/***@memberOfmodule:zrender/core/util*@param{Object|Function}target*@param{Object|Function}sorce*@param{boolean}overlay*/function mixin(target, source, overlay) { target = 'prototype' in target ? target.prototype : target; source = 'prototype' in source ? source.prototype : source; defaults(target, source, overlay);}/***Considertypedarray.*@param{Array|TypedArray}data*/function isArrayLike(data) { if (! data) { return; } if (typeof data == 'string') { return false; } return typeof data.length == 'number';}/***数组或对象遍历*@memberOfmodule:zrender/core/util*@param{Object|Array}obj*@param{Function}cb*@param{*}[context]*/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); } } }}/***数组映射*@memberOfmodule:zrender/core/util*@param{Array}obj*@param{Function}cb*@param{*}[context]*@return{Array}*/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; }}/***@memberOfmodule:zrender/core/util*@param{Array}obj*@param{Function}cb*@param{Object}[memo]*@param{*}[context]*@return{Array}*/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; }}/***数组过滤*@memberOfmodule:zrender/core/util*@param{Array}obj*@param{Function}cb*@param{*}[context]*@return{Array}*/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; }}/***数组项查找*@memberOfmodule:zrender/core/util*@param{Array}obj*@param{Function}cb*@param{*}[context]*@return{*}*//***@memberOfmodule:zrender/core/util*@param{Function}func*@param{*}context*@return{Function}*/function bind(func, context) { var args = nativeSlice.call(arguments, 2); return function () { return func.apply(context, args.concat(nativeSlice.call(arguments))); };}/***@memberOfmodule:zrender/core/util*@param{Function}func*@return{Function}*/function curry(func) { var args = nativeSlice.call(arguments, 1); return function () { return func.apply(this, args.concat(nativeSlice.call(arguments))); };}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isArray(value) { return objToString.call(value) === '[object Array]';}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isFunction$1(value) { return typeof value === 'function';}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isString(value) { return objToString.call(value) === '[object String]';}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isObject$1(value) { //AvoidaV8JITbuginChrome19-20.// See https://code.google.com/p/v8/issues/detail?id=2291 for more details.vartype=typeofvalue;returntype==='function'||(!!value&&type=='object');}/** * @memberOf module:zrender/core/util*@param{*}value*@return{boolean}*/function isBuiltInObject(value) { return !!BUILTIN_OBJECT[objToString.call(value)];}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isTypedArray(value) { return !!TYPED_ARRAY[objToString.call(value)];}/***@memberOfmodule:zrender/core/util*@param{*}value*@return{boolean}*/function isDom(value) { return typeof value === 'object' && typeof value.nodeType === 'number' && typeof value.ownerDocument === 'object';}/***WhetherisexactlyNaN.NoticeisNaN('a')returnstrue.*@param{*}value*@return{boolean}*/function eqNaN(value) { return value !== value;}/***Ifvalue1isnotnull,thenreturnvalue1,otherwisejudgetrestofvalues.*Lowperformance.*@memberOfmodule:zrender/core/util*@return{*}Finalvalue*/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;}/***@memberOfmodule:zrender/core/util*@param{Array}arr*@param{number}startIndex*@param{number}endIndex*@return{Array}*/function slice() { return Function.call.apply(nativeSlice, arguments);}/***Normalizecsslikedarrayconfiguration*e.g.*3=>[3,3,3,3]*[4,2]=>[4,2,4,2]*[4,3,2]=>[4,3,2,3]*@param{number|Array.<number>}val*@return{Array.<number>}*/function normalizeCssArray(val) { if (typeof (val) === 'number') { return [val, val, val, val]; } var len = val.length; if (len === 2) { //vertical|horizontalreturn[val[0],val[1],val[0],val[1]];}elseif(len===3){// top | horizontal | bottomreturn[val[0],val[1],val[2],val[1]];}returnval;}/** * @memberOf module:zrender/core/util*@param{boolean}condition*@param{string}message*/function assert$1(condition, message) { if (!condition) { throw new Error(message); }}/***@memberOfmodule:zrender/core/util*@param{string}strstringtobetrimed*@return{string}trimedstring*/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,'');}}varprimitiveKey='__ec_primitive__';/** * Set an object as primitive to be ignored traversing children in clone or merge */functionsetAsPrimitive(obj){obj[primitiveKey]=true;}functionisPrimitive(obj){returnobj[primitiveKey];}/** * @constructor * @param {Object} obj Only apply `ownProperty`. */functionHashMap(obj){varisArr=isArray(obj);// Key should not be set on this, otherwise// methods get/set/... may be overrided.this.data={};varthisMap=this;(objinstanceofHashMap)?obj.each(visit):(obj&&each$1(obj,visit));functionvisit(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`.// (We usually treat `null` and `undefined` as the same, different// from ES6 Map).get:function(key){returnthis.data.hasOwnProperty(key)?this.data[key]:null;},set:function(key,value){// Comparing with invocation chaining, `return value` is more commonly// used in this case: `var someVal = map.set('a', genVal());`return(this.data[key]=value);},// Although util.each can be performed on this hashMap directly, user// should not use the exposed keys, who are prefixed.each:function(cb,context){context!==void0&&(cb=bind(cb,context));for(varkeyinthis.data){this.data.hasOwnProperty(key)&&cb(this.data[key],key);}},// Do not use this method if performance sensitive.removeKey:function(key){deletethis.data[key];}};functioncreateHashMap(obj){returnnewHashMap(obj);}functionnoop(){}varArrayCtor=typeofFloat32Array==='undefined'?Array:Float32Array;/** * 创建一个向量 * @param {number} [x=0] * @param {number} [y=0] * @return {Vector2} */functioncreate(x,y){varout=newArrayCtor(2);if(x==null){x=0;}if(y==null){y=0;}out[0]=x;out[1]=y;returnout;}/** * 复制向量数据 * @param {Vector2} out * @param {Vector2} v * @return {Vector2} */functioncopy(out,v){out[0]=v[0];out[1]=v[1];returnout;}/** * 克隆一个向量 * @param {Vector2} v * @return {Vector2} */functionclone$1(v){varout=newArrayCtor(2);out[0]=v[0];out[1]=v[1];returnout;}/** * 设置向量的两个项 * @param {Vector2} out * @param {number} a * @param {number} b * @return {Vector2} 结果 *//***向量相加*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*/function add(out, v1, v2) { out[0] = v1[0] + v2[0]; out[1] = v1[1] + v2[1]; return out;}/***向量缩放后相加*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*@param{number}a*/function scaleAndAdd(out, v1, v2, a) { out[0] = v1[0] + v2[0] * a; out[1] = v1[1] + v2[1] * a; return out;}/***向量相减*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*/function sub(out, v1, v2) { out[0] = v1[0] - v2[0]; out[1] = v1[1] - v2[1]; return out;}/***向量长度*@param{Vector2}v*@return{number}*/function len(v) { return Math.sqrt(lenSquare(v));} //jshintignore:line/***向量长度平方*@param{Vector2}v*@return{number}*/function lenSquare(v) { return v[0] * v[0] + v[1] * v[1];}/***向量乘法*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*//***向量除法*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*//***向量点乘*@param{Vector2}v1*@param{Vector2}v2*@return{number}*//***向量缩放*@param{Vector2}out*@param{Vector2}v*@param{number}s*/function scale(out, v, s) { out[0] = v[0] * s; out[1] = v[1] * s; return out;}/***向量归一化*@param{Vector2}out*@param{Vector2}v*/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;}returnout;}/** * 计算向量间距离 * @param {Vector2} v1 * @param {Vector2} v2 * @return {number} */functiondistance(v1,v2){returnMath.sqrt((v1[0]-v2[0])*(v1[0]-v2[0])+(v1[1]-v2[1])*(v1[1]-v2[1]));}vardist=distance;/** * 向量距离平方 * @param {Vector2} v1 * @param {Vector2} v2 * @return {number} */functiondistanceSquare(v1,v2){return(v1[0]-v2[0])*(v1[0]-v2[0])+(v1[1]-v2[1])*(v1[1]-v2[1]);}vardistSquare=distanceSquare;/** * 求负向量 * @param {Vector2} out * @param {Vector2} v *//***插值两个点*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*@param{number}t*//***矩阵左乘向量*@param{Vector2}out*@param{Vector2}v*@param{Vector2}m*/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;}/***求两个向量最小值*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*/function min(out, v1, v2) { out[0] = Math.min(v1[0], v2[0]); out[1] = Math.min(v1[1], v2[1]); return out;}/***求两个向量最大值*@param{Vector2}out*@param{Vector2}v1*@param{Vector2}v2*/function max(out, v1, v2) { out[0] = Math.max(v1[0], v2[0]); out[1] = Math.max(v1[1], v2[1]); return out;}//TODODraggableforgroup// FIXME Draggable on element which has parent rotation or scalefunctionDraggable(){this.on('mousedown',this._dragStart,this);this.on('mousemove',this._drag,this);this.on('mouseup',this._dragEnd,this);this.on('globalout',this._dragEnd,this);// this._dropTarget = null;// this._draggingTarget = null;// this._x = 0;// this._y = 0;}Draggable.prototype={constructor:Draggable,_dragStart:function(e){vardraggingTarget=e.target;if(draggingTarget&&draggingTarget.draggable){this._draggingTarget=draggingTarget;draggingTarget.dragging=true;this._x=e.offsetX;this._y=e.offsetY;this.dispatchToElement(param(draggingTarget,e),'dragstart',e.event);}},_drag:function(e){vardraggingTarget=this._draggingTarget;if(draggingTarget){varx=e.offsetX;vary=e.offsetY;vardx=x-this._x;vardy=y-this._y;this._x=x;this._y=y;draggingTarget.drift(dx,dy,e);this.dispatchToElement(param(draggingTarget,e),'drag',e.event);vardropTarget=this.findHover(x,y,draggingTarget).target;varlastDropTarget=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(e){vardraggingTarget=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;}};functionparam(target,e){return{target:target,topTarget:e&&e.topTarget};}/** * Event Mixin * @module zrender/mixin/Eventful*@authorKener(@Kener-林峰,kener.linfeng@gmail.com)*pissang(https://www.github.com/pissang)*/var arrySlice = Array.prototype.slice;/***Eventdispatcher.**@aliasmodule:zrender/mixin/Eventful*@constructor*@param{Object}[eventProcessor]TheobjecteventProcessoristhescopewhen*`eventProcessor.xxx`called.*@param{Function}[eventProcessor.normalizeQuery]*param:{string|Object}Rawquery.*return:{string|Object}Normalizedquery.*@param{Function}[eventProcessor.filter]Eventwillbedispatchedonly*ifitreturns`true`.*param:{string}eventType*param:{string|Object}query*return:{boolean}*@param{Function}[eventProcessor.afterTrigger]Callafterallhandlerscalled.*param:{string}eventType*/var Eventful = function (eventProcessor) { this._$handlers = {}; this._$eventProcessor = eventProcessor;};Eventful.prototype = { constructor: Eventful, /***Thehandlercanonlybetriggeredonce,thenremoved.**@param{string}eventTheeventname.*@param{string|Object}[query]Conditionusedoneventfilter.*@param{Function}handlerTheeventhandler.*@param{Object}context*/ one: function (event, query, handler, context) { var _h = this._$handlers; if (typeof query === 'function') { context = handler; handler = query; query = null; } if (!handler || !event) { return this; } query = normalizeQuery(this, query); if (!_h[event]) { _h[event] = []; } for (var i = 0; i < _h[event].length; i++) { if (_h[event][i].h === handler) { return this; } } _h[event].push({ h: handler, one: true, query: query, ctx: context || this }); return this; }, /***Bindahandler.**@param{string}eventTheeventname.*@param{string|Object}[query]Conditionusedoneventfilter.*@param{Function}handlerTheeventhandler.*@param{Object}[context]*/ on: function (event, query, handler, context) { var _h = this._$handlers; if (typeof query === 'function') { context = handler; handler = query; query = null; } if (!handler || !event) { return this; } query = normalizeQuery(this, query); if (!_h[event]) { _h[event] = []; } for (var i = 0; i < _h[event].length; i++) { if (_h[event][i].h === handler) { return this; } } _h[event].push({ h: handler, one: false, query: query, ctx: context || this }); return this; }, /***Whetheranyhandlerhasbound.**@param{string}event*@return{boolean}*/ isSilent: function (event) { var _h = this._$handlers; return _h[event] && _h[event].length; }, /***Unbindaevent.**@param{string}eventTheeventname.*@param{Function}[handler]Theeventhandler.*/ off: function (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; }, /***Dispatchaevent.**@param{string}typeTheeventname.*/ trigger: function (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; } //Optimizeadvisefrombackboneswitch(argLen){case1:hItem.h.call(hItem.ctx);break;case2:hItem.h.call(hItem.ctx,args[1]);break;case3:hItem.h.call(hItem.ctx,args[1],args[2]);break;default:// have more than 2 given argumentshItem.h.apply(hItem.ctx,args);break;}if(hItem.one){_h.splice(i,1);len--;}else{i++;}}}eventProcessor&&eventProcessor.afterTrigger&&eventProcessor.afterTrigger(type);returnthis;},/** * Dispatch a event with context, which is specified at the last parameter. * * @param {string} type The event name. */triggerWithContext:function(type){var_h=this._$handlers[type];vareventProcessor=this._$eventProcessor;if(_h){varargs=arguments;varargLen=args.length;if(argLen>4){args=arrySlice.call(args,1,args.length-1);}varctx=args[args.length-1];varlen=_h.length;for(vari=0;i<len;){varhItem=_h[i];if(eventProcessor&&eventProcessor.filter&&hItem.query!=null&&!eventProcessor.filter(type,hItem.query)){i++;continue;}// Optimize advise from backboneswitch(argLen){case1:hItem.h.call(ctx);break;case2:hItem.h.call(ctx,args[1]);break;case3:hItem.h.call(ctx,args[1],args[2]);break;default:// have more than 2 given argumentshItem.h.apply(ctx,args);break;}if(hItem.one){_h.splice(i,1);len--;}else{i++;}}}eventProcessor&&eventProcessor.afterTrigger&&eventProcessor.afterTrigger(type);returnthis;}};functionnormalizeQuery(host,query){vareventProcessor=host._$eventProcessor;if(query!=null&&eventProcessor&&eventProcessor.normalizeQuery){query=eventProcessor.normalizeQuery(query);}returnquery;}/** * 事件辅助类 * @module zrender/core/event*@authorKener(@Kener-林峰,kener.linfeng@gmail.com)*/var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;functiongetBoundingClientRect(el){// BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRectreturnel.getBoundingClientRect?el.getBoundingClientRect():{left:0,top:0};}// `calculate` is optional, default falsefunctionclientToLocal(el,e,out,calculate){out=out||{};// According to the W3C Working Draft, offsetX and offsetY should be relative// to the padding edge of the target element. The only browser using this convention// is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does// not support the properties.// (see http://www.jacklmoore.com/notes/mouse-position/)// In zr painter.dom, padding edge equals to border edge.// FIXME// When mousemove event triggered on ec tooltip, target is not zr painter.dom, and// offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y// is too complex. So css-transfrom dont support in this case temporarily.if(calculate||!env$1.canvasSupported){defaultGetZrXY(el,e,out);}// Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned// ancestor element, so we should make sure el is positioned (e.g., not position:static).// BTW1, Webkit don't return the same results as FF in non-simple cases (like add// zoom-factor, overflow / opacity layers, transforms ...)// BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.// <https://bugs.jquery.com/ticket/8523#comment:14>// BTW3, In ff, offsetX/offsetY is always 0.elseif(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?)elseif(e.offsetX!=null){out.zrX=e.offsetX;out.zrY=e.offsetY;}// For some other device, e.g., IOS safari.else{defaultGetZrXY(el,e,out);}returnout;}functiondefaultGetZrXY(el,e,out){// This well-known method below does not support css transform.varbox=getBoundingClientRect(el);out.zrX=e.clientX-box.left;out.zrY=e.clientY-box.top;}/** * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标. * `calculate` is optional, default false. */functionnormalizeEvent(el,e,calculate){e=e||window.event;if(e.zrX!=null){returne;}vareventType=e.type;varisTouch=eventType&&eventType.indexOf('touch')>=0;if(!isTouch){clientToLocal(el,e,e,calculate);e.zrDelta=(e.wheelDelta)?e.wheelDelta/120:-(e.detail||0)/3;}else{vartouch=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;// See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js// If e.which has been defined, if may be readonly,// see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/whichvarbutton=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)));}returne;}/** * @param {HTMLElement} el * @param {string} name * @param {Function} handler */functionaddEventListener(el,name,handler){if(isDomLevel2){// Reproduct the console warning:// [Violation] Added non-passive event listener to a scroll-blocking <some> event.// Consider marking event handler as 'passive' to make the page more responsive.// Just set console log level: verbose in chrome dev tool.// then the warning log will be printed when addEventListener called.// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md// We have not yet found a neat way to using passive. Because in zrender the dom event// listener delegate all of the upper events of element. Some of those events need// to prevent default. For example, the feature `preventDefaultMouseMove` of echarts.// Before passive can be adopted, these issues should be considered:// (1) Whether and how a zrender user specifies an event listener passive. And by default,// passive or not.// (2) How to tread that some zrender event listener is passive, and some is not. If// we use other way but not preventDefault of mousewheel and touchmove, browser// compatibility should be handled.// var opts = (env.passiveSupported && name === 'mousewheel')// ? {passive: true}// // By default, the third param of el.addEventListener is `capture: false`.// : void 0;// el.addEventListener(name, handler /* , opts */);el.addEventListener(name,handler);}else{el.attachEvent('on'+name,handler);}}functionremoveEventListener(el,name,handler){if(isDomLevel2){el.removeEventListener(name,handler);}else{el.detachEvent('on'+name,handler);}}/** * preventDefault and stopPropagation. * Notice: do not do that in zrender. Upper application * do that if necessary. * * @memberOf module:zrender/core/event*@method*@param{Event}e:event对象*/var stop = isDomLevel2? function (e) { e.preventDefault(); e.stopPropagation(); e.cancelBubble = true; } : function (e) { e.returnValue = false; e.cancelBubble = true; };var SILENT = 'silent';function makeEventPacket(eveType, targetInfo, event) { return { type: eveType, event: event, //targetcanonlybeanelementthatisnotsilent.target:targetInfo.target,// topTarget can be a silent element.topTarget:targetInfo.topTarget,cancelBubble:false,offsetX:event.zrX,offsetY:event.zrY,gestureEvent:event.gestureEvent,pinchX:event.pinchX,pinchY:event.pinchY,pinchScale:event.pinchScale,wheelDelta:event.zrDelta,zrByTouch:event.zrByTouch,which:event.which,stop:stopEvent};}functionstopEvent(event){stop(this.event);}functionEmptyProxy(){}EmptyProxy.prototype.dispose=function(){};varhandlerNames=['click','dblclick','mousewheel','mouseout','mouseup','mousedown','mousemove','contextmenu'];/** * @alias module:zrender/Handler*@constructor*@extendsmodule:zrender/mixin/Eventful*@param{module:zrender/Storage}storageStorageinstance.*@param{module:zrender/Painter}painterPainterinstance.*@param{module:zrender/dom/HandlerProxy}proxyHandlerProxyinstance.*@param{HTMLElement}painterRootpainter.root(notpainter.getViewportRoot()).*/var Handler = function(storage, painter, proxy, painterRoot) { Eventful.call(this); this.storage = storage; this.painter = painter; this.painterRoot = painterRoot; proxy = proxy || new EmptyProxy(); /***Proxyofevent.canbeDom,WebGLSurface,etc.*/ this.proxy = null; /***{target,topTarget,x,y}*@private*@type{Object}*/ this._hovered = {}; /***@private*@type{Date}*/ this._lastTouchMoment; /***@private*@type{number}*/ this._lastX; /***@private*@type{number}*/ this._lastY; Draggable.call(this); this.setHandlerProxy(proxy);};Handler.prototype = { constructor: Handler, setHandlerProxy: function (proxy) { if (this.proxy) { this.proxy.dispose(); } if (proxy) { each$1(handlerNames, function (name) { proxy.on && proxy.on(name, this[name], this); }, this); //Attachhandlerproxy.handler=this;}this.proxy=proxy;},mousemove:function(event){varx=event.zrX;vary=event.zrY;varlastHovered=this._hovered;varlastHoveredTarget=lastHovered.target;// If lastHoveredTarget is removed from zr (detected by '__zr') by some API call// (like 'setOption' or 'dispatchAction') in event handlers, we should find// lastHovered again here. Otherwise 'mouseout' can not be triggered normally.// See #6198.if(lastHoveredTarget&&!lastHoveredTarget.__zr){lastHovered=this.findHover(lastHovered.x,lastHovered.y);lastHoveredTarget=lastHovered.target;}varhovered=this._hovered=this.findHover(x,y);varhoveredTarget=hovered.target;varproxy=this.proxy;proxy.setCursor&&proxy.setCursor(hoveredTarget?hoveredTarget.cursor:'default');// Mouse out on previous hovered elementif(lastHoveredTarget&&hoveredTarget!==lastHoveredTarget){this.dispatchToElement(lastHovered,'mouseout',event);}// Mouse moving on one elementthis.dispatchToElement(hovered,'mousemove',event);// Mouse over on a new elementif(hoveredTarget&&hoveredTarget!==lastHoveredTarget){this.dispatchToElement(hovered,'mouseover',event);}},mouseout:function(event){this.dispatchToElement(this._hovered,'mouseout',event);// There might be some doms created by upper layer application// at the same level of painter.getViewportRoot() (e.g., tooltip// dom created by echarts), where 'globalout' event should not// be triggered when mouse enters these doms. (But 'mouseout'// should be triggered at the original hovered element as usual).varelement=event.toElement||event.relatedTarget;varinnerDom;do{element=element&&element.parentNode;}while(element&&element.nodeType!=9&&!(innerDom=element===this.painterRoot));!innerDom&&this.trigger('globalout',{event:event});},/** * Resize */resize:function(event){this._hovered={};},/** * Dispatch event * @param {string} eventName * @param {event=} eventArgs */dispatch:function(eventName,eventArgs){varhandler=this[eventName];handler&&handler.call(this,eventArgs);},/** * Dispose */dispose:function(){this.proxy.dispose();this.storage=this.proxy=this.painter=null;},/** * 设置默认的cursor style * @param {string} [cursorStyle='default'] 例如 crosshair */setCursorStyle:function(cursorStyle){varproxy=this.proxy;proxy.setCursor&&proxy.setCursor(cursorStyle);},/** * 事件分发代理 * * @private * @param {Object} targetInfo {target, topTarget} 目标图形元素 * @param {string} eventName 事件名称 * @param {Object} event 事件对象 */dispatchToElement:function(targetInfo,eventName,event){targetInfo=targetInfo||{};varel=targetInfo.target;if(el&&el.silent){return;}vareventHandler='on'+eventName;vareventPacket=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 对象this.trigger(eventName,eventPacket);// 分发事件到用户自定义层// 用户有可能在全局 click 事件中 dispose,所以需要判断下 painter 是否存在this.painter&&this.painter.eachOtherLayer(function(layer){if(typeof(layer[eventHandler])=='function'){layer[eventHandler].call(layer,eventPacket);}if(layer.trigger){layer.trigger(eventName,eventPacket);}});}},/** * @private * @param {number} x * @param {number} y * @param {module:zrender/graphic/Displayable}exclude*@return{model:zrender/Element}*@method*/ findHover: function(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 //getDisplayListmayincludeignorediteminVMLmode&&!list[i].ignore&&(hoverCheckResult=isHover(list[i],x,y))){!out.topTarget&&(out.topTarget=list[i]);if(hoverCheckResult!==SILENT){out.target=list[i];break;}}}returnout;}};// Common handlerseach$1(['click','mousedown','mouseup','mousewheel','dblclick','contextmenu'],function(name){Handler.prototype[name]=function(event){// Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseovervarhovered=this.findHover(event.zrX,event.zrY);varhoveredTarget=hovered.target;if(name==='mousedown'){this._downEl=hoveredTarget;this._downPoint=[event.zrX,event.zrY];// In case click triggered before mouseupthis._upEl=hoveredTarget;}elseif(name==='mouseup'){this._upEl=hoveredTarget;}elseif(name==='click'){if(this._downEl!==this._upEl// Original click event is triggered on the whole canvas element,// including the case that `mousedown` - `mousemove` - `mouseup`,// which should be filtered, otherwise it will bring trouble to// pan and zoom.||!this._downPoint// Arbitrary value||dist(this._downPoint,[event.zrX,event.zrY])>4){return;}this._downPoint=null;}this.dispatchToElement(hovered,name,event);};});functionisHover(displayable,x,y){if(displayable[displayable.rectHover?'rectContain':'contain'](x,y)){varel=displayable;varisSilent;while(el){// If clipped by ancestor.// FIXME: If clipPath has neither stroke nor fill,// el.clipPath.contain(x, y) will always return false.if(el.clipPath&&!el.clipPath.contain(x,y)){returnfalse;}if(el.silent){isSilent=true;}el=el.parent;}returnisSilent?SILENT:true;}returnfalse;}mixin(Handler,Eventful);mixin(Handler,Draggable);/** * 3x2矩阵操作类 * @exports zrender/tool/matrix*/var ArrayCtor$1 = typeof Float32Array === 'undefined'? Array : Float32Array;/***Createaidentitymatrix.*@return{Float32Array|Array.<number>}*/function create$1() { var out = new ArrayCtor$1(6); identity(out); return out;}/***设置矩阵为单位矩阵*@param{Float32Array|Array.<number>}out*/function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out;}/***复制矩阵*@param{Float32Array|Array.<number>}out*@param{Float32Array|Array.<number>}m*/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;}/***矩阵相乘*@param{Float32Array|Array.<number>}out*@param{Float32Array|Array.<number>}m1*@param{Float32Array|Array.<number>}m2*/function mul$1(out, m1, m2) { //Considermatrix.mul(m,m2,m);// where out is the same as m2.// So use temp variable to escape error.varout0=m1[0]*m2[0]+m1[2]*m2[1];varout1=m1[1]*m2[0]+m1[3]*m2[1];varout2=m1[0]*m2[2]+m1[2]*m2[3];varout3=m1[1]*m2[2]+m1[3]*m2[3];varout4=m1[0]*m2[4]+m1[2]*m2[5]+m1[4];varout5=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;returnout;}/** * 平移变换 * @param {Float32Array|Array.<number>} out * @param {Float32Array|Array.<number>} a * @param {Float32Array|Array.<number>} v */functiontranslate(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];returnout;}/** * 旋转变换 * @param {Float32Array|Array.<number>} out * @param {Float32Array|Array.<number>} a * @param {number} rad */functionrotate(out,a,rad){varaa=a[0];varac=a[2];varatx=a[4];varab=a[1];varad=a[3];varaty=a[5];varst=Math.sin(rad);varct=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;returnout;}/** * 缩放变换 * @param {Float32Array|Array.<number>} out * @param {Float32Array|Array.<number>} a * @param {Float32Array|Array.<number>} v */functionscale$1(out,a,v){varvx=v[0];varvy=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;returnout;}/** * 求逆矩阵 * @param {Float32Array|Array.<number>} out * @param {Float32Array|Array.<number>} a */functioninvert(out,a){varaa=a[0];varac=a[2];varatx=a[4];varab=a[1];varad=a[3];varaty=a[5];vardet=aa*ad-ab*ac;if(!det){returnnull;}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;returnout;}/** * Clone a new matrix. * @param {Float32Array|Array.<number>} a *//***提供变换扩展*@modulezrender/mixin/Transformable*@authorpissang(https://www.github.com/pissang)*/var mIdentity = identity;var EPSILON = 5e-5;function isNotAroundZero(val) { return val > EPSILON || val < -EPSILON;}/***@aliasmodule:zrender/mixin/Transformable*@constructor*/var Transformable = function (opts) { opts = opts || {}; //Iftherearenogivenposition,rotation,scaleif(!opts.position){/** * 平移 * @type {Array.<number>} * @default [0, 0] */this.position=[0,0];}if(opts.rotation==null){/** * 旋转 * @type {Array.<number>} * @default 0 */this.rotation=0;}if(!opts.scale){/** * 缩放 * @type {Array.<number>} * @default [1, 1] */this.scale=[1,1];}/** * 旋转和缩放的原点 * @type {Array.<number>} * @default null */this.origin=this.origin||null;};vartransformableProto=Transformable.prototype;transformableProto.transform=null;/** * 判断是否需要有坐标变换 * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵 */transformableProto.needLocalTransform=function(){returnisNotAroundZero(this.rotation)||isNotAroundZero(this.position[0])||isNotAroundZero(this.position[1])||isNotAroundZero(this.scale[0]-1)||isNotAroundZero(this.scale[1]-1);};varscaleTmp=[];transformableProto.updateTransform=function(){varparent=this.parent;varparentHasTransform=parent&&parent.transform;varneedLocalTransform=this.needLocalTransform();varm=this.transform;if(!(needLocalTransform||parentHasTransform)){m&&mIdentity(m);return;}m=m||create$1();if(needLocalTransform){this.getLocalTransform(m);}else{mIdentity(m);}// 应用父节点变换if(parentHasTransform){if(needLocalTransform){mul$1(m,parent.transform,m);}else{copy$1(m,parent.transform);}}// 保存这个变换矩阵this.transform=m;varglobalScaleRatio=this.globalScaleRatio;if(globalScaleRatio!=null&&globalScaleRatio!==1){this.getGlobalScale(scaleTmp);varrelX=scaleTmp[0]<0?-1:1;varrelY=scaleTmp[1]<0?-1:1;varsx=((scaleTmp[0]-relX)*globalScaleRatio+relX)/scaleTmp[0]||0;varsy=((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){returnTransformable.getLocalTransform(this,m);};/** * 将自己的transform应用到context上 * @param {CanvasRenderingContext2D} ctx */transformableProto.setTransform=function(ctx){varm=this.transform;vardpr=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){vardpr=ctx.dpr||1;ctx.setTransform(dpr,0,0,dpr,0,0);};vartmpTransform=[];varoriginTransform=create$1();transformableProto.setLocalTransform=function(m){if(!m){// TODO return or set identity?return;}varsx=m[0]*m[0]+m[1]*m[1];varsy=m[2]*m[2]+m[3]*m[3];varposition=this.position;varscale$$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);};/** * 分解`transform`矩阵到`position`, `rotation`, `scale` */transformableProto.decomposeTransform=function(){if(!this.transform){return;}varparent=this.parent;varm=this.transform;if(parent&&parent.transform){// Get local transform and decompose them to position, scale, rotationmul$1(tmpTransform,parent.invTransform,m);m=tmpTransform;}varorigin=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);};/** * Get global scale * @return {Array.<number>} */transformableProto.getGlobalScale=function(out){varm=this.transform;out=out||[];if(!m){out[0]=1;out[1]=1;returnout;}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];}returnout;};/** * 变换坐标位置到 shape 的局部坐标空间 * @method * @param {number} x * @param {number} y * @return {Array.<number>} */transformableProto.transformCoordToLocal=function(x,y){varv2=[x,y];varinvTransform=this.invTransform;if(invTransform){applyTransform(v2,v2,invTransform);}returnv2;};/** * 变换局部坐标位置到全局坐标空间 * @method * @param {number} x * @param {number} y * @return {Array.<number>} */transformableProto.transformCoordToGlobal=function(x,y){varv2=[x,y];vartransform=this.transform;if(transform){applyTransform(v2,v2,transform);}returnv2;};/** * @static * @param {Object} target * @param {Array.<number>} target.origin * @param {number} target.rotation * @param {Array.<number>} target.position * @param {Array.<number>} [m] */Transformable.getLocalTransform=function(target,m){m=m||[];mIdentity(m);varorigin=target.origin;varscale$$1=target.scale||[1,1];varrotation=target.rotation||0;varposition=target.position||[0,0];if(origin){// Translate to originm[4]-=origin[0];m[5]-=origin[1];}scale$1(m,m,scale$$1);if(rotation){rotate(m,m,rotation);}if(origin){// Translate back from originm[4]+=origin[0];m[5]+=origin[1];}m[4]+=position[0];m[5]+=position[1];returnm;};/** * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js*@seehttp://sole.github.io/tween.js/examples/03_graphs.html*@exportszrender/animation/easing*/var easing = { /***@param{number}k*@return{number}*/ linear: function (k) { return k; }, /***@param{number}k*@return{number}*/ quadraticIn: function (k) { return k * k; }, /***@param{number}k*@return{number}*/ quadraticOut: function (k) { return k * (2 - k); }, /***@param{number}k*@return{number}*/ quadraticInOut: function (k) { if ((k *= 2) < 1) { return 0.5 * k * k; } return -0.5 * (--k * (k - 2) - 1); }, //三次方的缓动(t^3)/***@param{number}k*@return{number}*/ cubicIn: function (k) { return k * k * k; }, /***@param{number}k*@return{number}*/ cubicOut: function (k) { return --k * k * k + 1; }, /***@param{number}k*@return{number}*/ cubicInOut: function (k) { if ((k *= 2) < 1) { return 0.5 * k * k * k; } return 0.5 * ((k -= 2) * k * k + 2); }, //四次方的缓动(t^4)/***@param{number}k*@return{number}*/ quarticIn: function (k) { return k * k * k * k; }, /***@param{number}k*@return{number}*/ quarticOut: function (k) { return 1 - (--k * k * k * k); }, /***@param{number}k*@return{number}*/ quarticInOut: function (k) { if ((k *= 2) < 1) { return 0.5 * k * k * k * k; } return -0.5 * ((k -= 2) * k * k * k - 2); }, //五次方的缓动(t^5)/***@param{number}k*@return{number}*/ quinticIn: function (k) { return k * k * k * k * k; }, /***@param{number}k*@return{number}*/ quinticOut: function (k) { return --k * k * k * k * k + 1; }, /***@param{number}k*@return{number}*/ quinticInOut: function (k) { if ((k *= 2) < 1) { return 0.5 * k * k * k * k * k; } return 0.5 * ((k -= 2) * k * k * k * k + 2); }, //正弦曲线的缓动(sin(t))/***@param{number}k*@return{number}*/ sinusoidalIn: function (k) { return 1 - Math.cos(k * Math.PI /2);},/** * @param {number} k * @return {number} */sinusoidalOut:function(k){returnMath.sin(k*Math.PI/2);},/** * @param {number} k * @return {number} */sinusoidalInOut:function(k){return0.5*(1-Math.cos(Math.PI*k));},// 指数曲线的缓动(2^t)/** * @param {number} k * @return {number} */exponentialIn:function(k){returnk===0?0:Math.pow(1024,k-1);},/** * @param {number} k * @return {number} */exponentialOut:function(k){returnk===1?1:1-Math.pow(2,-10*k);},/** * @param {number} k * @return {number} */exponentialInOut:function(k){if(k===0){return0;}if(k===1){return1;}if((k*=2)<1){return0.5*Math.pow(1024,k-1);}return0.5*(-Math.pow(2,-10*(k-1))+2);},// 圆形曲线的缓动(sqrt(1-t^2))/** * @param {number} k * @return {number} */circularIn:function(k){return1-Math.sqrt(1-k*k);},/** * @param {number} k * @return {number} */circularOut:function(k){returnMath.sqrt(1-(--k*k));},/** * @param {number} k * @return {number} */circularInOut:function(k){if((k*=2)<1){return-0.5*(Math.sqrt(1-k*k)-1);}return0.5*(Math.sqrt(1-(k-=2)*k)+1);},// 创建类似于弹簧在停止前来回振荡的动画/** * @param {number} k * @return {number} */elasticIn:function(k){vars;vara=0.1;varp=0.4;if(k===0){return0;}if(k===1){return1;}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));},/** * @param {number} k * @return {number} */elasticOut:function(k){vars;vara=0.1;varp=0.4;if(k===0){return0;}if(k===1){return1;}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);},/** * @param {number} k * @return {number} */elasticInOut:function(k){vars;vara=0.1;varp=0.4;if(k===0){return0;}if(k===1){return1;}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));}returna*Math.pow(2,-10*(k-=1))*Math.sin((k-s)*(2*Math.PI)/p)*0.5+1;},// 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动/** * @param {number} k * @return {number} */backIn:function(k){vars=1.70158;returnk*k*((s+1)*k-s);},/** * @param {number} k * @return {number} */backOut:function(k){vars=1.70158;return--k*k*((s+1)*k+s)+1;},/** * @param {number} k * @return {number} */backInOut:function(k){vars=1.70158*1.525;if((k*=2)<1){return0.5*(k*k*((s+1)*k-s));}return0.5*((k-=2)*k*((s+1)*k+s)+2);},// 创建弹跳效果/** * @param {number} k * @return {number} */bounceIn:function(k){return1-easing.bounceOut(1-k);},/** * @param {number} k * @return {number} */bounceOut:function(k){if(k<(1/2.75)){return7.5625*k*k;}elseif(k<(2/2.75)){return7.5625*(k-=(1.5/2.75))*k+0.75;}elseif(k<(2.5/2.75)){return7.5625*(k-=(2.25/2.75))*k+0.9375;}else{return7.5625*(k-=(2.625/2.75))*k+0.984375;}},/** * @param {number} k * @return {number} */bounceInOut:function(k){if(k<0.5){returneasing.bounceIn(k*2)*0.5;}returneasing.bounceOut(k*2-1)*0.5+0.5;}};/** * 动画主控制器 * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件 * @config life(1000) 动画时长 * @config delay(0) 动画延迟时间 * @config loop(true) * @config gap(0) 循环的间隔时间 * @config onframe * @config easing(optional) * @config ondestroy(optional) * @config onrestart(optional) * * TODO pause */functionClip(options){this._target=options.target;// 生命周期this._life=options.life||1000;// 延时this._delay=options.delay||0;// 开始时间// this._startTime = new Date().getTime() + this._delay;// 单位毫秒this._initialized=false;// 是否循环this.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(globalTime,deltaTime){// Set startTime on first step, or _startTime may has milleseconds different between clips// PENDINGif(!this._initialized){this._startTime=globalTime+this._delay;this._initialized=true;}if(this._paused){this._pausedTime+=deltaTime;return;}varpercent=(globalTime-this._startTime-this._pausedTime)/this._life;// 还没开始if(percent<0){return;}percent=Math.min(percent,1);vareasing$$1=this.easing;vareasingFunc=typeofeasing$$1=='string'?easing[easing$$1]:easing$$1;varschedule=typeofeasingFunc==='function'?easingFunc(percent):percent;this.fire('frame',schedule);// 结束if(percent==1){if(this.loop){this.restart(globalTime);// 重新开始周期// 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件return'restart';}// 动画完成将这个控制器标识为待删除// 在Animation.update中进行批量删除this._needsRemove=true;return'destroy';}returnnull;},restart:function(globalTime){varremainder=(globalTime-this._startTime-this._pausedTime)%this._life;this._startTime=globalTime-remainder+this.gap;this._pausedTime=0;this._needsRemove=false;},fire:function(eventType,arg){eventType='on'+eventType;if(this[eventType]){this[eventType](this._target,arg);}},pause:function(){this._paused=true;},resume:function(){this._paused=false;}};// Simple LRU cache use doubly linked list// @module zrender/core/LRU/** * Simple double linked list. Compared with array, it has O(1) remove operation. * @constructor */varLinkedList=function(){/** * @type {module:zrender/core/LRU~Entry}*/ this.head = null; /***@type{module:zrender/core/LRU~Entry}*/ this.tail = null; this._len = 0;};var linkedListProto = LinkedList.prototype;/***Insertanewvalueatthetail*@param{}val*@return{module:zrender/core/LRU~Entry}*/linkedListProto.insert = function (val) { var entry = new Entry(val); this.insertEntry(entry); return entry;};/***Insertanentryatthetail*@param{module:zrender/core/LRU~Entry}entry*/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++;};/***Removeentry.*@param{module:zrender/core/LRU~Entry}entry*/linkedListProto.remove = function (entry) { var prev = entry.prev; var next = entry.next; if (prev) { prev.next = next; } else { //Isheadthis.head=next;}if(next){next.prev=prev;}else{// Is tailthis.tail=prev;}entry.next=entry.prev=null;this._len--;};/** * @return {number} */linkedListProto.len=function(){returnthis._len;};/** * Clear list */linkedListProto.clear=function(){this.head=this.tail=null;this._len=0;};/** * @constructor * @param {} val */varEntry=function(val){/** * @type {} */this.value=val;/** * @type {module:zrender/core/LRU~Entry}*/ this.next; /***@type{module:zrender/core/LRU~Entry}*/ this.prev;};/***LRUCache*@constructor*@aliasmodule:zrender/core/LRU*/var LRU = function (maxSize) { this._list = new LinkedList(); this._map = {}; this._maxSize = maxSize || 10; this._lastRemovedEntry = null;};var LRUProto = LRU.prototype;/***@param{string}key*@param{}value*@return{}Removedvalue*/LRUProto.put = function (key, value) { var list = this._list; var map = this._map; var removed = null; if (map[key] == null) { var len = list.len(); //Reuselastremovedentryvarentry=this._lastRemovedEntry;if(len>=this._maxSize&&len>0){// Remove the least recently usedvarleastUsedEntry=list.head;list.remove(leastUsedEntry);deletemap[leastUsedEntry.key];removed=leastUsedEntry.value;this._lastRemovedEntry=leastUsedEntry;}if(entry){entry.value=value;}else{entry=newEntry(value);}entry.key=key;list.insertEntry(entry);map[key]=entry;}returnremoved;};/** * @param {string} key * @return {} */LRUProto.get=function(key){varentry=this._map[key];varlist=this._list;if(entry!=null){// Put the latest used entry in the tailif(entry!==list.tail){list.remove(entry);list.insertEntry(entry);}returnentry.value;}};/** * Clear the cache */LRUProto.clear=function(){this._list.clear();this._map={};};varkCSSColorTable={'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]};functionclampCssByte(i){// Clamp to integer 0 .. 255.i=Math.round(i);// Seems to be what Chrome does (vs truncation).returni<0?0:i>255?255:i;}functionclampCssFloat(f){// Clamp to float 0.0 .. 1.0.returnf<0?0:f>1?1:f;}functionparseCssInt(str){// int or percentage.if(str.length&&str.charAt(str.length-1)==='%'){returnclampCssByte(parseFloat(str)/100*255);}returnclampCssByte(parseInt(str,10));}functionparseCssFloat(str){// float or percentage.if(str.length&&str.charAt(str.length-1)==='%'){returnclampCssFloat(parseFloat(str)/100);}returnclampCssFloat(parseFloat(str));}functioncssHueToRgb(m1,m2,h){if(h<0){h+=1;}elseif(h>1){h-=1;}if(h*6<1){returnm1+(m2-m1)*h*6;}if(h*2<1){returnm2;}if(h*3<2){returnm1+(m2-m1)*(2/3-h)*6;}returnm1;}functionsetRgba(out,r,g,b,a){out[0]=r;out[1]=g;out[2]=b;out[3]=a;returnout;}functioncopyRgba(out,a){out[0]=a[0];out[1]=a[1];out[2]=a[2];out[3]=a[3];returnout;}varcolorCache=newLRU(20);varlastRemovedArr=null;functionputToCache(colorStr,rgbaArr){// Reuse removed arrayif(lastRemovedArr){copyRgba(lastRemovedArr,rgbaArr);}lastRemovedArr=colorCache.put(colorStr,lastRemovedArr||(rgbaArr.slice()));}/** * @param {string} colorStr * @param {Array.<number>} out * @return {Array.<number>} * @memberOf module:zrender/util/color*/function parse(colorStr, rgbaArr) { if (!colorStr) { return; } rgbaArr = rgbaArr || []; var cached = colorCache.get(colorStr); if (cached) { return copyRgba(rgbaArr, cached); } //colorStrmaybenotstringcolorStr=colorStr+'';// Remove all whitespace, not compliant, but should just be more accepting.varstr=colorStr.replace(/ /g,'').toLowerCase();// Color keywords (and transparent) lookup.if(strinkCSSColorTable){copyRgba(rgbaArr,kCSSColorTable[str]);putToCache(colorStr,rgbaArr);returnrgbaArr;}// #abc and #abc123 syntax.if(str.charAt(0)==='#'){if(str.length===4){variv=parseInt(str.substr(1),16);// TODO(deanm): Stricter parsing.if(!(iv>=0&&iv<=0xfff)){setRgba(rgbaArr,0,0,0,1);return;// Covers NaN.}setRgba(rgbaArr,((iv&0xf00)>>4)|((iv&0xf00)>>8),(iv&0xf0)|((iv&0xf0)>>4),(iv&0xf)|((iv&0xf)<<4),1);putToCache(colorStr,rgbaArr);returnrgbaArr;}elseif(str.length===7){variv=parseInt(str.substr(1),16);// TODO(deanm): Stricter parsing.if(!(iv>=0&&iv<=0xffffff)){setRgba(rgbaArr,0,0,0,1);return;// Covers NaN.}setRgba(rgbaArr,(iv&0xff0000)>>16,(iv&0xff00)>>8,iv&0xff,1);putToCache(colorStr,rgbaArr);returnrgbaArr;}return;}varop=str.indexOf('('),ep=str.indexOf(')');if(op!==-1&&ep+1===str.length){varfname=str.substr(0,op);varparams=str.substr(op+1,ep-(op+1)).split(',');varalpha=1;// To allow case fallthrough.switch(fname){case'rgba':if(params.length!==4){setRgba(rgbaArr,0,0,0,1);return;}alpha=parseCssFloat(params.pop());// jshint ignore:line// Fall through.case'rgb':if(params.length!==3){setRgba(rgbaArr,0,0,0,1);return;}setRgba(rgbaArr,parseCssInt(params[0]),parseCssInt(params[1]),parseCssInt(params[2]),alpha);putToCache(colorStr,rgbaArr);returnrgbaArr;case'hsla':if(params.length!==4){setRgba(rgbaArr,0,0,0,1);return;}params[3]=parseCssFloat(params[3]);hsla2rgba(params,rgbaArr);putToCache(colorStr,rgbaArr);returnrgbaArr;case'hsl':if(params.length!==3){setRgba(rgbaArr,0,0,0,1);return;}hsla2rgba(params,rgbaArr);putToCache(colorStr,rgbaArr);returnrgbaArr;default:return;}}setRgba(rgbaArr,0,0,0,1);return;}/** * @param {Array.<number>} hsla * @param {Array.<number>} rgba * @return {Array.<number>} rgba */functionhsla2rgba(hsla,rgba){varh=(((parseFloat(hsla[0])%360)+360)%360)/360;// 0 .. 1// NOTE(deanm): According to the CSS spec s/l should only be// percentages, but we don't bother and let float or percentage.vars=parseCssFloat(hsla[1]);varl=parseCssFloat(hsla[2]);varm2=l<=0.5?l*(s+1):l+s-l*s;varm1=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];}returnrgba;}/** * @param {string} color * @param {number} level * @return {string} * @memberOf module:zrender/util/color*/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'); }}/***@param{string}color*@return{string}*@memberOfmodule:zrender/util/color*//***Mapvaluetocolor.Fasterthanlerpmethodsbecausecolorisrepresentedbyrgbaarray.*@param{number}normalizedValueAfloatbetween0and1.*@param{Array.<Array.<number>>}colorsListofrgbacolorarray*@param{Array.<number>}[out]Mappedgbacolorarray*@return{Array.<number>}willbenull/undefinedifinputillegal.*//***@deprecated*//***@param{number}normalizedValueAfloatbetween0and1.*@param{Array.<string>}colorsColorlist.*@param{boolean=}fullOutputDefaultfalse.*@return{(string|Object)}Resultcolor.IffullOutput,*return{color:...,leftIndex:...,rightIndex:...,value:...},*@memberOfmodule:zrender/util/color*//***@deprecated*//***@param{string}color*@param{number=}h0~360,ignorewhennull.*@param{number=}s0~1,ignorewhennull.*@param{number=}l0~1,ignorewhennull.*@return{string}Colorstringinrgbaformat.*@memberOfmodule:zrender/util/color*//***@param{string}color*@param{number=}alpha0~1*@return{string}Colorstringinrgbaformat.*@memberOfmodule:zrender/util/color*//***@param{Array.<number>}arrColorlike[12,33,44,0.4]*@param{string}type'rgba','hsva',...*@return{string}Resultcolor.(Ifinputillegal,returnundefined).*/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 + ')';}/***@moduleecharts/animation/Animator*/var arraySlice = Array.prototype.slice;function defaultGetter(target, key) { return target[key];}function defaultSetter(target, key, value) { target[key] = value;}/***@param{number}p0*@param{number}p1*@param{number}percent*@return{number}*/function interpolateNumber(p0, p1, percent) { return (p1 - p0) * percent + p0;}/***@param{string}p0*@param{string}p1*@param{number}percent*@return{string}*/function interpolateString(p0, p1, percent) { return percent > 0.5 ? p1 : p0;}/***@param{Array}p0*@param{Array}p1*@param{number}percent*@param{Array}out*@param{number}arrDim*/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); } } }}//arr0issourcearray,arr1istargetarray.// Do some preprocess to avoid error happened when interpolating from arr0 to arr1functionfillArr(arr0,arr1,arrDim){vararr0Len=arr0.length;vararr1Len=arr1.length;if(arr0Len!==arr1Len){// FIXME Not work for TypedArrayvarisPreviousLarger=arr0Len>arr1Len;if(isPreviousLarger){// Cut the previousarr0.length=arr1Len;}else{// Fill the previousfor(vari=arr0Len;i<arr1Len;i++){arr0.push(arrDim===1?arr1[i]:arraySlice.call(arr1[i]));}}}// Handling NaN valuevarlen2=arr0[0]&&arr0[0].length;for(vari=0;i<arr0.length;i++){if(arrDim===1){if(isNaN(arr0[i])){arr0[i]=arr1[i];}}else{for(varj=0;j<len2;j++){if(isNaN(arr0[i][j])){arr0[i][j]=arr1[i][j];}}}}}/** * @param {Array} arr0 * @param {Array} arr1 * @param {number} arrDim * @return {boolean} */functionisArraySame(arr0,arr1,arrDim){if(arr0===arr1){returntrue;}varlen=arr0.length;if(len!==arr1.length){returnfalse;}if(arrDim===1){for(vari=0;i<len;i++){if(arr0[i]!==arr1[i]){returnfalse;}}}else{varlen2=arr0[0].length;for(vari=0;i<len;i++){for(varj=0;j<len2;j++){if(arr0[i][j]!==arr1[i][j]){returnfalse;}}}}returntrue;}/** * Catmull Rom interpolate array * @param {Array} p0 * @param {Array} p1 * @param {Array} p2 * @param {Array} p3 * @param {number} t * @param {number} t2 * @param {number} t3 * @param {Array} out * @param {number} arrDim */functioncatmullRomInterpolateArray(p0,p1,p2,p3,t,t2,t3,out,arrDim){varlen=p0.length;if(arrDim==1){for(vari=0;i<len;i++){out[i]=catmullRomInterpolate(p0[i],p1[i],p2[i],p3[i],t,t2,t3);}}else{varlen2=p0[0].length;for(vari=0;i<len;i++){for(varj=0;j<len2;j++){out[i][j]=catmullRomInterpolate(p0[i][j],p1[i][j],p2[i][j],p3[i][j],t,t2,t3);}}}}/** * Catmull Rom interpolate number * @param {number} p0 * @param {number} p1 * @param {number} p2 * @param {number} p3 * @param {number} t * @param {number} t2 * @param {number} t3 * @return {number} */functioncatmullRomInterpolate(p0,p1,p2,p3,t,t2,t3){varv0=(p2-p0)*0.5;varv1=(p3-p1)*0.5;return(2*(p1-p2)+v0+v1)*t3+(-3*(p1-p2)-2*v0-v1)*t2+v0*t+p1;}functioncloneValue(value){if(isArrayLike(value)){varlen=value.length;if(isArrayLike(value[0])){varret=[];for(vari=0;i<len;i++){ret.push(arraySlice.call(value[i]));}returnret;}returnarraySlice.call(value);}returnvalue;}functionrgba2String(rgba){rgba[0]=Math.floor(rgba[0]);rgba[1]=Math.floor(rgba[1]);rgba[2]=Math.floor(rgba[2]);return'rgba('+rgba.join(',')+')';}functiongetArrayDim(keyframes){varlastValue=keyframes[keyframes.length-1].value;returnisArrayLike(lastValue&&lastValue[0])?2:1;}functioncreateTrackClip(animator,easing,oneTrackDone,keyframes,propName,forceAnimate){vargetter=animator._getter;varsetter=animator._setter;varuseSpline=easing==='spline';vartrackLen=keyframes.length;if(!trackLen){return;}// Guess data typevarfirstVal=keyframes[0].value;varisValueArray=isArrayLike(firstVal);varisValueColor=false;varisValueString=false;// For vertices morphingvararrDim=isValueArray?getArrayDim(keyframes):0;vartrackMaxTime;// Sort keyframe as ascendingkeyframes.sort(function(a,b){returna.time-b.time;});trackMaxTime=keyframes[trackLen-1].time;// Percents of each keyframevarkfPercents=[];// Value of each keyframevarkfValues=[];varprevValue=keyframes[0].value;varisAllValueEqual=true;for(vari=0;i<trackLen;i++){kfPercents.push(keyframes[i].time/trackMaxTime);// Assume value is a color when it is a stringvarvalue=keyframes[i].value;// Check if value is equal, deep check if value is arrayif(!((isValueArray&&isArraySame(value,prevValue,arrDim))||(!isValueArray&&value===prevValue))){isAllValueEqual=false;}prevValue=value;// Try converting a string to a color arrayif(typeofvalue=='string'){varcolorArray=parse(value);if(colorArray){value=colorArray;isValueColor=true;}else{isValueString=true;}}kfValues.push(value);}if(!forceAnimate&&isAllValueEqual){return;}varlastValue=kfValues[trackLen-1];// Polyfill array and NaN valuefor(vari=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// animation playback is sequencyvarlastFrame=0;varlastFramePercent=0;varstart;varw;varp0;varp1;varp2;varp3;if(isValueColor){varrgba=[0,0,0,0];}varonframe=function(target,percent){// Find the range keyframes// kf1-----kf2---------current--------kf3// find kf2 and kf3 and do interpolationvarframe;// In the easing function like elasticOut, percent may less than 0if(percent<0){frame=0;}elseif(percent<lastFramePercent){// Start from next key// PENDING start from lastFrame ?start=Math.min(lastFrame+1,trackLen-1);for(frame=start;frame>=0;frame--){if(kfPercents[frame]<=percent){break;}}// PENDING really need to do this ?frame=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;varrange=(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{varvalue;if(isValueColor){value=catmullRomInterpolateArray(p0,p1,p2,p3,w,w*w,w*w*w,rgba,1);value=rgba2String(rgba);}elseif(isValueString){// String is step(0.5)returninterpolateString(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{varvalue;if(isValueColor){interpolateArray(kfValues[frame],kfValues[frame+1],w,rgba,1);value=rgba2String(rgba);}elseif(isValueString){// String is step(0.5)returninterpolateString(kfValues[frame],kfValues[frame+1],w);}else{value=interpolateNumber(kfValues[frame],kfValues[frame+1],w);}setter(target,propName,value);}}};varclip=newClip({target:animator._target,life:trackMaxTime,loop:animator._loop,delay:animator._delay,onframe:onframe,ondestroy:oneTrackDone});if(easing&&easing!=='spline'){clip.easing=easing;}returnclip;}/** * @alias module:zrender/animation/Animator*@constructor*@param{Object}target*@param{boolean}loop*@param{Function}getter*@param{Function}setter*/var Animator = function(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 = { /***设置动画关键帧*@param{number}time关键帧时间,单位是ms*@param{Object}props关键帧的属性值,key-value表示*@return{module:zrender/animation/Animator}*/ when: function(time /*ms*/, props) { var tracks = this._tracks; for (var propName in props) { if (!props.hasOwnProperty(propName)) { continue; } if (!tracks[propName]) { tracks[propName] = []; //Invalidvaluevarvalue=this._getter(this._target,propName);if(value==null){// zrLog('Invalid property ' + propName);continue;}// If time is 0// Then props is given initialize value// Else// Initialize value from current prop valueif(time!==0){tracks[propName].push({time:0,value:cloneValue(value)});}}tracks[propName].push({time:time,value:props[propName]});}returnthis;},/** * 添加动画每一帧的回调函数 * @param {Function} callback * @return {module:zrender/animation/Animator}*/ during: function (callback) { this._onframeList.push(callback); return this; }, pause: function () { for (var i = 0; i < this._clipList.length; i++) { this._clipList[i].pause(); } this._paused = true; }, resume: function () { for (var i = 0; i < this._clipList.length; i++) { this._clipList[i].resume(); } this._paused = false; }, isPaused: function () { return !!this._paused; }, _doneCallback: function () { //Clearalltracksthis._tracks={};// Clear all clipsthis._clipList.length=0;vardoneList=this._doneList;varlen=doneList.length;for(vari=0;i<len;i++){doneList[i].call(this);}},/** * 开始执行动画 * @param {string|Function} [easing] * 动画缓动函数,详见{@link module:zrender/animation/easing}*@param{boolean}forceAnimate*@return{module:zrender/animation/Animator}*/ start: function (easing, forceAnimate) { var self = this; var clipCount = 0; var oneTrackDone = function() { 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++; //Ifstartafteraddedtoanimationif(this.animation){this.animation.addClip(clip);}lastClip=clip;}}// Add during callback on the last clipif(lastClip){varoldOnFrame=lastClip.onframe;lastClip.onframe=function(target,percent){oldOnFrame(target,percent);for(vari=0;i<self._onframeList.length;i++){self._onframeList[i](target,percent);}};}// This optimization will help the case that in the upper application// the view may be refreshed frequently, where animation will be// called repeatly but nothing changed.if(!clipCount){this._doneCallback();}returnthis;},/** * 停止动画 * @param {boolean} forwardToLast If move to last frame before stop */stop:function(forwardToLast){varclipList=this._clipList;varanimation=this.animation;for(vari=0;i<clipList.length;i++){varclip=clipList[i];if(forwardToLast){// Move to last frame before stopclip.onframe(this._target,1);}animation&&animation.removeClip(clip);}clipList.length=0;},/** * 设置动画延迟开始的时间 * @param {number} time 单位ms * @return {module:zrender/animation/Animator}*/ delay: function (time) { this._delay = time; return this; }, /***添加动画结束的回调*@param{Function}cb*@return{module:zrender/animation/Animator}*/ done: function(cb) { if (cb) { this._doneList.push(cb); } return this; }, /***@return{Array.<module:zrender/animation/Clip>}*/ getClips: function () { return this._clipList; }};var dpr = 1;//Ifinbrowserenvironmentif(typeofwindow!=='undefined'){dpr=Math.max(window.devicePixelRatio||1,1);}/** * config默认配置项 * @exports zrender/config*@authorKener(@Kener-林峰,kener.linfeng@gmail.com)*//***debug日志选项:catchBrushException为true下有效*0:不生成debug数据,发布用*1:异常抛出,调试用*2:控制台输出,调试用*/var debugMode = 0;//retina屏幕优化vardevicePixelRatio=dpr;varlog=function(){};if(debugMode===1){log=function(){for(varkinarguments){thrownewError(arguments[k]);}};}elseif(debugMode>1){log=function(){for(varkinarguments){console.log(arguments[k]);}};}varlog$1=log;/** * @alias modue:zrender/mixin/Animatable*@constructor*/var Animatable = function () { /***@type{Array.<module:zrender/animation/Animator>}*@readOnly*/ this.animators = [];};Animatable.prototype = { constructor: Animatable, /***动画**@param{string}pathThepathtofetchvaluefromobject,like'a.b.c'.*@param{boolean}[loop]Whethertoloopanimation.*@return{module:zrender/animation/Animator}*@example:*el.animate('style',false)*.when(1000,{x:10})*.done(function(){// Animation done })*.start()*/ animate: function (path, loop) { var target; var animatingShape = false; var el = this; var zr = this.__zr; if (path) { var pathSplitted = path.split('.'); var prop = el; //IfanimatingshapeanimatingShape=pathSplitted[0]==='shape';for(vari=0,l=pathSplitted.length;i<l;i++){if(!prop){continue;}prop=prop[pathSplitted[i]];}if(prop){target=prop;}}else{target=el;}if(!target){log$1('Property "'+path+'" is not existed in element '+el.id);return;}varanimators=el.animators;varanimator=newAnimator(target,loop);animator.during(function(target){el.dirty(animatingShape);}).done(function(){// FIXME Animator will not be removed if use `Animator#stop` to stop animationanimators.splice(indexOf(animators,animator),1);});animators.push(animator);// If animate after added to the zrenderif(zr){zr.animation.addAnimator(animator);}returnanimator;},/** * 停止动画 * @param {boolean} forwardToLast If move to last frame before stop */stopAnimation:function(forwardToLast){varanimators=this.animators;varlen=animators.length;for(vari=0;i<len;i++){animators[i].stop(forwardToLast);}animators.length=0;returnthis;},/** * Caution: this method will stop previous animation. * So do not use this method to one element twice before * animation starts, unless you know what you are doing. * @param {Object} target * @param {number} [time=500] Time in ms * @param {string} [easing='linear'] * @param {number} [delay=0] * @param {Function} [callback] * @param {Function} [forceAnimate] Prevent stop animation and callback * immediently when target values are the same as current values. * * @example * //Animateposition*el.animateTo({*position:[10,10]*},function(){// done })**// Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing*el.animateTo({*shape:{*width:500*},*style:{*fill:'red'*}*position:[10,10]*},100,100,'cubicOut',function(){// done })*/ //TODOReturnanimationkeyanimateTo:function(target,time,delay,easing,callback,forceAnimate){animateTo(this,target,time,delay,easing,callback,forceAnimate);},/** * Animate from the target state to current state. * The params and the return value are the same as `this.animateTo`. */animateFrom:function(target,time,delay,easing,callback,forceAnimate){animateTo(this,target,time,delay,easing,callback,forceAnimate,true);}};functionanimateTo(animatable,target,time,delay,easing,callback,forceAnimate,reverse){// animateTo(target, time, easing, callback);if(isString(delay)){callback=easing;easing=delay;delay=0;}// animateTo(target, time, delay, callback);elseif(isFunction$1(easing)){callback=easing;easing='linear';delay=0;}// animateTo(target, time, callback);elseif(isFunction$1(delay)){callback=delay;delay=0;}// animateTo(target, callback)elseif(isFunction$1(time)){callback=time;time=500;}// animateTo(target)elseif(!time){time=500;}// Stop all previous animationsanimatable.stopAnimation();animateToShallow(animatable,'',animatable,target,time,delay,reverse);// Animators may be removed immediately after start// if there is nothing to animatevaranimators=animatable.animators.slice();varcount=animators.length;functiondone(){count--;if(!count){callback&&callback();}}// No animators. This should be checked before animators[i].start(),// because 'done' may be executed immediately if no need to animate.if(!count){callback&&callback();}// Start after all animators created// Incase any animator is done immediately when all animation properties are not changedfor(vari=0;i<animators.length;i++){animators[i].done(done).start(easing,forceAnimate);}}/** * @param {string} path='' * @param {Object} source=animatable * @param {Object} target * @param {number} [time=500] * @param {number} [delay=0] * @param {boolean} [reverse] If `true`, animate * from the `target` to current state. * * @example * //Animateposition*el._animateToShallow({*position:[10,10]*})**// Animate shape, style and position in 100ms, delayed 100ms*el._animateToShallow({*shape:{*width:500*},*style:{*fill:'red'*}*position:[10,10]*},100,100)*/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) { //Attrdirectlyifnothasproperty// FIXME, if some property not needed for element ?if(!path){el.attr(name,value);}else{// Only support set shape or stylevarprops={};props[path]={};props[path][name]=value;el.attr(props);}}/** * @alias module:zrender/Element*@constructor*@extends{module:zrender/mixin/Animatable}*@extends{module:zrender/mixin/Transformable}*@extends{module:zrender/mixin/Eventful}*/var Element = function (opts) { //jshintignore:lineTransformable.call(this,opts);Eventful.call(this,opts);Animatable.call(this,opts);/** * 画布元素ID * @type {string} */this.id=opts.id||guid();};Element.prototype={/***元素类型*Elementtype*@type{string}*/ type: 'element', /***元素名字*Elementname*@type{string}*/ name: '', /***ZRender实例对象,会在element添加到zrender实例中后自动赋值*ZRenderinstancewillbeassignedwhenelementisassociatedwithzrender*@namemodule:/zrender/Element#__zr*@type{module:zrender/ZRender}*/ __zr: null, /***图形是否忽略,为true时忽略图形的绘制以及事件触发*Ifignoredrawingandeventsoftheelementobject*@namemodule:/zrender/Element#ignore*@type{boolean}*@defaultfalse*/ ignore: false, /***用于裁剪的路径(shape),所有Group内的路径在绘制时都会被这个路径裁剪*该路径会继承被裁减对象的变换*@type{module:zrender/graphic/Path}*@seehttp://www.w3.org/TR/2dcontext/#clipping-region*@readOnly*/ clipPath: null, /***是否是Group*@type{boolean}*/ isGroup: false, /***Driftelement*@param{number}dxdxontheglobalspace*@param{number}dydyontheglobalspace*/ drift: function (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); }, /***Hookbeforeupdate*/ beforeUpdate: function () {}, /***Hookafterupdate*/ afterUpdate: function () {}, /***Updateeachframe*/ update: function () { this.updateTransform(); }, /***@param{Function}cb*@param{}context*/ traverse: function (cb, context) {}, /***@protected*/ attrKV: function (key, value) { if (key === 'position' || key === 'scale' || key === 'origin') { //Copythearrayif(value){vartarget=this[key];if(!target){target=this[key]=[];}target[0]=value[0];target[1]=value[1];}}else{this[key]=value;}},/** * Hide the element */hide:function(){this.ignore=true;this.__zr&&this.__zr.refresh();},/** * Show the element */show:function(){this.ignore=false;this.__zr&&this.__zr.refresh();},/** * @param {string|Object} key * @param {*} value */attr:function(key,value){if(typeofkey==='string'){this.attrKV(key,value);}elseif(isObject$1(key)){for(varnameinkey){if(key.hasOwnProperty(name)){this.attrKV(name,key[name]);}}}this.dirty(false);returnthis;},/** * @param {module:zrender/graphic/Path}clipPath*/ setClipPath: function (clipPath) { var zr = this.__zr; if (zr) { clipPath.addSelfToZr(zr); } //Removepreviousclippathif(this.clipPath&&this.clipPath!==clipPath){this.removeClipPath();}this.clipPath=clipPath;clipPath.__zr=zr;clipPath.__clipTarget=this;this.dirty(false);},/** */removeClipPath:function(){varclipPath=this.clipPath;if(clipPath){if(clipPath.__zr){clipPath.removeSelfFromZr(clipPath.__zr);}clipPath.__zr=null;clipPath.__clipTarget=null;this.clipPath=null;this.dirty(false);}},/** * Add self from zrender instance. * Not recursively because it will be invoked when element added to storage. * @param {module:zrender/ZRender}zr*/ addSelfToZr: function (zr) { this.__zr = zr; //添加动画varanimators=this.animators;if(animators){for(vari=0;i<animators.length;i++){zr.animation.addAnimator(animators[i]);}}if(this.clipPath){this.clipPath.addSelfToZr(zr);}},/** * Remove self from zrender instance. * Not recursively because it will be invoked when element added to storage. * @param {module:zrender/ZRender}zr*/ removeSelfFromZr: function (zr) { this.__zr = null; //移除动画varanimators=this.animators;if(animators){for(vari=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);/** * @module echarts/core/BoundingRect*/var v2ApplyTransform = applyTransform;var mathMin = Math.min;var mathMax = Math.max;/***@aliasmodule:echarts/core/BoundingRect*/function BoundingRect(x, y, width, height) { if (width < 0) { x = x + width; width = -width; } if (height < 0) { y = y + height; height = -height; } /***@type{number}*/ this.x = x; /***@type{number}*/ this.y = y; /***@type{number}*/ this.width = width; /***@type{number}*/ this.height = height;}BoundingRect.prototype = { constructor: BoundingRect, /***@param{module:echarts/core/BoundingRect}other*/ union: function (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; }, /***@param{Array.<number>}m*@methods*/ applyTransform: (function () { var lt = []; var rb = []; var lb = []; var rt = []; return function (m) { //Incaseusagelikethis// el.getBoundingRect().applyTransform(el.transform)// And element has no transformif(!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]);varmaxX=mathMax(lt[0],rb[0],lb[0],rt[0]);varmaxY=mathMax(lt[1],rb[1],lb[1],rt[1]);this.width=maxX-this.x;this.height=maxY-this.y;};})(),/** * Calculate matrix of transforming from self to target rect * @param {module:zrender/core/BoundingRect}b*@return{Array.<number>}*/ calculateTransform: function (b) { var a = this; var sx = b.width /a.width;varsy=b.height/a.height;varm=create$1();// 矩阵右乘translate(m,m,[-a.x,-a.y]);scale$1(m,m,[sx,sy]);translate(m,m,[b.x,b.y]);returnm;},/** * @param {(module:echarts/core/BoundingRect|Object)}b*@return{boolean}*/ intersect: function (b) { if (!b) { return false; } if (!(b instanceof BoundingRect)) { //Normalizenegativewidth/height.b=BoundingRect.create(b);}vara=this;varax0=a.x;varax1=a.x+a.width;varay0=a.y;varay1=a.y+a.height;varbx0=b.x;varbx1=b.x+b.width;varby0=b.y;varby1=b.y+b.height;return!(ax1<bx0||bx1<ax0||ay1<by0||by1<ay0);},contain:function(x,y){varrect=this;returnx>=rect.x&&x<=(rect.x+rect.width)&&y>=rect.y&&y<=(rect.y+rect.height);},/** * @return {module:echarts/core/BoundingRect}*/ clone: function () { return new BoundingRect(this.x, this.y, this.width, this.height); }, /***Copyfromanotherrect*/ copy: function (other) { this.x = other.x; this.y = other.y; this.width = other.width; this.height = other.height; }, plain: function () { return { x: this.x, y: this.y, width: this.width, height: this.height }; }};/***@param{Object|module:zrender/core/BoundingRect}rect*@param{number}rect.x*@param{number}rect.y*@param{number}rect.width*@param{number}rect.height*@return{module:zrender/core/BoundingRect}*/BoundingRect.create = function (rect) { return new BoundingRect(rect.x, rect.y, rect.width, rect.height);};/***Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上*@modulezrender/graphic/Group*@example*varGroup=require('zrender/container/Group');*varCircle=require('zrender/graphic/shape/Circle');*varg=newGroup();*g.position[0]=100;*g.position[1]=100;*g.add(newCircle({*style:{*x:100,*y:100,*r:20,*}*}));*zr.add(g);*//***@aliasmodule:zrender/graphic/Group*@constructor*@extendsmodule:zrender/mixin/Transformable*@extendsmodule:zrender/mixin/Eventful*/var Group = function (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, /***@type{string}*/ type: 'group', /***所有子孙元素是否响应鼠标事件*@namemodule:/zrender/container/Group#silent*@type{boolean}*@defaultfalse*/ silent: false, /***@return{Array.<module:zrender/Element>}*/ children: function () { return this._children.slice(); }, /***获取指定index的儿子节点*@param{number}idx*@return{module:zrender/Element}*/ childAt: function (idx) { return this._children[idx]; }, /***获取指定名字的儿子节点*@param{string}name*@return{module:zrender/Element}*/ childOfName: function (name) { var children = this._children; for (var i = 0; i < children.length; i++) { if (children[i].name === name) { return children[i]; } } }, /***@return{number}*/ childCount: function () { return this._children.length; }, /***添加子节点到最后*@param{module:zrender/Element}child*/ add: function (child) { if (child && child !== this && child.parent !== this) { this._children.push(child); this._doAdd(child); } return this; }, /***添加子节点在nextSibling之前*@param{module:zrender/Element}child*@param{module:zrender/Element}nextSibling*/ addBefore: function (child, nextSibling) { if (child && child !== this && child.parent !== this && nextSibling && nextSibling.parent === this) { var children = this._children; var idx = children.indexOf(nextSibling); if (idx >= 0) { children.splice(idx, 0, child); this._doAdd(child); } } return this; }, _doAdd: function (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(); }, /***移除子节点*@param{module:zrender/Element}child*/ remove: function (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; }, /***移除所有子节点*/ removeAll: function () { 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; }, /***遍历所有子节点*@param{Function}cb*@param{}context*/ eachChild: function (cb, context) { var children = this._children; for (var i = 0; i < children.length; i++) { var child = children[i]; cb.call(context, child, i); } return this; }, /***深度优先遍历所有子孙节点*@param{Function}cb*@param{}context*/ traverse: function (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 (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 (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 () { this.__dirty = true; this.__zr && this.__zr.refresh(); return this; }, /***@return{module:zrender/core/BoundingRect}*/ getBoundingRect: function (includeChildren) { //TODOCachingvarrect=null;vartmpRect=newBoundingRect(0,0,0,0);varchildren=includeChildren||this._children;vartmpMat=[];for(vari=0;i<children.length;i++){varchild=children[i];if(child.ignore||child.invisible){continue;}varchildRect=child.getBoundingRect();vartransform=child.getLocalTransform(tmpMat);// TODO// The boundingRect cacluated by transforming original// rect may be bigger than the actual bundingRect when rotation// is used. (Consider a circle rotated aginst its center, where// the actual boundingRect should be the same as that not be// rotated.) But we can not find better approach to calculate// actual boundingRect yet, considering performance.if(transform){tmpRect.copy(childRect);tmpRect.applyTransform(transform);rect=rect||tmpRect.clone();rect.union(tmpRect);}else{rect=rect||childRect.clone();rect.union(childRect);}}returnrect||tmpRect;}};inherits(Group,Element);// https://github.com/mziccard/node-timsortvarDEFAULT_MIN_MERGE=32;varDEFAULT_MIN_GALLOPING=7;functionminRunLength(n){varr=0;while(n>=DEFAULT_MIN_MERGE){r|=n&1;n>>=1;}returnn+r;}functionmakeAscendingRun(array,lo,hi,compare){varrunHi=lo+1;if(runHi===hi){return1;}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++;}}returnrunHi-lo;}functionreverseRun(array,lo,hi){hi--;while(lo<hi){vart=array[lo];array[lo++]=array[hi];array[hi--]=t;}}functionbinaryInsertionSort(array,lo,hi,start,compare){if(start===lo){start++;}for(;start<hi;start++){varpivot=array[start];varleft=lo;varright=start;varmid;while(left<right){mid=left+right>>>1;if(compare(pivot,array[mid])<0){right=mid;}else{left=mid+1;}}varn=start-left;switch(n){case3:array[left+3]=array[left+2];case2:array[left+2]=array[left+1];case1:array[left+1]=array[left];break;default:while(n>0){array[left+n]=array[left+n-1];n--;}}array[left]=pivot;}}functiongallopLeft(value,array,start,length,hint,compare){varlastOffset=0;varmaxOffset=0;varoffset=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;}vartmp=lastOffset;lastOffset=hint-offset;offset=hint-tmp;}lastOffset++;while(lastOffset<offset){varm=lastOffset+(offset-lastOffset>>>1);if(compare(value,array[start+m])>0){lastOffset=m+1;}else{offset=m;}}returnoffset;}functiongallopRight(value,array,start,length,hint,compare){varlastOffset=0;varmaxOffset=0;varoffset=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;}vartmp=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){varm=lastOffset+(offset-lastOffset>>>1);if(compare(value,array[start+m])<0){offset=m;}else{lastOffset=m+1;}}returnoffset;}functionTimSort(array,compare){varminGallop=DEFAULT_MIN_GALLOPING;varrunStart;varrunLength;varstackSize=0;vartmp=[];runStart=[];runLength=[];functionpushRun(_runStart,_runLength){runStart[stackSize]=_runStart;runLength[stackSize]=_runLength;stackSize+=1;}functionmergeRuns(){while(stackSize>1){varn=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--;}}elseif(runLength[n]>runLength[n+1]){break;}mergeAt(n);}}functionforceMergeRuns(){while(stackSize>1){varn=stackSize-2;if(n>0&&runLength[n-1]<runLength[n+1]){n--;}mergeAt(n);}}functionmergeAt(i){varstart1=runStart[i];varlength1=runLength[i];varstart2=runStart[i+1];varlength2=runLength[i+1];runLength[i]=length1+length2;if(i===stackSize-3){runStart[i+1]=runStart[i+2];runLength[i+1]=runLength[i+2];}stackSize--;vark=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);}}functionmergeLow(start1,length1,start2,length2){vari=0;for(i=0;i<length1;i++){tmp[i]=array[start1+i];}varcursor1=0;varcursor2=start2;vardest=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;varcount1,count2,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];}elseif(length1===0){thrownewError();// throw new Error('mergeLow preconditions were not respected');}else{for(i=0;i<length1;i++){array[dest+i]=tmp[cursor1+i];}}}functionmergeHigh(start1,length1,start2,length2){vari=0;for(i=0;i<length2;i++){tmp[i]=array[start2+i];}varcursor1=start1+length1-1;varcursor2=length2-1;vardest=start2+length2-1;varcustomCursor=0;varcustomDest=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){varcount1=0;varcount2=0;varexit=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];}elseif(length2===0){thrownewError();// throw new Error('mergeHigh preconditions were not respected');}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;}functionsort(array,compare,lo,hi){if(!lo){lo=0;}if(!hi){hi=array.length;}varremaining=hi-lo;if(remaining<2){return;}varrunLength=0;if(remaining<DEFAULT_MIN_MERGE){runLength=makeAscendingRun(array,lo,hi,compare);binaryInsertionSort(array,lo,hi,lo+runLength,compare);return;}varts=newTimSort(array,compare);varminRun=minRunLength(remaining);do{runLength=makeAscendingRun(array,lo,hi,compare);if(runLength<minRun){varforce=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// https://jsfiddle.net/pissang/jr4x7mdm/8/functionshapeCompareFunc(a,b){if(a.zlevel===b.zlevel){if(a.z===b.z){// if (a.z2 === b.z2) {// // FIXME Slow has renderidx compare// // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement// // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012// return a.__renderidx - b.__renderidx;// }returna.z2-b.z2;}returna.z-b.z;}returna.zlevel-b.zlevel;}/** * 内容仓库 (M) * @alias module:zrender/Storage*@constructor*/var Storage = function () { //jshintignore:linethis._roots=[];this._displayList=[];this._displayListLen=0;};Storage.prototype={constructor:Storage,/** * @param {Function} cb * */traverse:function(cb,context){for(vari=0;i<this._roots.length;i++){this._roots[i].traverse(cb,context);}},/** * 返回所有图形的绘制队列 * @param {boolean} [update=false] 是否在返回前更新该数组 * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效 * * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}*@return{Array.<module:zrender/graphic/Displayable>}*/ getDisplayList: function (update, includeIgnore) { includeIgnore = includeIgnore || false; if (update) { this.updateDisplayList(includeIgnore); } return this._displayList; }, /***更新图形的绘制队列。*每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,*最后根据绘制的优先级(zlevel>z>插入顺序)排序得到绘制队列*@param{boolean}[includeIgnore=false]是否包含ignore的数组*/ updateDisplayList: function (includeIgnore) { this._displayListLen = 0; var roots = this._roots; var displayList = this._displayList; for (var i = 0, len = roots.length; i < len; i++) { this._updateAndAddDisplayable(roots[i], null, includeIgnore); } displayList.length = this._displayListLen; env$1.canvasSupported && sort(displayList, shapeCompareFunc); }, _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) { if (el.ignore && !includeIgnore) { return; } el.beforeUpdate(); if (el.__dirty) { el.update(); } el.afterUpdate(); var userSetClipPath = el.clipPath; if (userSetClipPath) { //FIXME效率影响if(clipPaths){clipPaths=clipPaths.slice();}else{clipPaths=[];}varcurrentClipPath=userSetClipPath;varparentClipPath=el;// Recursively add clip pathwhile(currentClipPath){// clipPath 的变换是基于使用这个 clipPath 的元素currentClipPath.parent=parentClipPath;currentClipPath.updateTransform();clipPaths.push(currentClipPath);parentClipPath=currentClipPath;currentClipPath=currentClipPath.clipPath;}}if(el.isGroup){varchildren=el._children;for(vari=0;i<children.length;i++){varchild=children[i];// Force to mark as dirty if group is dirty// FIXME __dirtyPath ?if(el.__dirty){child.__dirty=true;}this._updateAndAddDisplayable(child,clipPaths,includeIgnore);}// Mark group clean hereel.__dirty=false;}else{el.__clipPaths=clipPaths;this._displayList[this._displayListLen++]=el;}},/** * 添加图形(Shape)或者组(Group)到根节点 * @param {module:zrender/Element}el*/ addRoot: function (el) { if (el.__storage === this) { return; } if (el instanceof Group) { el.addChildrenToStorage(this); } this.addToStorage(el); this._roots.push(el); }, /***删除指定的图形(Shape)或者组(Group)*@param{string|Array.<string>}[el]如果为空清空整个Storage*/ delRoot: function (el) { if (el == null) { //不指定el清空for(vari=0;i<this._roots.length;i++){varroot=this._roots[i];if(rootinstanceofGroup){root.delChildrenFromStorage(this);}}this._roots=[];this._displayList=[];this._displayListLen=0;return;}if(elinstanceofArray){for(vari=0,l=el.length;i<l;i++){this.delRoot(el[i]);}return;}varidx=indexOf(this._roots,el);if(idx>=0){this.delFromStorage(el);this._roots.splice(idx,1);if(elinstanceofGroup){el.delChildrenFromStorage(this);}}},addToStorage:function(el){if(el){el.__storage=this;el.dirty(false);}returnthis;},delFromStorage:function(el){if(el){el.__storage=null;}returnthis;},/** * 清空并且释放Storage */dispose:function(){this._renderList=this._roots=null;},displayableSortFunc:shapeCompareFunc};varSHADOW_PROPS={'shadowBlur':1,'shadowOffsetX':1,'shadowOffsetY':1,'textShadowBlur':1,'textShadowOffsetX':1,'textShadowOffsetY':1,'textBoxShadowBlur':1,'textBoxShadowOffsetX':1,'textBoxShadowOffsetY':1};varfixShadow=function(ctx,propName,value){if(SHADOW_PROPS.hasOwnProperty(propName)){returnvalue*=ctx.dpr;}returnvalue;};varSTYLE_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);// var LINE_PROPS = STYLE_COMMON_PROPS.slice(4);varStyle=function(opts){this.extendFrom(opts,false);};functioncreateLinearGradient(ctx,obj,rect){varx=obj.x==null?0:obj.x;varx2=obj.x2==null?1:obj.x2;vary=obj.y==null?0:obj.y;vary2=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 Infinityx=isNaN(x)?0:x;x2=isNaN(x2)?1:x2;y=isNaN(y)?0:y;y2=isNaN(y2)?0:y2;varcanvasGradient=ctx.createLinearGradient(x,y,x2,y2);returncanvasGradient;}functioncreateRadialGradient(ctx,obj,rect){varwidth=rect.width;varheight=rect.height;varmin=Math.min(width,height);varx=obj.x==null?0.5:obj.x;vary=obj.y==null?0.5:obj.y;varr=obj.r==null?0.5:obj.r;if(!obj.global){x=x*width+rect.x;y=y*height+rect.y;r=r*min;}varcanvasGradient=ctx.createRadialGradient(x,y,0,x,y,r);returncanvasGradient;}Style.prototype={constructor:Style,/** * @type {string} */fill:'#000',/** * @type {string} */stroke:null,/** * @type {number} */opacity:1,/** * @type {number} */fillOpacity:null,/** * @type {number} */strokeOpacity:null,/** * @type {Array.<number>} */lineDash:null,/** * @type {number} */lineDashOffset:0,/** * @type {number} */shadowBlur:0,/** * @type {number} */shadowOffsetX:0,/** * @type {number} */shadowOffsetY:0,/** * @type {number} */lineWidth:1,/** * If stroke ignore scale * @type {Boolean} */strokeNoScale:false,// Bounding rect text configuration// Not affected by element transform/** * @type {string} */text:null,/** * If `fontSize` or `fontFamily` exists, `font` will be reset by * `fontSize`, `fontStyle`, `fontWeight`, `fontFamily`. * So do not visit it directly in upper application (like echarts), * but use `contain/text#makeFont`instead.*@type{string}*/ font: null, /***Thesameasfont.Usefontplease.*@deprecated*@type{string}*/ textFont: null, /***Ithelpsmergingrespectively,ratherthanparsinganentirefontstring.*@type{string}*/ fontStyle: null, /***Ithelpsmergingrespectively,ratherthanparsinganentirefontstring.*@type{string}*/ fontWeight: null, /***Ithelpsmergingrespectively,ratherthanparsinganentirefontstring.*Shouldbe12butnot'12px'.*@type{number}*/ fontSize: null, /***Ithelpsmergingrespectively,ratherthanparsinganentirefontstring.*@type{string}*/ fontFamily: null, /***Reservedforspecialfunctinality,like'hr'.*@type{string}*/ textTag: null, /***@type{string}*/ textFill: '#000', /***@type{string}*/ textStroke: null, /***@type{number}*/ textWidth: null, /***OnlyfortextBackground.*@type{number}*/ textHeight: null, /***textStrokemaybesetassomecolorasadefault*valueinupperapplicaion,wherethedefaultvalue*oftextStrokeWidthshouldbe0tomakesurethat*usercanchoosetodonotusetextstroke.*@type{number}*/ textStrokeWidth: 0, /***@type{number}*/ textLineHeight: null, /***'inside','left','right','top','bottom'*[x,y]*Basedonx,yofrect.*@type{string|Array.<number>}*@default'inside'*/ textPosition: 'inside', /***Ifnotspecified,usetheboundingRectofa`displayable`.*@type{Object}*/ textRect: null, /***[x,y]*@type{Array.<number>}*/ textOffset: null, /***@type{string}*/ textAlign: null, /***@type{string}*/ textVerticalAlign: null, /***@type{number}*/ textDistance: 5, /***@type{string}*/ textShadowColor: 'transparent', /***@type{number}*/ textShadowBlur: 0, /***@type{number}*/ textShadowOffsetX: 0, /***@type{number}*/ textShadowOffsetY: 0, /***@type{string}*/ textBoxShadowColor: 'transparent', /***@type{number}*/ textBoxShadowBlur: 0, /***@type{number}*/ textBoxShadowOffsetX: 0, /***@type{number}*/ textBoxShadowOffsetY: 0, /***Whethertransformtext.*OnlyusefulinPathandImageelement*@type{boolean}*/ transformText: false, /***TextrotatearoundpositionofPathorImage*OnlyusefulinPathandImageelementandtransformTextisfalse.*/ textRotation: 0, /***Textoriginoftextrotation,like[10,40].*Basedonx,yofrect.*Usefulinlabelrotationofcircularsymbol.*Bydefault,thisoriginistextPosition.*Canbe'center'.*@type{string|Array.<number>}*/ textOrigin: null, /***@type{string}*/ textBackgroundColor: null, /***@type{string}*/ textBorderColor: null, /***@type{number}*/ textBorderWidth: 0, /***@type{number}*/ textBorderRadius: 0, /***Canbe`2`or`[2,4]`or`[2,3,4,5]`*@type{number|Array.<number>}*/ textPadding: null, /***Textstylesforrichtext.*@type{Object}*/ rich: null, /***{outerWidth,outerHeight,ellipsis,placeholder}*@type{Object}*/ truncate: null, /***https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation*@type{string}*/ blend: null, /***@param{CanvasRenderingContext2D}ctx*/ bind: function (ctx, el, prevEl) { var style = this; var prevStyle = prevEl && prevEl.style; var firstDraw = !prevStyle; for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) { var prop = STYLE_COMMON_PROPS[i]; var styleName = prop[0]; if (firstDraw || style[styleName] !== prevStyle[styleName]) { //FIXMEInvalidpropertyvaluewillcausestyleleakfrompreviouselement.ctx[styleName]=fixShadow(ctx,styleName,style[styleName]||prop[1]);}}if((firstDraw||style.fill!==prevStyle.fill)){ctx.fillStyle=style.fill;}if((firstDraw||style.stroke!==prevStyle.stroke)){ctx.strokeStyle=style.stroke;}if((firstDraw||style.opacity!==prevStyle.opacity)){ctx.globalAlpha=style.opacity==null?1:style.opacity;}if((firstDraw||style.blend!==prevStyle.blend)){ctx.globalCompositeOperation=style.blend||'source-over';}if(this.hasStroke()){varlineWidth=style.lineWidth;ctx.lineWidth=lineWidth/((this.strokeNoScale&&el&&el.getLineScale)?el.getLineScale():1);}},hasFill:function(){varfill=this.fill;returnfill!=null&&fill!=='none';},hasStroke:function(){varstroke=this.stroke;returnstroke!=null&&stroke!=='none'&&this.lineWidth>0;},/** * Extend from other style * @param {zrender/graphic/Style}otherStyle*@param{boolean}overwritetrue:overwrirteanyway.*false:overwriteonlywhen!target.hasOwnProperty*others:overwritewhenpropertyisnotnull/undefined.*/ extendFrom: function (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]; } } } }, /***Batchsettingstylewithagivenobject*@param{Object|string}obj*@param{*}[obj]*/ set: function (obj, value) { if (typeof obj === 'string') { this[obj] = value; } else { this.extendFrom(obj, true); } }, /***Clone*@return{zrender/graphic/Style}[description]*/ clone: function () { var newStyle = new this.constructor(); newStyle.extendFrom(this, true); return newStyle; }, getGradient: function (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]; }}//ProvideforothersStyle.getGradient=styleProto.getGradient;varPattern=function(image,repeat){// Should do nothing more in this constructor. Because gradient can be// declard by `color: {image: ...}`, where this constructor will not be called.this.image=image;this.repeat=repeat;// Can be clonedthis.type='pattern';};Pattern.prototype.getCanvasPattern=function(ctx){returnctx.createPattern(this.image,this.repeat||'repeat');};/** * @module zrender/Layer*@authorpissang(https://www.github.com/pissang)*/function returnFalse() { return false;}/***创建dom**@inner*@param{string}iddomid待用*@param{Painter}painterpainterinstance*@param{number}number*/function createDom(id, painter, dpr) { var newDom = createCanvas(); var width = painter.getWidth(); var height = painter.getHeight(); var newDomStyle = newDom.style; if (newDomStyle) { //Innodeorsomeothernon-browserenvironmentnewDomStyle.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;returnnewDom;}/** * @alias module:zrender/Layer*@constructor*@extendsmodule:zrender/mixin/Transformable*@param{string}id*@param{module:zrender/Painter}painter*@param{number}[dpr]*/var Layer = function(id, painter, dpr) { var dom; dpr = dpr || devicePixelRatio; if (typeof id === 'string') { dom = createDom(id, painter, dpr); } //NotusingisDombecauseinnodeitwillreturnfalseelseif(isObject$1(id)){dom=id;id=dom.id;}this.id=id;this.dom=dom;vardomStyle=dom.style;if(domStyle){// Not in nodedom.onselectstart=returnFalse;// 避免页面选中的尴尬domStyle['-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;domStyle['margin']=0;domStyle['border-width']=0;}this.domBack=null;this.ctxBack=null;this.painter=painter;this.config=null;// Configs/** * 每次清空画布的颜色 * @type {string} * @default 0 */this.clearColor=0;/** * 是否开启动态模糊 * @type {boolean} * @default false */this.motionBlur=false;/** * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 * @type {number} * @default 0.7 */this.lastFrameAlpha=0.7;/** * Layer dpr * @type {number} */this.dpr=dpr;};Layer.prototype={constructor:Layer,__dirty:true,__used:false,__drawIndex:0,__startIndex:0,__endIndex:0,incremental:false,getElementCount:function(){returnthis.__endIndex-this.__startIndex;},initContext:function(){this.ctx=this.dom.getContext('2d');this.ctx.dpr=this.dpr;},createBackBuffer:function(){vardpr=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);}},/** * @param {number} width * @param {number} height */resize:function(width,height){vardpr=this.dpr;vardom=this.dom;vardomStyle=dom.style;vardomBack=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);}}},/** * 清空该层画布 * @param {boolean} [clearAll]=false Clear all with out motion blur * @param {Color} [clearColor] */clear:function(clearAll,clearColor){vardom=this.dom;varctx=this.ctx;varwidth=dom.width;varheight=dom.height;varclearColor=clearColor||this.clearColor;varhaveMotionBLur=this.motionBlur&&!clearAll;varlastFrameAlpha=this.lastFrameAlpha;vardpr=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'){varclearColorGradientOrPattern;// Gradientif(clearColor.colorStops){// Cache canvas gradientclearColorGradientOrPattern=clearColor.__canvasGradient||Style.getGradient(ctx,clearColor,{x:0,y:0,width:width,height:height});clearColor.__canvasGradient=clearColorGradientOrPattern;}// Patternelseif(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){vardomBack=this.domBack;ctx.save();ctx.globalAlpha=lastFrameAlpha;ctx.drawImage(domBack,0,0,width,height);ctx.restore();}}};varrequestAnimationFrame=(typeofwindow!=='undefined'&&((window.requestAnimationFrame&&window.requestAnimationFrame.bind(window))// https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809||(window.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window))||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame))||function(func){setTimeout(func,16);};varglobalImageCache=newLRU(50);/** * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image */functionfindExistImage(newImageOrSrc){if(typeofnewImageOrSrc==='string'){varcachedImgObj=globalImageCache.get(newImageOrSrc);returncachedImgObj&&cachedImgObj.image;}else{returnnewImageOrSrc;}}/** * Caution: User should cache loaded images, but not just count on LRU. * Consider if required images more than LRU size, will dead loop occur? * * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc * @param {HTMLImageElement|HTMLCanvasElement|Canvas} image Existent image. * @param {module:zrender/Element}[hostEl]Forcalling`dirty`.*@param{Function}[cb]params:(image,cbPayload)*@param{Object}[cbPayload]Payloadoncbcalling.*@return{HTMLImageElement|HTMLCanvasElement|Canvas}image*/function createOrUpdateImage(newImageOrSrc, image, hostEl, cb, cbPayload) { if (!newImageOrSrc) { return image; } else if (typeof newImageOrSrc === 'string') { //Imageshouldnotbeloadedrepeatly.if((image&&image.__zrImageSrc===newImageOrSrc)||!hostEl){returnimage;}// Only when there is no existent image or existent image src// is different, this method is responsible for load.varcachedImgObj=globalImageCache.get(newImageOrSrc);varpendingWrap={hostEl:hostEl,cb:cb,cbPayload:cbPayload};if(cachedImgObj){image=cachedImgObj.image;!isImageReady(image)&&cachedImgObj.pending.push(pendingWrap);}else{!image&&(image=newImage());image.onload=image.onerror=imageOnLoad;globalImageCache.put(newImageOrSrc,image.__cachedImgObj={image:image,pending:[pendingWrap]});image.src=image.__zrImageSrc=newImageOrSrc;}returnimage;}// newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvaselse{returnnewImageOrSrc;}}functionimageOnLoad(){varcachedImgObj=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(vari=0;i<cachedImgObj.pending.length;i++){varpendingWrap=cachedImgObj.pending[i];varcb=pendingWrap.cb;cb&&cb(this,pendingWrap.cbPayload);pendingWrap.hostEl.dirty();}cachedImgObj.pending.length=0;}functionisImageReady(image){returnimage&&image.width&&image.height;}vartextWidthCache={};vartextWidthCacheCounter=0;varTEXT_CACHE_MAX=5000;varSTYLE_REG=/\{([a-zA-Z0-9_]+)\|([^}]*)\}/g;varDEFAULT_FONT='12px sans-serif';// Avoid assign to an exported variable, for transforming to cjs.varmethods$1={};/** * @public * @param {string} text * @param {string} font * @return {number} width */functiongetWidth(text,font){font=font||DEFAULT_FONT;varkey=text+':'+font;if(textWidthCache[key]){returntextWidthCache[key];}vartextLines=(text+'').split('\n');varwidth=0;for(vari=0,l=textLines.length;i<l;i++){// textContain.measureText may be overrided in SVG or VMLwidth=Math.max(measureText(textLines[i],font).width,width);}if(textWidthCacheCounter>TEXT_CACHE_MAX){textWidthCacheCounter=0;textWidthCache={};}textWidthCacheCounter++;textWidthCache[key]=width;returnwidth;}/** * @public * @param {string} text * @param {string} font * @param {string} [textAlign='left'] * @param {string} [textVerticalAlign='top'] * @param {Array.<number>} [textPadding] * @param {Object} [rich] * @param {Object} [truncate] * @return {Object} {x, y, width, height, lineHeight} */functiongetBoundingRect(text,font,textAlign,textVerticalAlign,textPadding,rich,truncate){returnrich?getRichTextRect(text,font,textAlign,textVerticalAlign,textPadding,rich,truncate):getPlainTextRect(text,font,textAlign,textVerticalAlign,textPadding,truncate);}functiongetPlainTextRect(text,font,textAlign,textVerticalAlign,textPadding,truncate){varcontentBlock=parsePlainText(text,font,textPadding,truncate);varouterWidth=getWidth(text,font);if(textPadding){outerWidth+=textPadding[1]+textPadding[3];}varouterHeight=contentBlock.outerHeight;varx=adjustTextX(0,outerWidth,textAlign);vary=adjustTextY(0,outerHeight,textVerticalAlign);varrect=newBoundingRect(x,y,outerWidth,outerHeight);rect.lineHeight=contentBlock.lineHeight;returnrect;}functiongetRichTextRect(text,font,textAlign,textVerticalAlign,textPadding,rich,truncate){varcontentBlock=parseRichText(text,{rich:rich,truncate:truncate,font:font,textAlign:textAlign,textPadding:textPadding});varouterWidth=contentBlock.outerWidth;varouterHeight=contentBlock.outerHeight;varx=adjustTextX(0,outerWidth,textAlign);vary=adjustTextY(0,outerHeight,textVerticalAlign);returnnewBoundingRect(x,y,outerWidth,outerHeight);}/** * @public * @param {number} x * @param {number} width * @param {string} [textAlign='left'] * @return {number} Adjusted x. */functionadjustTextX(x,width,textAlign){// FIXME Right to left languageif(textAlign==='right'){x-=width;}elseif(textAlign==='center'){x-=width/2;}returnx;}/** * @public * @param {number} y * @param {number} height * @param {string} [textVerticalAlign='top'] * @return {number} Adjusted y. */functionadjustTextY(y,height,textVerticalAlign){if(textVerticalAlign==='middle'){y-=height/2;}elseif(textVerticalAlign==='bottom'){y-=height;}returny;}/** * @public * @param {stirng} textPosition * @param {Object} rect {x, y, width, height} * @param {number} distance * @return {Object} {x, y, textAlign, textVerticalAlign} */functionadjustTextPositionOnRect(textPosition,rect,distance){varx=rect.x;vary=rect.y;varheight=rect.height;varwidth=rect.width;varhalfHeight=height/2;vartextAlign='left';vartextVerticalAlign='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;}return{x:x,y:y,textAlign:textAlign,textVerticalAlign:textVerticalAlign};}/** * Show ellipsis if overflow. * * @public * @param {string} text * @param {string} containerWidth * @param {string} font * @param {number} [ellipsis='...'] * @param {Object} [options] * @param {number} [options.maxIterations=3] * @param {number} [options.minChar=0] If truncate result are less * then minChar, ellipsis will not show, which is * better for user hint in some cases. * @param {number} [options.placeholder=''] When all truncated, use the placeholder. * @return {string} */functiontruncateText(text,containerWidth,font,ellipsis,options){if(!containerWidth){return'';}vartextLines=(text+'').split('\n');options=prepareTruncateOptions(containerWidth,font,ellipsis,options);// FIXME// It is not appropriate that every line has '...' when truncate multiple lines.for(vari=0,len=textLines.length;i<len;i++){textLines[i]=truncateSingleLine(textLines[i],options);}returntextLines.join('\n');}functionprepareTruncateOptions(containerWidth,font,ellipsis,options){options=extend({},options);options.font=font;varellipsis=retrieve2(ellipsis,'...');options.maxIterations=retrieve2(options.maxIterations,2);varminChar=options.minChar=retrieve2(options.minChar,0);// FIXME// Other languages?options.cnCharWidth=getWidth('国',font);// FIXME// Consider proportional font?varascCharWidth=options.ascCharWidth=getWidth('a',font);options.placeholder=retrieve2(options.placeholder,'');// Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'.// Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'.varcontentWidth=containerWidth=Math.max(0,containerWidth-1);// Reserve some gap.for(vari=0;i<minChar&&contentWidth>=ascCharWidth;i++){contentWidth-=ascCharWidth;}varellipsisWidth=getWidth(ellipsis);if(ellipsisWidth>contentWidth){ellipsis='';ellipsisWidth=0;}contentWidth=containerWidth-ellipsisWidth;options.ellipsis=ellipsis;options.ellipsisWidth=ellipsisWidth;options.contentWidth=contentWidth;options.containerWidth=containerWidth;returnoptions;}functiontruncateSingleLine(textLine,options){varcontainerWidth=options.containerWidth;varfont=options.font;varcontentWidth=options.contentWidth;if(!containerWidth){return'';}varlineWidth=getWidth(textLine,font);if(lineWidth<=containerWidth){returntextLine;}for(varj=0;;j++){if(lineWidth<=contentWidth||j>=options.maxIterations){textLine+=options.ellipsis;break;}varsubLength=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;}returntextLine;}functionestimateLength(text,contentWidth,ascCharWidth,cnCharWidth){varwidth=0;vari=0;for(varlen=text.length;i<len&&width<contentWidth;i++){varcharCode=text.charCodeAt(i);width+=(0<=charCode&&charCode<=127)?ascCharWidth:cnCharWidth;}returni;}/** * @public * @param {string} font * @return {number} line height */functiongetLineHeight(font){// FIXME A rough approach.returngetWidth('国',font);}/** * @public * @param {string} text * @param {string} font * @return {Object} width */functionmeasureText(text,font){returnmethods$1.measureText(text,font);}// Avoid assign to an exported variable, for transforming to cjs.methods$1.measureText=function(text,font){varctx=getContext();ctx.font=font||DEFAULT_FONT;returnctx.measureText(text);};/** * @public * @param {string} text * @param {string} font * @param {Object} [truncate] * @return {Object} block: {lineHeight, lines, height, outerHeight} * Notice: for performance, do not calculate outerWidth util needed. */functionparsePlainText(text,font,padding,truncate){text!=null&&(text+='');varlineHeight=getLineHeight(font);varlines=text?text.split('\n'):[];varheight=lines.length*lineHeight;varouterHeight=height;if(padding){outerHeight+=padding[0]+padding[2];}if(text&&truncate){vartruncOuterHeight=truncate.outerHeight;vartruncOuterWidth=truncate.outerWidth;if(truncOuterHeight!=null&&outerHeight>truncOuterHeight){text='';lines=[];}elseif(truncOuterWidth!=null){varoptions=prepareTruncateOptions(truncOuterWidth-(padding?padding[1]+padding[3]:0),font,truncate.ellipsis,{minChar:truncate.minChar,placeholder:truncate.placeholder});// FIXME// It is not appropriate that every line has '...' when truncate multiple lines.for(vari=0,len=lines.length;i<len;i++){lines[i]=truncateSingleLine(lines[i],options);}}}return{lines:lines,height:height,outerHeight:outerHeight,lineHeight:lineHeight};}/** * For example: 'some text {a|some text}other text{b|some text}xxx{c|}xxx' * Also consider 'bbbb{a|xxx\nzzz}xxxx\naaaa'. * * @public * @param {string} text * @param {Object} style * @return {Object} block * { * width, * height, * lines: [{ * lineHeight, * width, * tokens: [[{ * styleName, * text, * width, // include textPadding * height, // include textPadding * textWidth, // pure text width * textHeight, // pure text height * lineHeihgt, * font, * textAlign, * textVerticalAlign * }], [...], ...] * }, ...] * } * If styleName is undefined, it is plain text. */functionparseRichText(text,style){varcontentBlock={lines:[],width:0,height:0};text!=null&&(text+='');if(!text){returncontentBlock;}varlastIndex=STYLE_REG.lastIndex=0;varresult;while((result=STYLE_REG.exec(text))!=null){varmatchedIndex=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));}varlines=contentBlock.lines;varcontentHeight=0;varcontentWidth=0;// For `textWidth: 100%`varpendingList=[];varstlPadding=style.textPadding;vartruncate=style.truncate;vartruncateWidth=truncate&&truncate.outerWidth;vartruncateHeight=truncate&&truncate.outerHeight;if(stlPadding){truncateWidth!=null&&(truncateWidth-=stlPadding[1]+stlPadding[3]);truncateHeight!=null&&(truncateHeight-=stlPadding[0]+stlPadding[2]);}// Calculate layout info of tokens.for(vari=0;i<lines.length;i++){varline=lines[i];varlineHeight=0;varlineWidth=0;for(varj=0;j<line.tokens.length;j++){vartoken=line.tokens[j];vartokenStyle=token.styleName&&style.rich[token.styleName]||{};// textPadding should not inherit from style.vartextPadding=token.textPadding=tokenStyle.textPadding;// textFont has been asigned to font by `normalizeStyle`.varfont=token.font=tokenStyle.font||style.font;// textHeight can be used when textVerticalAlign is specified in token.vartokenHeight=token.textHeight=retrieve2(// textHeight should not be inherited, consider it can be specified// as box height of the block.tokenStyle.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);vartokenWidth=tokenStyle.textWidth;vartokenWidthNotSpecified=tokenWidth==null||tokenWidth==='auto';// Percent width, can be `100%`, can be used in drawing separate// line when box width is needed to be auto.if(typeoftokenWidth==='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// and it is too complicated.}else{if(tokenWidthNotSpecified){tokenWidth=token.textWidth;// FIXME: If image is not loaded and textWidth is not specified, calling// `getBoundingRect()` will not get correct result.vartextBackgroundColor=tokenStyle.textBackgroundColor;varbgImg=textBackgroundColor&&textBackgroundColor.image;// Use cases:// (1) If image is not loaded, it will be loaded at render phase and call// `dirty()` and `textBackgroundColor.image` will be replaced with the loaded// image, and then the right size will be calculated here at the next tick.// See `graphic/helper/text.js`.// (2) If image loaded, and `textBackgroundColor.image` is image src string,// use `imageHelper.findExistImage` to find cached image.// `imageHelper.findExistImage` will always be called here before// `imageHelper.createOrUpdateImage` in `graphic/helper/text.js#renderRichText`// which ensures that image will not be rendered before correct size calcualted.if(bgImg){bgImg=findExistImage(bgImg);if(isImageReady(bgImg)){tokenWidth=Math.max(tokenWidth,bgImg.width*tokenHeight/bgImg.height);}}}varpaddingW=textPadding?textPadding[1]+textPadding[3]:0;tokenWidth+=paddingW;varremianTruncWidth=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(vari=0;i<pendingList.length;i++){vartoken=pendingList[i];varpercentWidth=token.percentWidth;// Should not base on outerWidth, because token can not be placed out of padding.token.width=parseInt(percentWidth,10)/100*contentWidth;}returncontentBlock;}functionpushTokens(block,str,styleName){varisEmptyStr=str==='';varstrs=str.split('\n');varlines=block.lines;for(vari=0;i<strs.length;i++){vartext=strs[i];vartoken={styleName:styleName,text:text,isLineHolder:!text&&!isEmptyStr};// The first token should be appended to the last line.if(!i){vartokens=(lines[lines.length-1]||(lines[0]={tokens:[]})).tokens;// Consider cases:// (1) ''.split('\n') => ['', '\n', ''], the '' at the first item// (which is a placeholder) should be replaced by new token.// (2) A image backage, where token likes {a|}.// (3) A redundant '' will affect textAlign in line.// (4) tokens with the same tplName should not be merged, because// they should be displayed in different box (with border and padding).vartokensLen=tokens.length;(tokensLen===1&&tokens[0].isLineHolder)?(tokens[0]=token)// Consider text is '', only insert when it is the "lineHolder" or// "emptyStr". Otherwise a redundant '' will affect textAlign in line.:((text||!tokensLen||isEmptyStr)&&tokens.push(token));}// Other tokens always start a new line.else{// If there is '', insert it as a placeholder.lines.push({tokens:[token]});}}}functionmakeFont(style){// FIXME in node-canvas fontWeight is before fontStyle// Use `fontSize` `fontFamily` to check whether font properties are defined.varfont=(style.fontSize||style.fontFamily)&&[style.fontStyle,style.fontWeight,(style.fontSize||12)+'px',// If font properties are defined, `fontFamily` should not be ignored.style.fontFamily||'sans-serif'].join(' ');returnfont&&trim(font)||style.textFont||style.font;}functionbuildPath(ctx,shape){varx=shape.x;vary=shape.y;varwidth=shape.width;varheight=shape.height;varr=shape.r;varr1;varr2;varr3;varr4;// Convert width and height to positive for better borderRadiusif(width<0){x=x+width;width=-width;}if(height<0){y=y+height;height=-height;}if(typeofr==='number'){r1=r2=r3=r4=r;}elseif(rinstanceofArray){if(r.length===1){r1=r2=r3=r4=r[0];}elseif(r.length===2){r1=r3=r[0];r2=r4=r[1];}elseif(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;}vartotal;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);}// TODO: Have not support 'start', 'end' yet.varVALID_TEXT_ALIGN={left:1,right:1,center:1};varVALID_TEXT_VERTICAL_ALIGN={top:1,bottom:1,middle:1};// Different from `STYLE_COMMON_PROPS` of `graphic/Style`,// the default value of shadowColor is `'transparent'`.varSHADOW_STYLE_COMMON_PROPS=[['textShadowBlur','shadowBlur',0],['textShadowOffsetX','shadowOffsetX',0],['textShadowOffsetY','shadowOffsetY',0],['textShadowColor','shadowColor','transparent']];/** * @param {module:zrender/graphic/Style}style*@return{module:zrender/graphic/Style}Theinputstyle.*/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'; //CompatiblewithtextBaseline.vartextVerticalAlign=style.textVerticalAlign||style.textBaseline;textVerticalAlign==='center'&&(textVerticalAlign='middle');style.textVerticalAlign=(textVerticalAlign==null||VALID_TEXT_VERTICAL_ALIGN[textVerticalAlign])?textVerticalAlign:'top';vartextPadding=style.textPadding;if(textPadding){style.textPadding=normalizeCssArray(style.textPadding);}}}/** * @param {CanvasRenderingContext2D} ctx * @param {string} text * @param {module:zrender/graphic/Style}style*@param{Object|boolean}[rect]{x,y,width,height}*Ifsetfalse,recttextisnotused.*@param{Element}[prevEl]Forctxpropcache.*/function renderText(hostEl, ctx, text, style, rect, prevEl) { style.rich? renderRichText(hostEl, ctx, text, style, rect) : renderPlainText(hostEl, ctx, text, style, rect, prevEl);}//AvoidsettingtoctxaccordingtoprevElifpossiblefor// performance in scenarios of large amount text.functionrenderPlainText(hostEl,ctx,text,style,rect,prevEl){'use strict';varprevStyle=prevEl&&prevEl.style;// Some cache only available on textEl.varisPrevTextEl=prevStyle&&prevEl.type==='text';varstyleFont=style.font||DEFAULT_FONT;if(!isPrevTextEl||styleFont!==(prevStyle.font||DEFAULT_FONT)){ctx.font=styleFont;}// Use the final font from context-2d, because the final// font might not be the style.font when it is illegal.// But get `ctx.font` might be time consuming.varcomputedFont=hostEl.__computedFont;if(hostEl.__styleFont!==styleFont){hostEl.__styleFont=styleFont;computedFont=hostEl.__computedFont=ctx.font;}vartextPadding=style.textPadding;varcontentBlock=hostEl.__textCotentBlock;if(!contentBlock||hostEl.__dirtyText){contentBlock=hostEl.__textCotentBlock=parsePlainText(text,computedFont,textPadding,style.truncate);}varouterHeight=contentBlock.outerHeight;vartextLines=contentBlock.lines;varlineHeight=contentBlock.lineHeight;varboxPos=getBoxPosition(outerHeight,style,rect);varbaseX=boxPos.baseX;varbaseY=boxPos.baseY;vartextAlign=boxPos.textAlign||'left';vartextVerticalAlign=boxPos.textVerticalAlign;// Origin of textRotation should be the base point of text drawing.applyTextRotation(ctx,style,rect,baseX,baseY);varboxY=adjustTextY(baseY,outerHeight,textVerticalAlign);vartextX=baseX;vartextY=boxY;varneedDrawBg=needDrawBackground(style);if(needDrawBg||textPadding){// Consider performance, do not call getTextWidth util necessary.vartextWidth=getWidth(text,computedFont);varouterWidth=textWidth;textPadding&&(outerWidth+=textPadding[1]+textPadding[3]);varboxX=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// textAlign from prevEl, and we dont sure whether textAlign will be reset if// font set happened.ctx.textAlign=textAlign;// Force baseline to be "middle". Otherwise, if using "top", the// text will offset downward a little bit in font "Microsoft YaHei".ctx.textBaseline='middle';// Always set shadowBlur and shadowOffset to avoid leak from displayable.for(vari=0;i<SHADOW_STYLE_COMMON_PROPS.length;i++){varpropItem=SHADOW_STYLE_COMMON_PROPS[i];varstyleProp=propItem[0];varctxProp=propItem[1];varval=style[styleProp];if(!isPrevTextEl||val!==prevStyle[styleProp]){ctx[ctxProp]=fixShadow(ctx,ctxProp,val||propItem[2]);}}// `textBaseline` is set as 'middle'.textY+=lineHeight/2;vartextStrokeWidth=style.textStrokeWidth;vartextStrokeWidthPrev=isPrevTextEl?prevStyle.textStrokeWidth:null;varstrokeWidthChanged=!isPrevTextEl||textStrokeWidth!==textStrokeWidthPrev;varstrokeChanged=!isPrevTextEl||strokeWidthChanged||style.textStroke!==prevStyle.textStroke;vartextStroke=getStroke(style.textStroke,textStrokeWidth);vartextFill=getFill(style.textFill);if(textStroke){if(strokeWidthChanged){ctx.lineWidth=textStrokeWidth;}if(strokeChanged){ctx.strokeStyle=textStroke;}}if(textFill){if(!isPrevTextEl||style.textFill!==prevStyle.textFill||prevStyle.textBackgroundColor){ctx.fillStyle=textFill;}}// Optimize simply, in most cases only one line exists.if(textLines.length===1){// Fill after stroke so the outline will not cover the main part.textStroke&&ctx.strokeText(textLines[0],textX,textY);textFill&&ctx.fillText(textLines[0],textX,textY);}else{for(vari=0;i<textLines.length;i++){// Fill after stroke so the outline will not cover the main part.textStroke&&ctx.strokeText(textLines[i],textX,textY);textFill&&ctx.fillText(textLines[i],textX,textY);textY+=lineHeight;}}}functionrenderRichText(hostEl,ctx,text,style,rect){varcontentBlock=hostEl.__textCotentBlock;if(!contentBlock||hostEl.__dirtyText){contentBlock=hostEl.__textCotentBlock=parseRichText(text,style);}drawRichText(hostEl,ctx,contentBlock,style,rect);}functiondrawRichText(hostEl,ctx,contentBlock,style,rect){varcontentWidth=contentBlock.width;varouterWidth=contentBlock.outerWidth;varouterHeight=contentBlock.outerHeight;vartextPadding=style.textPadding;varboxPos=getBoxPosition(outerHeight,style,rect);varbaseX=boxPos.baseX;varbaseY=boxPos.baseY;vartextAlign=boxPos.textAlign;vartextVerticalAlign=boxPos.textVerticalAlign;// Origin of textRotation should be the base point of text drawing.applyTextRotation(ctx,style,rect,baseX,baseY);varboxX=adjustTextX(baseX,outerWidth,textAlign);varboxY=adjustTextY(baseY,outerHeight,textVerticalAlign);varxLeft=boxX;varlineTop=boxY;if(textPadding){xLeft+=textPadding[3];lineTop+=textPadding[0];}varxRight=xLeft+contentWidth;needDrawBackground(style)&&drawBackground(hostEl,ctx,style,boxX,boxY,outerWidth,outerHeight);for(vari=0;i<contentBlock.lines.length;i++){varline=contentBlock.lines[i];vartokens=line.tokens;vartokenCount=tokens.length;varlineHeight=line.lineHeight;varusedWidth=line.width;varleftIndex=0;varlineXLeft=xLeft;varlineXRight=xRight;varrightIndex=tokenCount-1;vartoken;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.lineXLeft+=(contentWidth-(lineXLeft-xLeft)-(xRight-lineXRight)-usedWidth)/2;while(leftIndex<=rightIndex){token=tokens[leftIndex];// Consider width specified by user, use 'center' rather than 'left'.placeToken(hostEl,ctx,token,style,lineHeight,lineTop,lineXLeft+token.width/2,'center');lineXLeft+=token.width;leftIndex++;}lineTop+=lineHeight;}}functionapplyTextRotation(ctx,style,rect,x,y){// textRotation only apply in RectText.if(rect&&style.textRotation){varorigin=style.textOrigin;if(origin==='center'){x=rect.width/2+rect.x;y=rect.height/2+rect.y;}elseif(origin){x=origin[0]+rect.x;y=origin[1]+rect.y;}ctx.translate(x,y);// Positive: anticlockwisectx.rotate(-style.textRotation);ctx.translate(-x,-y);}}functionplaceToken(hostEl,ctx,token,style,lineHeight,lineTop,x,textAlign){vartokenStyle=style.rich[token.styleName]||{};tokenStyle.text=token.text;// 'ctx.textBaseline' is always set as 'middle', for sake of// the bias of "Microsoft YaHei".vartextVerticalAlign=token.textVerticalAlign;vary=lineTop+lineHeight/2;if(textVerticalAlign==='top'){y=lineTop+token.height/2;}elseif(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);vartextPadding=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// text will offset downward a little bit in font "Microsoft YaHei".setCtx(ctx,'textBaseline','middle');setCtx(ctx,'font',token.font||DEFAULT_FONT);vartextStroke=getStroke(tokenStyle.textStroke||style.textStroke,textStrokeWidth);vartextFill=getFill(tokenStyle.textFill||style.textFill);vartextStrokeWidth=retrieve2(tokenStyle.textStrokeWidth,style.textStrokeWidth);// Fill after stroke so the outline will not cover the main part.if(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);}}functionneedDrawBackground(style){returnstyle.textBackgroundColor||(style.textBorderWidth&&style.textBorderColor);}// style: {textBackgroundColor, textBorderWidth, textBorderColor, textBorderRadius, text}// shape: {x, y, width, height}functiondrawBackground(hostEl,ctx,style,x,y,width,height){vartextBackgroundColor=style.textBackgroundColor;vartextBorderWidth=style.textBorderWidth;vartextBorderColor=style.textBorderColor;varisPlainBg=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();vartextBorderRadius=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){varoriginalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.fillOpacity*style.opacity;ctx.fill();ctx.globalAlpha=originalGlobalAlpha;}else{ctx.fill();}}elseif(isFunction$1(textBackgroundColor)){setCtx(ctx,'fillStyle',textBackgroundColor(style));ctx.fill();}elseif(isObject$1(textBackgroundColor)){varimage=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){varoriginalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.strokeOpacity*style.opacity;ctx.stroke();ctx.globalAlpha=originalGlobalAlpha;}else{ctx.stroke();}}}functiononBgImageLoaded(image,textBackgroundColor){// Replace image, so that `contain/text.js#parseRichText`// will get correct result in next tick.textBackgroundColor.image=image;}functiongetBoxPosition(blockHeiht,style,rect){varbaseX=style.x||0;varbaseY=style.y||0;vartextAlign=style.textAlign;vartextVerticalAlign=style.textVerticalAlign;// Text position represented by coordif(rect){vartextPosition=style.textPosition;if(textPositioninstanceofArray){// PercentbaseX=rect.x+parsePercent(textPosition[0],rect.width);baseY=rect.y+parsePercent(textPosition[1],rect.height);}else{varres=adjustTextPositionOnRect(textPosition,rect,style.textDistance);baseX=res.x;baseY=res.y;// Default align and baseline when has textPositiontextAlign=textAlign||res.textAlign;textVerticalAlign=textVerticalAlign||res.textVerticalAlign;}// textOffset is only support in RectText, otherwise// we have to adjust boundingRect for textOffset.vartextOffset=style.textOffset;if(textOffset){baseX+=textOffset[0];baseY+=textOffset[1];}}return{baseX:baseX,baseY:baseY,textAlign:textAlign,textVerticalAlign:textVerticalAlign};}functionsetCtx(ctx,prop,value){ctx[prop]=fixShadow(ctx,prop,value);returnctx[prop];}/** * @param {string} [stroke] If specified, do not check style.textStroke. * @param {string} [lineWidth] If specified, do not check style.textStroke. * @param {number} style */functiongetStroke(stroke,lineWidth){return(stroke==null||lineWidth<=0||stroke==='transparent'||stroke==='none')?null// TODO pattern and gradient?:(stroke.image||stroke.colorStops)?'#000':stroke;}functiongetFill(fill){return(fill==null||fill==='none')?null// TODO pattern and gradient?:(fill.image||fill.colorStops)?'#000':fill;}functionparsePercent(value,maxValue){if(typeofvalue==='string'){if(value.lastIndexOf('%')>=0){returnparseFloat(value)/100*maxValue;}returnparseFloat(value);}returnvalue;}functiongetTextXForPadding(x,textAlign,textPadding){returntextAlign==='right'?(x-textPadding[1]):textAlign==='center'?(x+textPadding[3]/2-textPadding[1]/2):(x+textPadding[3]);}/** * @param {string} text * @param {module:zrender/Style}style*@return{boolean}*/function needDrawText(text, style) { return text != null && (text || style.textBackgroundColor || (style.textBorderWidth && style.textBorderColor) || style.textPadding);}/***Mixinfordrawingtextinaelementboundingrect*@modulezrender/mixin/RectText*/var tmpRect$1 = new BoundingRect();var RectText = function () {};RectText.prototype = { constructor: RectText, /***Drawtextinarectwithspecifiedposition.*@param{CanvasRenderingContext2D}ctx*@param{Object}rectDisplayablerect*/ drawRectText: function (ctx, rect) { var style = this.style; rect = style.textRect || rect; //Optimize,avoidnormalizeeverytime.this.__dirty&&normalizeTextStyle(style,true);vartext=style.text;// Convert to stringtext!=null&&(text+='');if(!needDrawText(text,style)){return;}// FIXME// Do not provide prevEl to `textHelper.renderText` for ctx prop cache,// but use `ctx.save()` and `ctx.restore()`. Because the cache for rect// text propably break the cache for its host elements.ctx.save();// Transform rect to view spacevartransform=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.renderText(this,ctx,text,style,rect);ctx.restore();}};/** * 可绘制的图形基类 * Base class of all displayable graphic objects * @module zrender/graphic/Displayable*//***@aliasmodule:zrender/graphic/Displayable*@extendsmodule:zrender/Element*@extendsmodule:zrender/graphic/mixin/RectText*/function Displayable(opts) { opts = opts || {}; Element.call(this, opts); //Extendpropertiesfor(varnameinopts){if(opts.hasOwnProperty(name)&&name!=='style'){this[name]=opts[name];}}/** * @type {module:zrender/graphic/Style}*/ this.style = new Style(opts.style, this); this._rect = null; //Shapesforcascadeclipping.this.__clipPaths=[];// FIXME Stateful must be mixined after style is setted// Stateful.call(this, opts);}Displayable.prototype={constructor:Displayable,type:'displayable',/** * Displayable 是否为脏,Painter 中会根据该标记判断是否需要是否需要重新绘制 * Dirty flag. From which painter will determine if this displayable object needs brush * @name module:zrender/graphic/Displayable#__dirty*@type{boolean}*/ __dirty: true, /***图形是否可见,为true时不绘制图形,但是仍能触发鼠标事件*Ifignoredrawingofthedisplayableobject.Mouseeventwillstillbetriggered*@namemodule:/zrender/graphic/Displayable#invisible*@type{boolean}*@defaultfalse*/ invisible: false, /***@namemodule:/zrender/graphic/Displayable#z*@type{number}*@default0*/ z: 0, /***@namemodule:/zrender/graphic/Displayable#z*@type{number}*@default0*/ z2: 0, /***z层level,决定绘画在哪层canvas中*@namemodule:/zrender/graphic/Displayable#zlevel*@type{number}*@default0*/ zlevel: 0, /***是否可拖拽*@namemodule:/zrender/graphic/Displayable#draggable*@type{boolean}*@defaultfalse*/ draggable: false, /***是否正在拖拽*@namemodule:/zrender/graphic/Displayable#draggable*@type{boolean}*@defaultfalse*/ dragging: false, /***是否相应鼠标事件*@namemodule:/zrender/graphic/Displayable#silent*@type{boolean}*@defaultfalse*/ silent: false, /***Ifenableculling*@type{boolean}*@defaultfalse*/ culling: false, /***Mousecursorwhenhovered*@namemodule:/zrender/graphic/Displayable#cursor*@type{string}*/ cursor: 'pointer', /***Ifhoverareaisboundingrect*@namemodule:/zrender/graphic/Displayable#rectHover*@type{string}*/ rectHover: false, /***Rendertheelementprogressivelywhenthevalue>=0,*usefullforlargedata.*@type{boolean}*/ progressive: false, /***@type{boolean}*/ incremental: false, /***Scaleratioforglobalscale.*@type{boolean}*/ globalScaleRatio: 1, beforeBrush: function (ctx) {}, afterBrush: function (ctx) {}, /***图形绘制方法*@param{CanvasRenderingContext2D}ctx*/ //Interfacebrush:function(ctx,prevEl){},/** * 获取最小包围盒 * @return {module:zrender/core/BoundingRect}*/ //InterfacegetBoundingRect:function(){},/** * 判断坐标 x, y 是否在图形上 * If displayable element contain coord x, y * @param {number} x * @param {number} y * @return {boolean} */contain:function(x,y){returnthis.rectContain(x,y);},/** * @param {Function} cb * @param {} context */traverse:function(cb,context){cb.call(context,this);},/** * 判断坐标 x, y 是否在图形的包围盒上 * If bounding rect of element contain coord x, y * @param {number} x * @param {number} y * @return {boolean} */rectContain:function(x,y){varcoord=this.transformCoordToLocal(x,y);varrect=this.getBoundingRect();returnrect.contain(coord[0],coord[1]);},/** * 标记图形元素为脏,并且在下一帧重绘 * Mark displayable element dirty and refresh next frame */dirty:function(){this.__dirty=this.__dirtyText=true;this._rect=null;this.__zr&&this.__zr.refresh();},/** * 图形是否会触发事件 * If displayable object binded any event * @return {boolean} */// TODO, 通过 bind 绑定的事件// isSilent: function () {// return !(// this.hoverable || this.draggable// || this.onmousemove || this.onmouseover || this.onmouseout// || this.onmousedown || this.onmouseup || this.onclick// || this.ondragenter || this.ondragover || this.ondragleave// || this.ondrop// );// },/***Aliasforanimate('style')*@param{boolean}loop*/ animateStyle: function (loop) { return this.animate('style', loop); }, attrKV: function (key, value) { if (key !== 'style') { Element.prototype.attrKV.call(this, key, value); } else { this.style.set(value); } }, /***@param{Object|string}key*@param{*}value*/ setStyle: function (key, value) { this.style.set(key, value); this.dirty(false); return this; }, /***Usegivenstyleobject*@param{Object}obj*/ useStyle: function (obj) { this.style = new Style(obj, this); this.dirty(false); return this; }};inherits(Displayable, Element);mixin(Displayable, RectText);/***@aliaszrender/graphic/Image*@extendsmodule:zrender/graphic/Displayable*@constructor*@param{Object}opts*/function ZImage(opts) { Displayable.call(this, opts);}ZImage.prototype = { constructor: ZImage, type: 'image', brush: function (ctx, prevEl) { var style = this.style; var src = style.image; //Mustbindeachtimestyle.bind(ctx,this,prevEl);varimage=this._image=createOrUpdateImage(src,this._image,this,this.onload);if(!image||!isImageReady(image)){return;}// 图片已经加载完成// if (image.nodeName.toUpperCase() == 'IMG') {// if (!image.complete) {// return;// }// }// Else is canvasvarx=style.x||0;vary=style.y||0;varwidth=style.width;varheight=style.height;varaspect=image.width/image.height;if(width==null&&height!=null){// Keep image/height ratiowidth=height*aspect;}elseif(height==null&&width!=null){height=width/aspect;}elseif(width==null&&height==null){width=image.width;height=image.height;}// 设置transformthis.setTransform(ctx);if(style.sWidth&&style.sHeight){varsx=style.sx||0;varsy=style.sy||0;ctx.drawImage(image,sx,sy,style.sWidth,style.sHeight,x,y,width,height);}elseif(style.sx&&style.sy){varsx=style.sx;varsy=style.sy;varsWidth=width-sx;varsHeight=height-sy;ctx.drawImage(image,sx,sy,sWidth,sHeight,x,y,width,height);}else{ctx.drawImage(image,x,y,width,height);}// Draw rect textif(style.text!=null){// Only restore transform when needs draw text.this.restoreTransform(ctx);this.drawRectText(ctx,this.getBoundingRect());}},getBoundingRect:function(){varstyle=this.style;if(!this._rect){this._rect=newBoundingRect(style.x||0,style.y||0,style.width||0,style.height||0);}returnthis._rect;}};inherits(ZImage,Displayable);varHOVER_LAYER_ZLEVEL=1e5;varCANVAS_ZLEVEL=314159;varEL_AFTER_INCREMENTAL_INC=0.01;varINCREMENTAL_INC=0.001;functionparseInt10(val){returnparseInt(val,10);}functionisLayerValid(layer){if(!layer){returnfalse;}if(layer.__builtin__){returntrue;}if(typeof(layer.resize)!=='function'||typeof(layer.refresh)!=='function'){returnfalse;}returntrue;}vartmpRect=newBoundingRect(0,0,0,0);varviewRect=newBoundingRect(0,0,0,0);functionisDisplayableCulled(el,width,height){tmpRect.copy(el.getBoundingRect());if(el.transform){tmpRect.applyTransform(el.transform);}viewRect.width=width;viewRect.height=height;return!tmpRect.intersect(viewRect);}functionisClipPathChanged(clipPaths,prevClipPaths){if(clipPaths==prevClipPaths){// Can both be null or undefinedreturnfalse;}if(!clipPaths||!prevClipPaths||(clipPaths.length!==prevClipPaths.length)){returntrue;}for(vari=0;i<clipPaths.length;i++){if(clipPaths[i]!==prevClipPaths[i]){returntrue;}}}functiondoClip(clipPaths,ctx){for(vari=0;i<clipPaths.length;i++){varclipPath=clipPaths[i];clipPath.setTransform(ctx);ctx.beginPath();clipPath.buildPath(ctx,clipPath.shape);ctx.clip();// Transform backclipPath.restoreTransform(ctx);}}functioncreateRoot(width,height){vardomRoot=document.createElement('div');// domRoot.onselectstart = returnFalse; // 避免页面选中的尴尬domRoot.style.cssText=['position:relative','overflow:hidden','width:'+width+'px','height:'+height+'px','padding:0','margin:0','border-width:0'].join(';')+';';returndomRoot;}/** * @alias module:zrender/Painter*@constructor*@param{HTMLElement}root绘图容器*@param{module:zrender/Storage}storage*@param{Object}opts*/var Painter = function (root, storage, opts) { this.type = 'canvas'; //Innodeenvironmentusingnode-canvasvarsingleCanvas=!root.nodeName// In node ?||root.nodeName.toUpperCase()==='CANVAS';this._opts=opts=extend({},opts||{});/** * @type {number} */this.dpr=opts.devicePixelRatio||devicePixelRatio;/** * @type {boolean} * @private */this._singleCanvas=singleCanvas;/** * 绘图容器 * @type {HTMLElement} */this.root=root;varrootStyle=root.style;if(rootStyle){rootStyle['-webkit-tap-highlight-color']='transparent';rootStyle['-webkit-user-select']=rootStyle['user-select']=rootStyle['-webkit-touch-callout']='none';root.innerHTML='';}/** * @type {module:zrender/Storage}*/ this.storage = storage; /***@type{Array.<number>}*@private*/ var zlevelList = this._zlevelList = []; /***@type{Object.<string,module:zrender/Layer>}*@private*/ var layers = this._layers = {}; /***@type{Object.<string,Object>}*@private*/ this._layerConfig = {}; /***zrenderwilldocompositingwhenrootisacanvasandhavemultiplezlevels.*/ 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; //Usecanvaswidthandheightdirectlyroot.width=width*this.dpr;root.height=height*this.dpr;this._width=width;this._height=height;// Create layer if only one given canvas// Device can be specified to create a high dpi image.varmainLayer=newLayer(root,this,this.dpr);mainLayer.__builtin__=true;mainLayer.initContext();// FIXME Use canvas width and height// mainLayer.resize(width, height);layers[CANVAS_ZLEVEL]=mainLayer;mainLayer.zlevel=CANVAS_ZLEVEL;// Not use common zlevel.zlevelList.push(CANVAS_ZLEVEL);this._domRoot=root;}/** * @type {module:zrender/Layer}*@private*/ this._hoverlayer = null; this._hoverElements = [];};Painter.prototype = { constructor: Painter, getType: function () { return 'canvas'; }, /***Ifpainteruseasinglecanvas*@return{boolean}*/ isSingleCanvas: function () { return this._singleCanvas; }, /***@return{HTMLDivElement}*/ getViewportRoot: function () { return this._domRoot; }, getViewportRootOffset: function () { var viewportRoot = this.getViewportRoot(); if (viewportRoot) { return { offsetLeft: viewportRoot.offsetLeft || 0, offsetTop: viewportRoot.offsetTop || 0 }; } }, /***刷新*@param{boolean}[paintAll=false]强制绘制所有displayable*/ refresh: function (paintAll) { var list = this.storage.getDisplayList(true); var zlevelList = this._zlevelList; this._redrawId = Math.random(); this._paintList(list, paintAll, this._redrawId); //Paintcustumlayersfor(vari=0;i<zlevelList.length;i++){varz=zlevelList[i];varlayer=this._layers[z];if(!layer.__builtin__&&layer.refresh){varclearColor=i===0?this._backgroundColor:null;layer.refresh(clearColor);}}this.refreshHover();returnthis;},addHover:function(el,hoverStyle){if(el.__hoverMir){return;}varelMirror=newel.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);returnelMirror;},removeHover:function(el){varelMirror=el.__hoverMir;varhoverElements=this._hoverElements;varidx=indexOf(hoverElements,elMirror);if(idx>=0){hoverElements.splice(idx,1);}el.__hoverMir=null;},clearHover:function(el){varhoverElements=this._hoverElements;for(vari=0;i<hoverElements.length;i++){varfrom=hoverElements[i].__from;if(from){from.__hoverMir=null;}}hoverElements.length=0;},refreshHover:function(){varhoverElements=this._hoverElements;varlen=hoverElements.length;varhoverLayer=this._hoverlayer;hoverLayer&&hoverLayer.clear();if(!len){return;}sort(hoverElements,this.storage.displayableSortFunc);// Use a extream large zlevel// FIXME?if(!hoverLayer){hoverLayer=this._hoverlayer=this.getLayer(HOVER_LAYER_ZLEVEL);}varscope={};hoverLayer.ctx.save();for(vari=0;i<len;){varel=hoverElements[i];varoriginalEl=el.__from;// Original el is removed// PENDINGif(!(originalEl&&originalEl.__zr)){hoverElements.splice(i,1);originalEl.__hoverMir=null;len--;continue;}i++;// Use transform// FIXME style and shape ?if(!originalEl.invisible){el.transform=originalEl.transform;el.invTransform=originalEl.invTransform;el.__clipPaths=originalEl.__clipPaths;// el.this._doPaintEl(el,hoverLayer,true,scope);}}hoverLayer.ctx.restore();},getHoverLayer:function(){returnthis.getLayer(HOVER_LAYER_ZLEVEL);},_paintList:function(list,paintAll,redrawId){if(this._redrawId!==redrawId){return;}paintAll=paintAll||false;this._updateLayerStatus(list);varfinished=this._doPaintList(list,paintAll);if(this._needsManuallyCompositing){this._compositeManually();}if(!finished){varself=this;requestAnimationFrame(function(){self._paintList(list,paintAll,redrawId);});}},_compositeManually:function(){varctx=this.getLayer(CANVAS_ZLEVEL).ctx;varwidth=this._domRoot.width;varheight=this._domRoot.height;ctx.clearRect(0,0,width,height);// PENDING, If only builtin layer?this.eachBuiltinLayer(function(layer){if(layer.virtual){ctx.drawImage(layer.dom,0,0,width,height);}});},_doPaintList:function(list,paintAll){varlayerList=[];for(varzi=0;zi<this._zlevelList.length;zi++){varzlevel=this._zlevelList[zi];varlayer=this._layers[zlevel];if(layer.__builtin__&&layer!==this._hoverlayer&&(layer.__dirty||paintAll)){layerList.push(layer);}}varfinished=true;for(vark=0;k<layerList.length;k++){varlayer=layerList[k];varctx=layer.ctx;varscope={};ctx.save();varstart=paintAll?layer.__startIndex:layer.__drawIndex;varuseTimer=!paintAll&&layer.incremental&&Date.now;varstartTime=useTimer&&Date.now();varclearColor=layer.zlevel===this._zlevelList[0]?this._backgroundColor:null;// All elements in this layer are cleared.if(layer.__startIndex===layer.__endIndex){layer.clear(false,clearColor);}elseif(start===layer.__startIndex){varfirstEl=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(vari=start;i<layer.__endIndex;i++){varel=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.vardTime=Date.now()-startTime;// Give 15 millisecond to draw.// The rest elements will be drawn in the next frame.if(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.ctx.restore();}ctx.restore();}if(env$1.wxa){// Flush for weixin applicationeach$1(this._layers,function(layer){if(layer&&layer.ctx&&layer.ctx.draw){layer.ctx.draw();}});}returnfinished;},_doPaintEl:function(el,currentLayer,forcePaint,scope){varctx=currentLayer.ctx;varm=el.transform;if((currentLayer.__dirty||forcePaint)// Ignore invisible element&&!el.invisible// Ignore transparent element&&el.style.opacity!==0// Ignore scale 0 element, in some environment like node-canvas// Draw a scale 0 element can cause all following draw wrong// And setTransform with scale 0 will cause set back transform failed.&&!(m&&!m[0]&&!m[3])// Ignore culled element&&!(el.culling&&isDisplayableCulled(el,this._width,this._height))){varclipPaths=el.__clipPaths;// Optimize when clipping on group with several elementsif(!scope.prevElClipPaths||isClipPathChanged(clipPaths,scope.prevElClipPaths)){// If has previous clipping state, restore from itif(scope.prevElClipPaths){currentLayer.ctx.restore();scope.prevElClipPaths=null;// Reset prevEl since context has been restoredscope.prevEl=null;}// New clipping stateif(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);}},/** * 获取 zlevel 所在层,如果不存在则会创建一个新的层 * @param {number} zlevel * @param {boolean} virtual Virtual layer will not be inserted into dom. * @return {module:zrender/Layer}*/ getLayer: function (zlevel, virtual) { if (this._singleCanvas && !this._needsManuallyCompositing) { zlevel = CANVAS_ZLEVEL; } var layer = this._layers[zlevel]; if (!layer) { //Createanewlayerlayer=newLayer('zr_'+zlevel,this,this.dpr);layer.zlevel=zlevel;layer.__builtin__=true;if(this._layerConfig[zlevel]){merge(layer,this._layerConfig[zlevel],true);}if(virtual){layer.virtual=virtual;}this.insertLayer(zlevel,layer);// Context is created after dom inserted to document// Or excanvas will get 0px clientWidth and clientHeightlayer.initContext();}returnlayer;},insertLayer:function(zlevel,layer){varlayersMap=this._layers;varzlevelList=this._zlevelList;varlen=zlevelList.length;varprevLayer=null;vari=-1;vardomRoot=this._domRoot;if(layersMap[zlevel]){log$1('ZLevel '+zlevel+' has been used already');return;}// Check if is a valid layerif(!isLayerValid(layer)){log$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.// (It can be a WebGL layer and assigned to a ZImage element)// But it still under management of zrender.if(!layer.virtual){if(prevLayer){varprevDom=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 layereachLayer:function(cb,context){varzlevelList=this._zlevelList;varz;vari;for(i=0;i<zlevelList.length;i++){z=zlevelList[i];cb.call(context,this._layers[z],z);}},// Iterate each buildin layereachBuiltinLayer:function(cb,context){varzlevelList=this._zlevelList;varlayer;varz;vari;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 layereachOtherLayer:function(cb,context){varzlevelList=this._zlevelList;varlayer;varz;vari;for(i=0;i<zlevelList.length;i++){z=zlevelList[i];layer=this._layers[z];if(!layer.__builtin__){cb.call(context,layer,z);}}},/** * 获取所有已创建的层 * @param {Array.<module:zrender/Layer>}[prevLayer]*/ getLayers: function () { return this._layers; }, _updateLayerStatus: function (list) { this.eachBuiltinLayer(function (layer, z) { layer.__dirty = layer.__used = false; }); function updatePrevLayer(idx) { if (prevLayer) { if (prevLayer.__endIndex !== idx) { prevLayer.__dirty = true; } prevLayer.__endIndex = idx; } } if (this._singleCanvas) { for (var i = 1; 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; for (var i = 0; i < list.length; i++) { var el = list[i]; var zlevel = el.zlevel; var layer; //PENDINGIfchangeoneincrementalelementstyle?// TODO Where there are non-incremental elements between incremental elements.if(el.incremental){layer=this.getLayer(zlevel+INCREMENTAL_INC,this._needsManuallyCompositing);layer.incremental=true;incrementalLayerCount=1;}else{layer=this.getLayer(zlevel+(incrementalLayerCount>0?EL_AFTER_INCREMENTAL_INC:0),this._needsManuallyCompositing);}if(!layer.__builtin__){log$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.layer.__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.layer.__drawIndex=i;}}}updatePrevLayer(i);this.eachBuiltinLayer(function(layer,z){// Used in last frame but not in this frame. Needs clearif(!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.if(layer.__dirty&&layer.__drawIndex<0){layer.__drawIndex=layer.__startIndex;}});},/** * 清除hover层外所有内容 */clear:function(){this.eachBuiltinLayer(this._clearLayer);returnthis;},_clearLayer:function(layer){layer.clear();},setBackgroundColor:function(backgroundColor){this._backgroundColor=backgroundColor;},/** * 修改指定zlevel的绘制参数 * * @param {string} zlevel * @param {Object} config 配置对象 * @param {string} [config.clearColor=0] 每次清空画布的颜色 * @param {string} [config.motionBlur=false] 是否开启动态模糊 * @param {number} [config.lastFrameAlpha=0.7] * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显 */configLayer:function(zlevel,config){if(config){varlayerConfig=this._layerConfig;if(!layerConfig[zlevel]){layerConfig[zlevel]=config;}else{merge(layerConfig[zlevel],config,true);}for(vari=0;i<this._zlevelList.length;i++){var_zlevel=this._zlevelList[i];if(_zlevel===zlevel||_zlevel===zlevel+EL_AFTER_INCREMENTAL_INC){varlayer=this._layers[_zlevel];merge(layer,layerConfig[zlevel],true);}}}},/** * 删除指定层 * @param {number} zlevel 层所在的zlevel */delLayer:function(zlevel){varlayers=this._layers;varzlevelList=this._zlevelList;varlayer=layers[zlevel];if(!layer){return;}layer.dom.parentNode.removeChild(layer.dom);deletelayers[zlevel];zlevelList.splice(indexOf(zlevelList,zlevel),1);},/** * 区域大小变化后重绘 */resize:function(width,height){if(!this._domRoot.style){// Maybe in node or workerif(width==null||height==null){return;}this._width=width;this._height=height;this.getLayer(CANVAS_ZLEVEL).resize(width,height);}else{vardomRoot=this._domRoot;// FIXME Why ?domRoot.style.display='none';// Save input w/hvaropts=this._opts;width!=null&&(opts.width=width);height!=null&&(opts.height=height);width=this._getSize(0);height=this._getSize(1);domRoot.style.display='';// 优化没有实际改变的resizeif(this._width!=width||height!=this._height){domRoot.style.width=width+'px';domRoot.style.height=height+'px';for(varidinthis._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;}returnthis;},/** * 清除单独的一个层 * @param {number} zlevel */clearLayer:function(zlevel){varlayer=this._layers[zlevel];if(layer){layer.clear();}},/** * 释放 */dispose:function(){this.root.innerHTML='';this.root=this.storage=this._domRoot=this._layers=null;},/** * Get canvas which has all thing rendered * @param {Object} opts * @param {string} [opts.backgroundColor] * @param {number} [opts.pixelRatio] */getRenderedCanvas:function(opts){opts=opts||{};if(this._singleCanvas&&!this._compositeManually){returnthis._layers[CANVAS_ZLEVEL].dom;}varimageLayer=newLayer('image',this,opts.pixelRatio||this.dpr);imageLayer.initContext();imageLayer.clear(false,opts.backgroundColor||this._backgroundColor);if(opts.pixelRatio<=this.dpr){this.refresh();varwidth=imageLayer.dom.width;varheight=imageLayer.dom.height;varctx=imageLayer.ctx;this.eachLayer(function(layer){if(layer.__builtin__){ctx.drawImage(layer.dom,0,0,width,height);}elseif(layer.renderToCanvas){imageLayer.ctx.save();layer.renderToCanvas(imageLayer.ctx);imageLayer.ctx.restore();}});}else{// PENDING, echarts-gl and incremental rendering.varscope={};vardisplayList=this.storage.getDisplayList(true);for(vari=0;i<displayList.length;i++){varel=displayList[i];this._doPaintEl(el,imageLayer,true,scope);}}returnimageLayer.dom;},/** * 获取绘图区域宽度 */getWidth:function(){returnthis._width;},/** * 获取绘图区域高度 */getHeight:function(){returnthis._height;},_getSize:function(whIdx){varopts=this._opts;varwh=['width','height'][whIdx];varcwh=['clientWidth','clientHeight'][whIdx];varplt=['paddingLeft','paddingTop'][whIdx];varprb=['paddingRight','paddingBottom'][whIdx];if(opts[wh]!=null&&opts[wh]!=='auto'){returnparseFloat(opts[wh]);}varroot=this.root;// IE8 does not support getComputedStyle, but it use VML.varstl=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(path,dpr){dpr=dpr||this.dpr;varcanvas=document.createElement('canvas');varctx=canvas.getContext('2d');varrect=path.getBoundingRect();varstyle=path.style;varshadowBlurSize=style.shadowBlur*dpr;varshadowOffsetX=style.shadowOffsetX*dpr;varshadowOffsetY=style.shadowOffsetY*dpr;varlineWidth=style.hasStroke()?style.lineWidth:0;varleftMargin=Math.max(lineWidth/2,-shadowOffsetX+shadowBlurSize);varrightMargin=Math.max(lineWidth/2,shadowOffsetX+shadowBlurSize);vartopMargin=Math.max(lineWidth/2,-shadowOffsetY+shadowBlurSize);varbottomMargin=Math.max(lineWidth/2,shadowOffsetY+shadowBlurSize);varwidth=rect.width+leftMargin+rightMargin;varheight=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;varpathTransform={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);}varImageShape=ZImage;varimgShape=newImageShape({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;}returnimgShape;}};/** * 动画主类, 调度和管理所有动画控制器 * * @module zrender/animation/Animation*@authorpissang(https://github.com/pissang)*///TODOAdditiveanimation// http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/// https://developer.apple.com/videos/wwdc2014/#236/***@typedef{Object}IZRenderStage*@property{Function}update*//***@aliasmodule:zrender/animation/Animation*@constructor*@param{Object}[options]*@param{Function}[options.onframe]*@param{IZRenderStage}[options.stage]*@example*varanimation=newAnimation();*varobj={*x:100,*y:100*};*animation.animate(node.position)*.when(1000,{*x:500,*y:500*})*.when(2000,{*x:100,*y:100*})*.start('spline');*/var Animation = function (options) { options = options || {}; this.stage = options.stage || {}; this.onframe = options.onframe || function() {}; //privatepropertiesthis._clips=[];this._running=false;this._time;this._pausedTime;this._pauseStart;this._paused=false;Eventful.call(this);};Animation.prototype={constructor:Animation,/** * 添加 clip * @param {module:zrender/animation/Clip}clip*/ addClip: function (clip) { this._clips.push(clip); }, /***添加animator*@param{module:zrender/animation/Animator}animator*/ addAnimator: function (animator) { animator.animation = this; var clips = animator.getClips(); for (var i = 0; i < clips.length; i++) { this.addClip(clips[i]); } }, /***删除动画片段*@param{module:zrender/animation/Clip}clip*/ removeClip: function(clip) { var idx = indexOf(this._clips, clip); if (idx >= 0) { this._clips.splice(idx, 1); } }, /***删除动画片段*@param{module:zrender/animation/Animator}animator*/ removeAnimator: function (animator) { var clips = animator.getClips(); for (var i = 0; i < clips.length; i++) { this.removeClip(clips[i]); } animator.animation = null; }, _update: function() { 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); //Throwouttheeventsneedtobecalledafter// stage.update, like destroyif(e){deferredEvents.push(e);deferredClips.push(clip);}}// Remove the finished clipfor(vari=0;i<len;){if(clips[i]._needsRemove){clips[i]=clips[len-1];clips.pop();len--;}else{i++;}}len=deferredEvents.length;for(vari=0;i<len;i++){deferredClips[i].fire(deferredEvents[i]);}this._time=time;this.onframe(delta);// 'frame' should be triggered before stage, because upper application// depends on the sequence (e.g., echarts-stream and finish// event judge)this.trigger('frame',delta);if(this.stage.update){this.stage.update();}},_startLoop:function(){varself=this;this._running=true;functionstep(){if(self._running){requestAnimationFrame(step);!self._paused&&self._update();}}requestAnimationFrame(step);},/** * Start animation. */start:function(){this._time=newDate().getTime();this._pausedTime=0;this._startLoop();},/** * Stop animation. */stop:function(){this._running=false;},/** * Pause animation. */pause:function(){if(!this._paused){this._pauseStart=newDate().getTime();this._paused=true;}},/** * Resume animation. */resume:function(){if(this._paused){this._pausedTime+=(newDate().getTime())-this._pauseStart;this._paused=false;}},/** * Clear animation. */clear:function(){this._clips=[];},/** * Whether animation finished. */isFinished:function(){return!this._clips.length;},/** * Creat animator for a target, whose props can be animated. * * @param {Object} target * @param {Object} options * @param {boolean} [options.loop=false] Whether loop animation. * @param {Function} [options.getter=null] Get value from target. * @param {Function} [options.setter=null] Set value to target. * @return {module:zrender/animation/Animation~Animator}*/ //TODOGapanimate:function(target,options){options=options||{};varanimator=newAnimator(target,options.loop,options.getter,options.setter);this.addAnimator(animator);returnanimator;}};mixin(Animation,Eventful);/** * Only implements needed gestures for mobile. */varGestureMgr=function(){/** * @private * @type {Array.<Object>} */this._track=[];};GestureMgr.prototype={constructor:GestureMgr,recognize:function(event,target,root){this._doTrack(event,target,root);returnthis._recognize(event);},clear:function(){this._track.length=0;returnthis;},_doTrack:function(event,target,root){vartouches=event.touches;if(!touches){return;}vartrackItem={points:[],touches:[],target:target,event:event};for(vari=0,len=touches.length;i<len;i++){vartouch=touches[i];varpos=clientToLocal(root,touch,{});trackItem.points.push([pos.zrX,pos.zrY]);trackItem.touches.push(touch);}this._track.push(trackItem);},_recognize:function(event){for(vareventNameinrecognizers){if(recognizers.hasOwnProperty(eventName)){vargestureInfo=recognizers[eventName](this._track,event);if(gestureInfo){returngestureInfo;}}}}};functiondist$1(pointPair){vardx=pointPair[1][0]-pointPair[0][0];vardy=pointPair[1][1]-pointPair[0][1];returnMath.sqrt(dx*dx+dy*dy);}functioncenter(pointPair){return[(pointPair[0][0]+pointPair[1][0])/2,(pointPair[0][1]+pointPair[1][1])/2];}varrecognizers={pinch:function(track,event){vartrackLen=track.length;if(!trackLen){return;}varpinchEnd=(track[trackLen-1]||{}).points;varpinchPre=(track[trackLen-2]||{}).points||pinchEnd;if(pinchPre&&pinchPre.length>1&&pinchEnd&&pinchEnd.length>1){varpinchScale=dist$1(pinchEnd)/dist$1(pinchPre);!isFinite(pinchScale)&&(pinchScale=1);event.pinchScale=pinchScale;varpinchCenter=center(pinchEnd);event.pinchX=pinchCenter[0];event.pinchY=pinchCenter[1];return{type:'pinch',target:track[0].target,event:event};}}// Only pinch currently.};varTOUCH_CLICK_DELAY=300;varmouseHandlerNames=['click','dblclick','mousewheel','mouseout','mouseup','mousedown','mousemove','contextmenu'];vartouchHandlerNames=['touchstart','touchend','touchmove'];varpointerEventNames={pointerdown:1,pointerup:1,pointermove:1,pointerout:1};varpointerHandlerNames=map(mouseHandlerNames,function(name){varnm=name.replace('mouse','pointer');returnpointerEventNames[nm]?nm:name;});functioneventNameFix(name){return(name==='mousewheel'&&env$1.browser.firefox)?'DOMMouseScroll':name;}functionprocessGesture(proxy,event,stage){vargestureMgr=proxy._gestureMgr;stage==='start'&&gestureMgr.clear();vargestureInfo=gestureMgr.recognize(event,proxy.handler.findHover(event.zrX,event.zrY,null).target,proxy.dom);stage==='end'&&gestureMgr.clear();// Do not do any preventDefault here. Upper application do that if necessary.if(gestureInfo){vartype=gestureInfo.type;event.gestureEvent=type;proxy.handler.dispatchToElement({target:gestureInfo.target},type,gestureInfo.event);}}// function onMSGestureChange(proxy, event) {// if (event.translationX || event.translationY) {// // mousemove is carried by MSGesture to reduce the sensitivity.// proxy.handler.dispatchToElement(event.target, 'mousemove', event);// }// if (event.scale !== 1) {// event.pinchX = event.offsetX;// event.pinchY = event.offsetY;// event.pinchScale = event.scale;// proxy.handler.dispatchToElement(event.target, 'pinch', event);// }// }/** * Prevent mouse event from being dispatched after Touch Events action * @see <https://github.com/deltakosh/handjs/blob/master/src/hand.base.js>*1.Mobilebrowsersdispatchmouseevents300msaftertouchend.*2.ChromeforAndroiddispatchmousedownforlong-touchabout650ms*Result:BlockingMouseEventsfor700ms.*/function setTouchTimer(instance) { instance._touching = true; clearTimeout(instance._touchTimer); instance._touchTimer = setTimeout(function () { instance._touching = false; }, 700);}var domHandlers = { /***Mousemovehandler*@inner*@param{Event}event*/ mousemove: function (event) { event = normalizeEvent(this.dom, event); this.trigger('mousemove', event); }, /***Mouseouthandler*@inner*@param{Event}event*/ mouseout: function (event) { event = normalizeEvent(this.dom, event); var element = event.toElement || event.relatedTarget; if (element != this.dom) { while (element && element.nodeType != 9) { //忽略包含在root中的dom引起的mouseOutif(element===this.dom){return;}element=element.parentNode;}}this.trigger('mouseout',event);},/** * Touch开始响应函数 * @inner * @param {Event} event */touchstart:function(event){// Default mouse behaviour should not be disabled here.// For example, page may needs to be slided.event=normalizeEvent(this.dom,event);// Mark touch, which is useful in distinguish touch and// mouse event in upper applicatoin.event.zrByTouch=true;this._lastTouchMoment=newDate();processGesture(this,event,'start');// In touch device, trigger `mousemove`(`mouseover`) should// be triggered, and must before `mousedown` triggered.domHandlers.mousemove.call(this,event);domHandlers.mousedown.call(this,event);setTouchTimer(this);},/** * Touch移动响应函数 * @inner * @param {Event} event */touchmove:function(event){event=normalizeEvent(this.dom,event);// Mark touch, which is useful in distinguish touch and// mouse event in upper applicatoin.event.zrByTouch=true;processGesture(this,event,'change');// Mouse move should always be triggered no matter whether// there is gestrue event, because mouse move and pinch may// be used at the same time.domHandlers.mousemove.call(this,event);setTouchTimer(this);},/** * Touch结束响应函数 * @inner * @param {Event} event */touchend:function(event){event=normalizeEvent(this.dom,event);// Mark touch, which is useful in distinguish touch and// mouse event in upper applicatoin.event.zrByTouch=true;processGesture(this,event,'end');domHandlers.mouseup.call(this,event);// Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is// triggered in `touchstart`. This seems to be illogical, but by this mechanism,// we can conveniently implement "hover style" in both PC and touch device just// by listening to `mouseover` to add "hover style" and listening to `mouseout`// to remove "hover style" on an element, without any additional code for// compatibility. (`mouseout` will not be triggered in `touchend`, so "hover// style" will remain for user view)// click event should always be triggered no matter whether// there is gestrue event. System click can not be prevented.if(+newDate()-this._lastTouchMoment<TOUCH_CLICK_DELAY){domHandlers.click.call(this,event);}setTouchTimer(this);},pointerdown:function(event){domHandlers.mousedown.call(this,event);// if (useMSGuesture(this, event)) {// this._msGesture.addPointer(event.pointerId);// }},pointermove:function(event){// FIXME// pointermove is so sensitive that it always triggered when// tap(click) on touch screen, which affect some judgement in// upper application. So, we dont support mousemove on MS touch// device yet.if(!isPointerFromTouch(event)){domHandlers.mousemove.call(this,event);}},pointerup:function(event){domHandlers.mouseup.call(this,event);},pointerout:function(event){// pointerout will be triggered when tap on touch screen// (IE11+/Edge on MS Surface) after click event triggered,// which is inconsistent with the mousout behavior we defined// in touchend. So we unify them.// (check domHandlers.touchend for detailed explanation)if(!isPointerFromTouch(event)){domHandlers.mouseout.call(this,event);}}};functionisPointerFromTouch(event){varpointerType=event.pointerType;returnpointerType==='pen'||pointerType==='touch';}// function useMSGuesture(handlerProxy, event) {// return isPointerFromTouch(event) && !!handlerProxy._msGesture;// }// Common handlerseach$1(['click','mousedown','mouseup','mousewheel','dblclick','contextmenu'],function(name){domHandlers[name]=function(event){event=normalizeEvent(this.dom,event);this.trigger(name,event);};});/** * 为控制类实例初始化dom 事件处理函数 * * @inner * @param {module:zrender/Handler}instance控制类实例*/function initDomHandler(instance) { each$1(touchHandlerNames, function (name) { instance._handlers[name] = bind(domHandlers[name], instance); }); each$1(pointerHandlerNames, function (name) { instance._handlers[name] = bind(domHandlers[name], instance); }); each$1(mouseHandlerNames, function (name) { instance._handlers[name] = makeMouseHandler(domHandlers[name], instance); }); function makeMouseHandler(fn, instance) { return function () { if (instance._touching) { return; } return fn.apply(instance, arguments); }; }}function HandlerDomProxy(dom) { Eventful.call(this); this.dom = dom; /***@private*@type{boolean}*/ this._touching = false; /***@private*@type{number}*/ this._touchTimer; /***@private*@type{module:zrender/core/GestureMgr}*/ this._gestureMgr = new GestureMgr(); this._handlers = {}; initDomHandler(this); if (env$1.pointerEventsSupported) { //OnlyIE11+/Edge //1.Ondevicesthatbothenabletouchandmouse(e.g.,MSSurfaceandlenovoX240),// IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event// at the same time.// 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on// screen, which do not occurs in pointer event.// So we use pointer event to both detect touch gesture and mouse behavior.mountHandlers(pointerHandlerNames,this);// FIXME// Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,// which does not prevent defuault behavior occasionally (which may cause view port// zoomed in but use can not zoom it back). And event.preventDefault() does not work.// So we have to not to use MSGesture and not to support touchmove and pinch on MS// touch screen. And we only support click behavior on MS touch screen now.// MS Gesture Event is only supported on IE11+/Edge and on Windows 8+.// We dont support touch on IE on win7.// See <https://msdn.microsoft.com/en-us/library/dn433243(v=vs.85).aspx>// if (typeof MSGesture === 'function') {// (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line// dom.addEventListener('MSGestureChange', onMSGestureChange);// }}else{if(env$1.touchEventsSupported){mountHandlers(touchHandlerNames,this);// Handler of 'mouseout' event is needed in touch mode, which will be mounted below.// addEventListener(root, 'mouseout', this._mouseoutHandler);}// 1. Considering some devices that both enable touch and mouse event (like on MS Surface// and lenovo X240, @see #2350), we make mouse event be always listened, otherwise// mouse event can not be handle in those devices.// 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent// mouseevent after touch event triggered, see `setTouchTimer`.mountHandlers(mouseHandlerNames,this);}functionmountHandlers(handlerNames,instance){each$1(handlerNames,function(name){addEventListener(dom,eventNameFix(name),instance._handlers[name]);},instance);}}varhandlerDomProxyProto=HandlerDomProxy.prototype;handlerDomProxyProto.dispose=function(){varhandlerNames=mouseHandlerNames.concat(touchHandlerNames);for(vari=0;i<handlerNames.length;i++){varname=handlerNames[i];removeEventListener(this.dom,eventNameFix(name),this._handlers[name]);}};handlerDomProxyProto.setCursor=function(cursorStyle){this.dom.style&&(this.dom.style.cursor=cursorStyle||'default');};mixin(HandlerDomProxy,Eventful);/*!* ZRender, a high performance 2d drawing library.** Copyright (c) 2013, Baidu Inc.* All rights reserved.** LICENSE* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt*/var useVML = !env$1.canvasSupported;var painterCtors = { canvas: Painter};/***@type{string}*/var version$1 = '4.0.5';/***Initializingazrenderinstance*@param{HTMLElement}dom*@param{Object}opts*@param{string}[opts.renderer='canvas']'canvas'or'svg'*@param{number}[opts.devicePixelRatio]*@param{number|string}[opts.width]Canbe'auto'(thesameasnull/undefined)*@param{number|string}[opts.height]Canbe'auto'(thesameasnull/undefined)*@return{module:zrender/ZRender}*/function init$1(dom, opts) { var zr = new ZRender(guid(), dom, opts); return zr;}/***Disposezrenderinstance*@param{module:zrender/ZRender}zr*//***Getzrenderinstancebyid*@param{string}idzrenderinstanceid*@return{module:zrender/ZRender}*//***@modulezrender/ZRender*//***@constructor*@aliasmodule:zrender/ZRender*@param{string}id*@param{HTMLElement}dom*@param{Object}opts*@param{string}[opts.renderer='canvas']'canvas'or'svg'*@param{number}[opts.devicePixelRatio]*@param{number}[opts.width]Canbe'auto'(thesameasnull/undefined)*@param{number}[opts.height]Canbe'auto'(thesameasnull/undefined)*/var ZRender = function (id, dom, opts) { opts = opts || {}; /***@type{HTMLDomElement}*/ this.dom = dom; /***@type{string}*/ this.id = id; var self = this; var storage = new Storage(); var rendererType = opts.renderer; //TODOWebGLif(useVML){if(!painterCtors.vml){thrownewError('You need to require \'zrender/vml/vml\' to support IE8');}rendererType='vml';}elseif(!rendererType||!painterCtors[rendererType]){rendererType='canvas';}varpainter=newpainterCtors[rendererType](dom,storage,opts,id);this.storage=storage;this.painter=painter;varhanderProxy=(!env$1.node&&!env$1.worker)?newHandlerDomProxy(painter.getViewportRoot()):null;this.handler=newHandler(storage,painter,handerProxy,painter.root);/** * @type {module:zrender/animation/Animation}*/ this.animation = new Animation({ stage: { update: bind(this.flush, this) } }); this.animation.start(); /***@type{boolean}*@private*/ this._needsRefresh; //修改storage.delFromStorage,每次删除元素之前删除动画// FIXME 有点uglyvaroldDelFromStorage=storage.delFromStorage;varoldAddToStorage=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,/** * 获取实例唯一标识 * @return {string} */getId:function(){returnthis.id;},/** * 添加元素 * @param {module:zrender/Element}el*/ add: function (el) { this.storage.addRoot(el); this._needsRefresh = true; }, /***删除元素*@param{module:zrender/Element}el*/ remove: function (el) { this.storage.delRoot(el); this._needsRefresh = true; }, /***Changeconfigurationoflayer*@param{string}zLevel*@param{Object}config*@param{string}[config.clearColor=0]Clearcolor*@param{string}[config.motionBlur=false]Ifenablemotionblur*@param{number}[config.lastFrameAlpha=0.7]Motionblurfactor.Largervaluecauselongertrailer*/ configLayer: function (zLevel, config) { if (this.painter.configLayer) { this.painter.configLayer(zLevel, config); } this._needsRefresh = true; }, /***Setbackgroundcolor*@param{string}backgroundColor*/ setBackgroundColor: function (backgroundColor) { if (this.painter.setBackgroundColor) { this.painter.setBackgroundColor(backgroundColor); } this._needsRefresh = true; }, /***Repaintthecanvasimmediately*/ refreshImmediately: function () { //varstart=newDate();// Clear needsRefresh ahead to avoid something wrong happens in refresh// Or it will cause zrender refreshes again and again.this._needsRefresh=false;this.painter.refresh();/** * Avoid trigger zr.refresh in Element#beforeUpdate hook */this._needsRefresh=false;// var end = new Date();// var log = document.getElementById('log');// if (log) {// log.innerHTML = log.innerHTML + '<br>' + (end - start);// }},/** * Mark and repaint the canvas in the next frame of browser */refresh:function(){this._needsRefresh=true;},/** * Perform all refresh */flush:function(){vartriggerRendered;if(this._needsRefresh){triggerRendered=true;this.refreshImmediately();}if(this._needsRefreshHover){triggerRendered=true;this.refreshHoverImmediately();}triggerRendered&&this.trigger('rendered');},/** * Add element to hover layer * @param {module:zrender/Element}el*@param{Object}style*/ addHover: function (el, style) { if (this.painter.addHover) { var elMirror = this.painter.addHover(el, style); this.refreshHover(); return elMirror; } }, /***Addelementfromhoverlayer*@param{module:zrender/Element}el*/ removeHover: function (el) { if (this.painter.removeHover) { this.painter.removeHover(el); this.refreshHover(); } }, /***Clearallhoverelementsinhoverlayer*@param{module:zrender/Element}el*/ clearHover: function () { if (this.painter.clearHover) { this.painter.clearHover(); this.refreshHover(); } }, /***Refreshhoverinnextframe*/ refreshHover: function () { this._needsRefreshHover = true; }, /***Refreshhoverimmediately*/ refreshHoverImmediately: function () { this._needsRefreshHover = false; this.painter.refreshHover && this.painter.refreshHover(); }, /***Resizethecanvas.*Shouldbeinvokedwhencontainersizeischanged*@param{Object}[opts]*@param{number|string}[opts.width]Canbe'auto'(thesameasnull/undefined)*@param{number|string}[opts.height]Canbe'auto'(thesameasnull/undefined)*/ resize: function(opts) { opts = opts || {}; this.painter.resize(opts.width, opts.height); this.handler.resize(); }, /***Stopandclearallanimationimmediately*/ clearAnimation: function () { this.animation.clear(); }, /***Getcontainerwidth*/ getWidth: function() { return this.painter.getWidth(); }, /***Getcontainerheight*/ getHeight: function() { return this.painter.getHeight(); }, /***ExportthecanvasasBase64URL*@param{string}type*@param{string}[backgroundColor='#fff']*@return{string}Base64URL*/ //toDataURL:function(type,backgroundColor){// return this.painter.getRenderedCanvas({// backgroundColor: backgroundColor// }).toDataURL(type);// },/** * Converting a path to image. * It has much better performance of drawing image rather than drawing a vector path. * @param {module:zrender/graphic/Path}e*@param{number}width*@param{number}height*/ pathToImage: function(e, dpr) { return this.painter.pathToImage(e, dpr); }, /***Setdefaultcursor*@param{string}[cursorStyle='default']例如crosshair*/ setCursorStyle: function (cursorStyle) { this.handler.setCursorStyle(cursorStyle); }, /***Findhoveredelement*@param{number}x*@param{number}y*@return{Object}{target,topTarget}*/ findHover: function (x, y) { return this.handler.findHover(x, y); }, /***Bindevent**@param{string}eventNameEventname*@param{Function}eventHandlerHandlerfunction*@param{Object}[context]Contextobject*/ on: function(eventName, eventHandler, context) { this.handler.on(eventName, eventHandler, context); }, /***Unbindevent*@param{string}eventNameEventname*@param{Function}[eventHandler]Handlerfunction*/ off: function(eventName, eventHandler) { this.handler.off(eventName, eventHandler); }, /***Triggereventmanually**@param{string}eventNameEventname*@param{event=}eventEventobject*/ trigger: function (eventName, event) { this.handler.trigger(eventName, event); }, /***Clearallobjectsandthecanvas.*/ clear: function () { this.storage.delRoot(); this.painter.clear(); }, /***Disposeself.*/ dispose: function () { this.animation.stop(); this.clear(); this.storage.dispose(); this.painter.dispose(); this.handler.dispose(); this.animation = this.storage = this.painter = this.handler = null; }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var each$2 = each$1;var isObject$2 = isObject$1;var isArray$1 = isArray;/***Makethenamedisplayable.Butweshould*makesureitisnotduplicatedwithuser*specifiedname,souse'\0';*/var DUMMY_COMPONENT_NAME_PREFIX = 'series\0';/***Ifvalueisnotarray,thentranslateittoarray.*@param{*}value*@return{Array}[value]orvalue*/function normalizeToArray(value) { return value instanceof Array? value : value == null?[] : [value];}/***Syncdefaultoptionbetweennormalandemphasislike`position`and`show`*Incasesomeonewillwritecodelike*label:{*show:false,*position:'outside',*fontSize:18*},*emphasis:{*label:{show:true}*}*@param{Object}opt*@param{string}key*@param{Array.<string>}subOpts*/function defaultEmphasis(opt, key, subOpts) { //Caution:performancesensitive.if(opt){opt[key]=opt[key]||{};opt.emphasis=opt.emphasis||{};opt.emphasis[key]=opt.emphasis[key]||{};// Default emphasis option from normalfor(vari=0,len=subOpts.length;i<len;i++){varsubOptName=subOpts[i];if(!opt.emphasis[key].hasOwnProperty(subOptName)&&opt[key].hasOwnProperty(subOptName)){opt.emphasis[key][subOptName]=opt[key][subOptName];}}}}varTEXT_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([// 'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter',// 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',// // FIXME: deprecated, check and remove it.// 'textStyle'// ]);/** * The method do not ensure performance. * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] * This helper method retieves value from data. * @param {string|number|Date|Array|Object} dataItem * @return {number|string|Date|Array.<number|string|Date>} */functiongetDataItemValue(dataItem){return(isObject$2(dataItem)&&!isArray$1(dataItem)&&!(dataIteminstanceofDate))?dataItem.value:dataItem;}/** * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] * This helper method determine if dataItem has extra option besides value * @param {string|number|Date|Array|Object} dataItem */functionisDataItemOption(dataItem){returnisObject$2(dataItem)&&!(dataIteminstanceofArray);// // markLine data can be array// && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));}/** * Mapping to exists for merge. * * @public * @param {Array.<Object>|Array.<module:echarts/model/Component>}exists*@param{Object|Array.<Object>}newCptOptions*@return{Array.<Object>}Result,like[{exist:...,option:...},{}],*indexofwhichisthesameasexists.*/function mappingToExists(exists, newCptOptions) { //Mappingbytheorderbyoriginaloption(butnotorderof// new option) in merge mode. Because we should ensure// some specified index (like xAxisIndex) is consistent with// original option, which is easy to understand, espatially in// media query. And in most case, merge option is used to// update partial option but not be expected to change order.newCptOptions=(newCptOptions||[]).slice();varresult=map(exists||[],function(obj,index){return{exist:obj};});// Mapping by id or name if specified.each$2(newCptOptions,function(cptOption,index){if(!isObject$2(cptOption)){return;}// id has highest priority.for(vari=0;i<result.length;i++){if(!result[i].option// Consider name: two map to one.&&cptOption.id!=null&&result[i].exist.id===cptOption.id+''){result[i].option=cptOption;newCptOptions[index]=null;return;}}for(vari=0;i<result.length;i++){varexist=result[i].exist;if(!result[i].option// Consider name: two map to one.// Can not match when both ids exist but different.&&(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.each$2(newCptOptions,function(cptOption,index){if(!isObject$2(cptOption)){return;}vari=0;for(;i<result.length;i++){varexist=result[i].exist;if(!result[i].option// Existing model that already has id should be able to// mapped to (because after mapping performed model may// be assigned with a id, whish should not affect next// mapping), except those has inner id.&&!isIdInner(exist)// Caution:// Do not overwrite id. But name can be overwritten,// because axis use name as 'show label text'.// 'exist' always has id and name and we dont// need to check it.&&cptOption.id==null){result[i].option=cptOption;break;}}if(i>=result.length){result.push({option:cptOption});}});returnresult;}/** * Make id and name for mapping result (result of mappingToExists) * into `keyInfo` field. * * @public * @param {Array.<Object>} Result, like [{exist: ..., option: ...}, {}], * which order is the same as exists. * @return {Array.<Object>} The input. */functionmakeIdAndName(mapResult){// We use this id to hash component models and view instances// in echarts. id can be specified by user, or auto generated.// The id generation rule ensures new view instance are able// to mapped to old instance when setOption are called in// no-merge mode. So we generate model id by name and plus// type in view id.// name can be duplicated among components, which is convenient// to specify multi components (like series) by one name.// Ensure that each id is distinct.varidMap=createHashMap();each$2(mapResult,function(item,index){varexistCpt=item.exist;existCpt&&idMap.set(existCpt.id,item);});each$2(mapResult,function(item,index){varopt=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.each$2(mapResult,function(item,index){varexistCpt=item.exist;varopt=item.option;varkeyInfo=item.keyInfo;if(!isObject$2(opt)){return;}// name can be overwitten. Consider case: axis.name = '20km'.// But id generated by name will not be changed, which affect// only in that case: setOption with 'not merge mode' and view// instance will be recreated, which can be accepted.keyInfo.name=opt.name!=null?opt.name+'':existCpt?existCpt.name// Avoid diffferent series has the same name,// because name may be used like in color pallet.:DUMMY_COMPONENT_NAME_PREFIX+index;if(existCpt){keyInfo.id=existCpt.id;}elseif(opt.id!=null){keyInfo.id=opt.id+'';}else{// Consider this situatoin:// optionA: [{name: 'a'}, {name: 'a'}, {..}]// optionB [{..}, {name: 'a'}, {name: 'a'}]// Series with the same name between optionA and optionB// should be mapped.varidNum=0;do{keyInfo.id='\0'+keyInfo.name+'\0'+idNum++;}while(idMap.get(keyInfo.id));}idMap.set(keyInfo.id,item);});}functionisNameSpecified(componentModel){varname=componentModel.name;// Is specified when `indexOf` get -1 or > 0.return!!(name&&name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));}/** * @public * @param {Object} cptOption * @return {boolean} */functionisIdInner(cptOption){returnisObject$2(cptOption)&&cptOption.id&&(cptOption.id+'').indexOf('\0_ec_\0')===0;}/** * A helper for removing duplicate items between batchA and batchB, * and in themselves, and categorize by series. * * @param {Array.<Object>} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] * @param {Array.<Object>} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] * @return {Array.<Array.<Object>, Array.<Object>>} result: [resultBatchA, resultBatchB] *//***@param{module:echarts/data/List}data*@param{Object}payloadContainsdataIndex(meansrawIndex)/dataIndexInside/name*eachofwhichcanbeArrayorprimarytype.*@return{number|Array.<number>}dataIndexIfnotfound,returnundefined/null.*/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); }}/***Enablepropertystoragetoanyhostobject.*Notice:Serializationisnotsupported.**Forexample:*varinner=zrUitl.makeInner();**functionsome1(hostObj){*inner(hostObj).someProperty=1212;*...*}*functionsome2(){*varfields=inner(this);*fields.someProperty1=1212;*fields.someProperty2='xx';*...*}**@return{Function}*/function makeInner() { //Considerdifferentscopebyesmoduleimport.varkey='__\0ec_inner_'+innerUniqueIndex+++'_'+Math.random().toFixed(5);returnfunction(hostObj){returnhostObj[key]||(hostObj[key]={});};}varinnerUniqueIndex=0;/** * @param {module:echarts/model/Global}ecModel*@param{string|Object}finder*Ifstring,e.g.,'geo',means{geoIndex:0}.*IfObject,couldcontainsomeofthesepropertiesbelow:*{*seriesIndex,seriesId,seriesName,*geoIndex,geoId,geoName,*bmapIndex,bmapId,bmapName,*xAxisIndex,xAxisId,xAxisName,*yAxisIndex,yAxisId,yAxisName,*gridIndex,gridId,gridName,*...(canbeextended)*}*Eachpropertiescanbenumber|string|Array.<number>|Array.<string>*Forexample,afindercouldbe*{*seriesIndex:3,*geoId:['aa','cc'],*gridName:['xx','rr']*}*xxxIndexcanbesetas'all'(meansallxxx)or'none'(meansnotspecify)*Ifnothingornull/undefinedspecified,returnnothing.*@param{Object}[opt]*@param{string}[opt.defaultMainType]*@param{Array.<string>}[opt.includeMainTypes]*@return{Object}resultlike:*{*seriesModels:[seriesModel1,seriesModel2],*seriesModel:seriesModel1,// The first model*geoModels:[geoModel1,geoModel2],*geoModel:geoModel1,// The first model*...*}*/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'andotherillgalkeys.if(key==='dataIndex'||key==='dataIndexInside'){result[key]=value;return;}varparsedKey=key.match(/^(\w+)(Index|Id|Name)$/)||[];varmainType=parsedKey[1];varqueryType=(parsedKey[2]||'').toLowerCase();if(!mainType||!queryType||value==null||(queryType==='index'&&value==='none')||(opt&&opt.includeMainTypes&&indexOf(opt.includeMainTypes,mainType)<0)){return;}varqueryParam={mainType:mainType};if(queryType!=='index'||value!=='all'){queryParam[queryType]=value;}varmodels=ecModel.queryComponents(queryParam);result[mainType+'Models']=models;result[mainType+'Model']=models[0];});returnresult;}functionhas(obj,prop){returnobj&&obj.hasOwnProperty(prop);}functionsetAttribute(dom,key,value){dom.setAttribute?dom.setAttribute(key,value):(dom[key]=value);}functiongetAttribute(dom,key){returndom.getAttribute?dom.getAttribute(key):dom[key];}functiongetTooltipRenderMode(renderModeOption){if(renderModeOption==='auto'){// Using html when `document` exists, use richText otherwisereturnenv$1.domSupported?'html':'richText';}else{returnrenderModeOption||'html';}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var TYPE_DELIMITER = '.';var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';/***Notice,parseClassType('')shouldreturns{main:'',sub:''}*@public*/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;}/***@public*/function checkClassType(componentType) { assert$1( /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType),'componentType "'+componentType+'" illegal');}/** * @public */functionenableClassExtend(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:'')+'.');}});}varsuperClass=this;varExtendedClass=function(){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;returnExtendedClass;};}varclassBase=0;/** * Can not use instanceof, consider different scope by * cross domain or es module import in ec extensions. * Mount a method "isInstance()" to Clz. */functionenableClassCheck(Clz){varclassAttr=['__\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'.// Consider this case:// class A has method f,// class B inherits class A, overrides method f, f call superApply('f'),// class C inherits class B, do not overrides method f,// then when method of class C is called, dead loop occured.functionsuperCall(context,methodName){varargs=slice(arguments,2);returnthis.superClass.prototype[methodName].apply(context,args);}functionsuperApply(context,methodName,args){returnthis.superClass.prototype[methodName].apply(context,args);}/** * @param {Object} entity * @param {Object} options * @param {boolean} [options.registerWhenExtend] * @public */functionenableClassManagement(entity,options){options=options||{};/** * Component model classes * key: componentType, * value: * componentClass, when componentType is 'xxx' * or Object.<subKey, componentClass>, when componentType is 'xxx.yy' * @type {Object} */varstorage={};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;}elseif(componentType.sub!==IS_CONTAINER){varcontainer=makeContainer(componentType);container[componentType.sub]=Clazz;}}returnClazz;};entity.getClass=function(componentMainType,subType,throwWhenNotFound){varClazz=storage[componentMainType];if(Clazz&&Clazz[IS_CONTAINER]){Clazz=subType?Clazz[subType]:null;}if(throwWhenNotFound&&!Clazz){thrownewError(!subType?componentMainType+'.'+'type should be specified.':'Component '+componentMainType+'.'+(subType||'')+' not exists. Load it first.');}returnClazz;};entity.getClassesByMainType=function(componentType){componentType=parseClassType$1(componentType);varresult=[];varobj=storage[componentType.main];if(obj&&obj[IS_CONTAINER]){each$1(obj,function(o,type){type!==IS_CONTAINER&&result.push(o);});}else{result.push(obj);}returnresult;};entity.hasClass=function(componentType){// Just consider componentType.main.componentType=parseClassType$1(componentType);return!!storage[componentType.main];};/** * @return {Array.<string>} Like ['aa', 'bb'], but can not be ['aa.xx'] */entity.getAllClassMainTypes=function(){vartypes=[];each$1(storage,function(obj,type){types.push(type);});returntypes;};/** * If a main type is container and has sub types * @param {string} mainType * @return {boolean} */entity.hasSubTypes=function(componentType){componentType=parseClassType$1(componentType);varobj=storage[componentType.main];returnobj&&obj[IS_CONTAINER];};entity.parseClassType=parseClassType$1;functionmakeContainer(componentType){varcontainer=storage[componentType.main];if(!container||!container[IS_CONTAINER]){container=storage[componentType.main]={};container[IS_CONTAINER]=true;}returncontainer;}if(options.registerWhenExtend){varoriginalExtend=entity.extend;if(originalExtend){entity.extend=function(proto){varExtendedClass=originalExtend.call(this,proto);returnentity.registerClass(ExtendedClass,proto.type);};}}returnentity;}/** * @param {string|Array.<string>} properties *//**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///TODOParseshadowstyle// TODO Only shallow path supportvarmakeStyleMapper=function(properties){// Normalizefor(vari=0;i<properties.length;i++){if(!properties[i][1]){properties[i][1]=properties[i][0];}}returnfunction(model,excludes,includes){varstyle={};for(vari=0;i<properties.length;i++){varpropName=properties[i][1];if((excludes&&indexOf(excludes,propName)>=0)||(includes&&indexOf(includes,propName)<0)){continue;}varval=model.getShallow(propName);if(val!=null){style[properties[i][0]]=val;}}returnstyle;};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var getLineStyle = makeStyleMapper([ ['lineWidth', 'width'],['stroke', 'color'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor'] ]);var lineStyleMixin = { getLineStyle: function (excludes) { var style = getLineStyle(this, excludes); var lineDash = this.getLineDash(style.lineWidth); lineDash && (style.lineDash = lineDash); return style; }, getLineDash: function (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)? null : (lineType === 'dashed' ?[dashSize, dashSize] : [dotSize, dotSize]); }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var getAreaStyle = makeStyleMapper([ ['fill', 'color'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['opacity'],['shadowColor'] ]);var areaStyleMixin = { getAreaStyle: function (excludes, includes) { return getAreaStyle(this, excludes, includes); }};/***曲线辅助模块*@modulezrender/core/curve*@authorpissang(https://www.github.com/pissang)*/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;// 临时变量var_v0=create();var_v1=create();var_v2=create();functionisAroundZero(val){returnval>-EPSILON$1&&val<EPSILON$1;}functionisNotAroundZero$1(val){returnval>EPSILON$1||val<-EPSILON$1;}/** * 计算三次贝塞尔值 * @memberOf module:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}p3*@param{number}t*@return{number}*/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);}/***计算三次贝塞尔导数值*@memberOfmodule:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}p3*@param{number}t*@return{number}*/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);}/***计算三次贝塞尔方程根,使用盛金公式*@memberOfmodule:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}p3*@param{number}val*@param{Array.<number>}roots*@return{number}有效根数目*/function cubicRootAt(p0, p1, p2, p3, val, roots) { //Evaluaterootsofcubicfunctionsvara=p3+3*(p1-p2)-p0;varb=3*(p2-p1*2+p0);varc=3*(p1-p0);vard=p0-val;varA=b*b-3*a*c;varB=b*c-9*a*d;varC=c*c-3*b*d;varn=0;if(isAroundZero(A)&&isAroundZero(B)){if(isAroundZero(b)){roots[0]=0;}else{vart1=-c/b;//t1, t2, t3, b is not zeroif(t1>=0&&t1<=1){roots[n++]=t1;}}}else{vardisc=B*B-4*A*C;if(isAroundZero(disc)){varK=B/A;vart1=-b/a+K;// t1, a is not zerovart2=-K/2;// t2, t3if(t1>=0&&t1<=1){roots[n++]=t1;}if(t2>=0&&t2<=1){roots[n++]=t2;}}elseif(disc>0){vardiscSqrt=mathSqrt$2(disc);varY1=A*b+1.5*a*(-B+discSqrt);varY2=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);}vart1=(-b-(Y1+Y2))/(3*a);if(t1>=0&&t1<=1){roots[n++]=t1;}}else{varT=(2*A*b-3*a*B)/(2*mathSqrt$2(A*A*A));vartheta=Math.acos(T)/3;varASqrt=mathSqrt$2(A);vartmp=Math.cos(theta);vart1=(-b-2*ASqrt*tmp)/(3*a);vart2=(-b+ASqrt*(tmp+THREE_SQRT*Math.sin(theta)))/(3*a);vart3=(-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;}}}returnn;}/** * 计算三次贝塞尔方程极限值的位置 * @memberOf module:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}p3*@param{Array.<number>}extrema*@return{number}有效数目*/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{vardisc=b*b-4*a*c;if(isAroundZero(disc)){extrema[0]=-b/(2*a);}elseif(disc>0){vardiscSqrt=mathSqrt$2(disc);vart1=(-b+discSqrt)/(2*a);vart2=(-b-discSqrt)/(2*a);if(t1>=0&&t1<=1){extrema[n++]=t1;}if(t2>=0&&t2<=1){extrema[n++]=t2;}}}returnn;}/** * 细分三次贝塞尔曲线 * @memberOf module:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}p3*@param{number}t*@param{Array.<number>}out*/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; //Seg0out[0]=p0;out[1]=p01;out[2]=p012;out[3]=p0123;// Seg1out[4]=p0123;out[5]=p123;out[6]=p23;out[7]=p3;}/** * 投射点到三次贝塞尔曲线上,返回投射距离。 * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} x3 * @param {number} y3 * @param {number} x * @param {number} y * @param {Array.<number>} [out] 投射点 * @return {number} */functioncubicProjectPoint(x0,y0,x1,y1,x2,y2,x3,y3,x,y,out){// http://pomax.github.io/bezierinfo/#projectionsvart;varinterval=0.005;vard=Infinity;varprev;varnext;vard1;vard2;_v0[0]=x;_v0[1]=y;// 先粗略估计一下可能的最小距离的 t 值// PENDINGfor(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 iterationfor(vari=0;i<32;i++){if(interval<EPSILON_NUMERIC){break;}prev=t-interval;next=t+interval;// t - interval_v1[0]=cubicAt(x0,x1,x2,x3,prev);_v1[1]=cubicAt(y0,y1,y2,y3,prev);d1=distSquare(_v1,_v0);if(prev>=0&&d1<d){t=prev;d=d1;}else{// t + interval_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;}}}// tif(out){out[0]=cubicAt(x0,x1,x2,x3,t);out[1]=cubicAt(y0,y1,y2,y3,t);}// console.log(interval, i);returnmathSqrt$2(d);}/** * 计算二次方贝塞尔值 * @param {number} p0 * @param {number} p1 * @param {number} p2 * @param {number} t * @return {number} */functionquadraticAt(p0,p1,p2,t){varonet=1-t;returnonet*(onet*p0+2*t*p1)+t*t*p2;}/** * 计算二次方贝塞尔导数值 * @param {number} p0 * @param {number} p1 * @param {number} p2 * @param {number} t * @return {number} */functionquadraticDerivativeAt(p0,p1,p2,t){return2*((1-t)*(p1-p0)+t*(p2-p1));}/** * 计算二次方贝塞尔方程根 * @param {number} p0 * @param {number} p1 * @param {number} p2 * @param {number} t * @param {Array.<number>} roots * @return {number} 有效根数目 */functionquadraticRootAt(p0,p1,p2,val,roots){vara=p0-2*p1+p2;varb=2*(p1-p0);varc=p0-val;varn=0;if(isAroundZero(a)){if(isNotAroundZero$1(b)){vart1=-c/b;if(t1>=0&&t1<=1){roots[n++]=t1;}}}else{vardisc=b*b-4*a*c;if(isAroundZero(disc)){vart1=-b/(2*a);if(t1>=0&&t1<=1){roots[n++]=t1;}}elseif(disc>0){vardiscSqrt=mathSqrt$2(disc);vart1=(-b+discSqrt)/(2*a);vart2=(-b-discSqrt)/(2*a);if(t1>=0&&t1<=1){roots[n++]=t1;}if(t2>=0&&t2<=1){roots[n++]=t2;}}}returnn;}/** * 计算二次贝塞尔方程极限值 * @memberOf module:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@return{number}*/function quadraticExtremum(p0, p1, p2) { var divider = p0 + p2 - 2 * p1; if (divider === 0) { //p1iscenterofp0andp2return0.5;}else{return(p0-p1)/divider;}}/** * 细分二次贝塞尔曲线 * @memberOf module:zrender/core/curve*@param{number}p0*@param{number}p1*@param{number}p2*@param{number}t*@param{Array.<number>}out*/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; //Seg0out[0]=p0;out[1]=p01;out[2]=p012;// Seg1out[3]=p012;out[4]=p12;out[5]=p2;}/** * 投射点到二次贝塞尔曲线上,返回投射距离。 * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。 * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} x * @param {number} y * @param {Array.<number>} out 投射点 * @return {number} */functionquadraticProjectPoint(x0,y0,x1,y1,x2,y2,x,y,out){// http://pomax.github.io/bezierinfo/#projectionsvart;varinterval=0.005;vard=Infinity;_v0[0]=x;_v0[1]=y;// 先粗略估计一下可能的最小距离的 t 值// PENDINGfor(var_t=0;_t<1;_t+=0.05){_v1[0]=quadraticAt(x0,x1,x2,_t);_v1[1]=quadraticAt(y0,y1,y2,_t);vard1=distSquare(_v0,_v1);if(d1<d){t=_t;d=d1;}}d=Infinity;// At most 32 iterationfor(vari=0;i<32;i++){if(interval<EPSILON_NUMERIC){break;}varprev=t-interval;varnext=t+interval;// t - interval_v1[0]=quadraticAt(x0,x1,x2,prev);_v1[1]=quadraticAt(y0,y1,y2,prev);vard1=distSquare(_v1,_v0);if(prev>=0&&d1<d){t=prev;d=d1;}else{// t + interval_v2[0]=quadraticAt(x0,x1,x2,next);_v2[1]=quadraticAt(y0,y1,y2,next);vard2=distSquare(_v2,_v0);if(next<=1&&d2<d){t=next;d=d2;}else{interval*=0.5;}}}// tif(out){out[0]=quadraticAt(x0,x1,x2,t);out[1]=quadraticAt(y0,y1,y2,t);}// console.log(interval, i);returnmathSqrt$2(d);}/** * @author Yi Shen(https://github.com/pissang)*/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();/***从顶点数组中计算出最小包围盒,写入`min`和`max`中*@modulezrender/core/bbox*@param{Array<Object>}points顶点数组*@param{number}min*@param{number}max*//***@memberOfmodule:zrender/core/bbox*@param{number}x0*@param{number}y0*@param{number}x1*@param{number}y1*@param{Array.<number>}min*@param{Array.<number>}max*/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 = [];/***从三阶贝塞尔曲线(p0,p1,p2,p3)中计算出最小包围盒,写入`min`和`max`中*@memberOfmodule:zrender/core/bbox*@param{number}x0*@param{number}y0*@param{number}x1*@param{number}y1*@param{number}x2*@param{number}y2*@param{number}x3*@param{number}y3*@param{Array.<number>}min*@param{Array.<number>}max*/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]);}/***从二阶贝塞尔曲线(p0,p1,p2)中计算出最小包围盒,写入`min`和`max`中*@memberOfmodule:zrender/core/bbox*@param{number}x0*@param{number}y0*@param{number}x1*@param{number}y1*@param{number}x2*@param{number}y2*@param{Array.<number>}min*@param{Array.<number>}max*/function fromQuadratic(x0, y0, x1, y1, x2, y2, min$$1, max$$1) { var quadraticExtremum$$1 = quadraticExtremum; var quadraticAt$$1 = quadraticAt; //Findextremities,wherederivativeinxdimorydimiszerovartx=mathMax$3(mathMin$3(quadraticExtremum$$1(x0,x1,x2),1),0);varty=mathMax$3(mathMin$3(quadraticExtremum$$1(y0,y1,y2),1),0);varx=quadraticAt$$1(x0,x1,x2,tx);vary=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);}/** * 从圆弧中计算出最小包围盒,写入`min`和`max`中 * @method * @memberOf module:zrender/core/bbox*@param{number}x*@param{number}y*@param{number}rx*@param{number}ry*@param{number}startAngle*@param{number}endAngle*@param{number}anticlockwise*@param{Array.<number>}min*@param{Array.<number>}max*/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) { //Isacirclemin$$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]startAngle=startAngle%(PI2);if(startAngle<0){startAngle=startAngle+PI2;}endAngle=endAngle%(PI2);if(endAngle<0){endAngle=endAngle+PI2;}if(startAngle>endAngle&&!anticlockwise){endAngle+=PI2;}elseif(startAngle<endAngle&&anticlockwise){startAngle+=PI2;}if(anticlockwise){vartmp=endAngle;endAngle=startAngle;startAngle=tmp;}// var number = 0;// var step = (anticlockwise ? -Math.PI : Math.PI) / 2;for(varangle=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);}}}/** * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中 * 可以用于 isInsidePath 判断以及获取boundingRect * * @module zrender/core/PathProxy*@authorYiShen(http://www.github.com/pissang)*///TODOgetTotalLength,getPointAtLengthvarCMD={M:1,L:2,C:3,Q:4,A:5,Z:6,// RectR:7};// var CMD_MEM_SIZE = {// M: 3,// L: 3,// C: 7,// Q: 5,// A: 9,// R: 5,// Z: 1// };varmin$1=[];varmax$1=[];varmin2=[];varmax2=[];varmathMin$2=Math.min;varmathMax$2=Math.max;varmathCos$1=Math.cos;varmathSin$1=Math.sin;varmathSqrt$1=Math.sqrt;varmathAbs=Math.abs;varhasTypedArray=typeofFloat32Array!='undefined';/** * @alias module:zrender/core/PathProxy*@constructor*/var PathProxy = function (notSaveData) { this._saveData = !(notSaveData || false); if (this._saveData) { /***Pathdata.Storedasflatarray*@type{Array.<Object>}*/ this.data = []; } this._ctx = null;};/***快速计算Path包围盒(并不是最小包围盒)*@return{Object}*/PathProxy.prototype = { constructor: PathProxy, _xi: 0, _yi: 0, _x0: 0, _y0: 0, //Unitx,Unity.Provideforavoidingdrawingthattooshortlinesegment_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,/** * @readOnly */setScale:function(sx,sy){this._ux=mathAbs(1/devicePixelRatio/sx)||0;this._uy=mathAbs(1/devicePixelRatio/sy)||0;},getContext:function(){returnthis._ctx;},/** * @param {CanvasRenderingContext2D} ctx * @return {module:zrender/core/PathProxy}*/ beginPath: function (ctx) { this._ctx = ctx; ctx && ctx.beginPath(); ctx && (this.dpr = ctx.dpr); //Resetif(this._saveData){this._len=0;}if(this._lineDash){this._lineDash=null;this._dashOffset=0;}returnthis;},/** * @param {number} x * @param {number} y * @return {module:zrender/core/PathProxy}*/ moveTo: function (x, y) { this.addData(CMD.M, x, y); this._ctx && this._ctx.moveTo(x, y); //x0,y0,xi,yi是记录在_dashedXXXXTo方法中使用// xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。// 有可能在 beginPath 之后直接调用 lineTo,这时候 x0, y0 需要// 在 lineTo 方法中记录,这里先不考虑这种情况,dashed line 也只在 IE10- 中不支持this._x0=x;this._y0=y;this._xi=x;this._yi=y;returnthis;},/** * @param {number} x * @param {number} y * @return {module:zrender/core/PathProxy}*/ lineTo: function (x, y) { var exceedUnit = mathAbs(x - this._xi) > this._ux || mathAbs(y - this._yi) > this._uy //Forcedrawthefirstsegment||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;}returnthis;},/** * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} x3 * @param {number} y3 * @return {module:zrender/core/PathProxy}*/ bezierCurveTo: function (x1, y1, x2, y2, x3, y3) { this.addData(CMD.C, x1, y1, x2, y2, x3, y3); if (this._ctx) { this._needsDash()? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); } this._xi = x3; this._yi = y3; return this; }, /***@param{number}x1*@param{number}y1*@param{number}x2*@param{number}y2*@return{module:zrender/core/PathProxy}*/ quadraticCurveTo: function (x1, y1, x2, y2) { this.addData(CMD.Q, x1, y1, x2, y2); if (this._ctx) { this._needsDash()? this._dashedQuadraticTo(x1, y1, x2, y2) : this._ctx.quadraticCurveTo(x1, y1, x2, y2); } this._xi = x2; this._yi = y2; return this; }, /***@param{number}cx*@param{number}cy*@param{number}r*@param{number}startAngle*@param{number}endAngle*@param{boolean}anticlockwise*@return{module:zrender/core/PathProxy}*/ arc: function (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; }, //TODOarcTo:function(x1,y1,x2,y2,radius){if(this._ctx){this._ctx.arcTo(x1,y1,x2,y2,radius);}returnthis;},// TODOrect:function(x,y,w,h){this._ctx&&this._ctx.rect(x,y,w,h);this.addData(CMD.R,x,y,w,h);returnthis;},/** * @return {module:zrender/core/PathProxy}*/ closePath: function () { this.addData(CMD.Z); var ctx = this._ctx; var x0 = this._x0; var y0 = this._y0; if (ctx) { this._needsDash() && this._dashedLineTo(x0, y0); ctx.closePath(); } this._xi = x0; this._yi = y0; return this; }, /***Context从外部传入,因为有可能是rebuildPath完之后再fill。*stroke同样*@param{CanvasRenderingContext2D}ctx*@return{module:zrender/core/PathProxy}*/ fill: function (ctx) { ctx && ctx.fill(); this.toStatic(); }, /***@param{CanvasRenderingContext2D}ctx*@return{module:zrender/core/PathProxy}*/ stroke: function (ctx) { ctx && ctx.stroke(); this.toStatic(); }, /***必须在其它绘制命令前调用*Mustbeinvokedbeforeallotherpathdrawingmethods*@return{module:zrender/core/PathProxy}*/ setLineDash: function (lineDash) { if (lineDash instanceof Array) { this._lineDash = lineDash; this._dashIdx = 0; var lineDashSum = 0; for (var i = 0; i < lineDash.length; i++) { lineDashSum += lineDash[i]; } this._dashSum = lineDashSum; } return this; }, /***必须在其它绘制命令前调用*Mustbeinvokedbeforeallotherpathdrawingmethods*@return{module:zrender/core/PathProxy}*/ setLineDashOffset: function (offset) { this._dashOffset = offset; return this; }, /****@return{boolean}*/ len: function () { return this._len; }, /***直接设置Path数据*/ setData: function (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; }, /***添加子路径*@param{module:zrender/core/PathProxy|Array.<module:zrender/core/PathProxy>}path*/ appendPath: function (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; }, /***填充Path数据。*尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。*/ addData: function (cmd) { if (!this._saveData) { return; } var data = this.data; if (this._len + arguments.length > data.length) { //因为之前的数组已经转换成静态的Float32Array// 所以不够用时需要扩展一个新的动态数组this._expandData();data=this.data;}for(vari=0;i<arguments.length;i++){data[this._len++]=arguments[i];}this._prevCmd=cmd;},_expandData:function(){// Only if data is Float32Arrayif(!(this.datainstanceofArray)){varnewData=[];for(vari=0;i<this._len;i++){newData[i]=this.data[i];}this.data=newData;}},/** * If needs js implemented dashed line * @return {boolean} * @private */_needsDash:function(){returnthis._lineDash;},_dashedLineTo:function(x1,y1){vardashSum=this._dashSum;varoffset=this._dashOffset;varlineDash=this._lineDash;varctx=this._ctx;varx0=this._xi;vary0=this._yi;vardx=x1-x0;vardy=y1-y0;vardist$$1=mathSqrt$1(dx*dx+dy*dy);varx=x0;vary=y0;vardash;varnDash=lineDash.length;varidx;dx/=dist$$1;dy/=dist$$1;if(offset<0){// Convert to positive offsetoffset=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 offsetif((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 lineTodx=x-x1;dy=y-y1;this._dashOffset=-mathSqrt$1(dx*dx+dy*dy);},// Not accurate dashed line to_dashedBezierTo:function(x1,y1,x2,y2,x3,y3){vardashSum=this._dashSum;varoffset=this._dashOffset;varlineDash=this._lineDash;varctx=this._ctx;varx0=this._xi;vary0=this._yi;vart;vardx;vardy;varcubicAt$$1=cubicAt;varbezierLen=0;varidx=this._dashIdx;varnDash=lineDash.length;varx;vary;vartmpLen=0;if(offset<0){// Convert to positive offsetoffset=dashSum+offset;}offset%=dashSum;// Bezier approx lengthfor(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 offsetfor(;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// Bad result if dash is longidx%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(idx%2!==0)&&ctx.lineTo(x3,y3);dx=x3-x;dy=y3-y;this._dashOffset=-mathSqrt$1(dx*dx+dy*dy);},_dashedQuadraticTo:function(x1,y1,x2,y2){// Convert quadratic to cubic using degree elevationvarx3=x2;vary3=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);},/** * 转成静态的 Float32Array 减少堆内存占用 * Convert dynamic array to static Float32Array */toStatic:function(){vardata=this.data;if(datainstanceofArray){data.length=this._len;if(hasTypedArray){this.data=newFloat32Array(data);}}},/** * @return {module:zrender/core/BoundingRect}*/ getBoundingRect: function () { min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE; max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE; var data = this.data; var xi = 0; var yi = 0; var x0 = 0; var y0 = 0; for (var i = 0; i < data.length;) { var cmd = data[i++]; if (i == 1) { //如果第一个命令是L,C,Q// 则 previous point 同绘制命令的第一个 point//// 第一个命令为 Arc 的情况下会在后面特殊处理xi=data[i];yi=data[i+1];x0=xi;y0=yi;}switch(cmd){caseCMD.M:// moveTo 命令重新创建一个新的 subpath, 并且更新新的起点// 在 closePath 的时候使用x0=data[i++];y0=data[i++];xi=x0;yi=y0;min2[0]=x0;min2[1]=y0;max2[0]=x0;max2[1]=y0;break;caseCMD.L:fromLine(xi,yi,data[i],data[i+1],min2,max2);xi=data[i++];yi=data[i++];break;caseCMD.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;caseCMD.Q:fromQuadratic(xi,yi,data[i++],data[i++],data[i],data[i+1],min2,max2);xi=data[i++];yi=data[i++];break;caseCMD.A:// TODO Arc 判断的开销比较大varcx=data[i++];varcy=data[i++];varrx=data[i++];varry=data[i++];varstartAngle=data[i++];varendAngle=data[i++]+startAngle;// TODO Arc 旋转varpsi=data[i++];varanticlockwise=1-data[i++];if(i==1){// 直接使用 arc 命令// 第一个命令起点还未定义x0=mathCos$1(startAngle)*rx+cx;y0=mathSin$1(startAngle)*ry+cy;}fromArc(cx,cy,rx,ry,startAngle,endAngle,anticlockwise,min2,max2);xi=mathCos$1(endAngle)*rx+cx;yi=mathSin$1(endAngle)*ry+cy;break;caseCMD.R:x0=xi=data[i++];y0=yi=data[i++];varwidth=data[i++];varheight=data[i++];// Use fromLinefromLine(x0,y0,x0+width,y0+height,min2,max2);break;caseCMD.Z:xi=x0;yi=y0;break;}// Unionmin(min$1,min$1,min2);max(max$1,max$1,max2);}// No dataif(i===0){min$1[0]=min$1[1]=max$1[0]=max$1[1]=0;}returnnewBoundingRect(min$1[0],min$1[1],max$1[0]-min$1[0],max$1[1]-min$1[1]);},/** * Rebuild path from current data * Rebuild path will not consider javascript implemented line dash. * @param {CanvasRenderingContext2D} ctx */rebuildPath:function(ctx){vard=this.data;varx0,y0;varxi,yi;varx,y;varux=this._ux;varuy=this._uy;varlen$$1=this._len;for(vari=0;i<len$$1;){varcmd=d[i++];if(i==1){// 如果第一个命令是 L, C, Q// 则 previous point 同绘制命令的第一个 point//// 第一个命令为 Arc 的情况下会在后面特殊处理xi=d[i];yi=d[i+1];x0=xi;y0=yi;}switch(cmd){caseCMD.M:x0=xi=d[i++];y0=yi=d[i++];ctx.moveTo(xi,yi);break;caseCMD.L:x=d[i++];y=d[i++];// Not draw too small seg betweenif(mathAbs(x-xi)>ux||mathAbs(y-yi)>uy||i===len$$1-1){ctx.lineTo(x,y);xi=x;yi=y;}break;caseCMD.C:ctx.bezierCurveTo(d[i++],d[i++],d[i++],d[i++],d[i++],d[i++]);xi=d[i-2];yi=d[i-1];break;caseCMD.Q:ctx.quadraticCurveTo(d[i++],d[i++],d[i++],d[i++]);xi=d[i-2];yi=d[i-1];break;caseCMD.A:varcx=d[i++];varcy=d[i++];varrx=d[i++];varry=d[i++];vartheta=d[i++];vardTheta=d[i++];varpsi=d[i++];varfs=d[i++];varr=(rx>ry)?rx:ry;varscaleX=(rx>ry)?1:rx/ry;varscaleY=(rx>ry)?ry/rx:1;varisEllipse=Math.abs(rx-ry)>1e-3;varendAngle=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 命令// 第一个命令起点还未定义x0=mathCos$1(theta)*rx+cx;y0=mathSin$1(theta)*ry+cy;}xi=mathCos$1(endAngle)*rx+cx;yi=mathSin$1(endAngle)*ry+cy;break;caseCMD.R:x0=xi=d[i];y0=yi=d[i+1];ctx.rect(d[i++],d[i++],d[i++],d[i++]);break;caseCMD.Z:ctx.closePath();xi=x0;yi=y0;}}}};PathProxy.CMD=CMD;/** * 线段包含判断 * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @param {number} lineWidth * @param {number} x * @param {number} y * @return {boolean} */functioncontainStroke$1(x0,y0,x1,y1,lineWidth,x,y){if(lineWidth===0){returnfalse;}var_l=lineWidth;var_a=0;var_b=x0;// Quick rejectif((y>y0+_l&&y>y1+_l)||(y<y0-_l&&y<y1-_l)||(x>x0+_l&&x>x1+_l)||(x<x0-_l&&x<x1-_l)){returnfalse;}if(x0!==x1){_a=(y0-y1)/(x0-x1);_b=(x0*y1-x1*y0)/(x0-x1);}else{returnMath.abs(x-x0)<=_l/2;}vartmp=_a*x-y+_b;var_s=tmp*tmp/(_a*_a+1);return_s<=_l/2*_l/2;}/** * 三次贝塞尔曲线描边包含判断 * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} x3 * @param {number} y3 * @param {number} lineWidth * @param {number} x * @param {number} y * @return {boolean} */functioncontainStroke$2(x0,y0,x1,y1,x2,y2,x3,y3,lineWidth,x,y){if(lineWidth===0){returnfalse;}var_l=lineWidth;// Quick rejectif((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)){returnfalse;}vard=cubicProjectPoint(x0,y0,x1,y1,x2,y2,x3,y3,x,y,null);returnd<=_l/2;}/** * 二次贝塞尔曲线描边包含判断 * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} lineWidth * @param {number} x * @param {number} y * @return {boolean} */functioncontainStroke$3(x0,y0,x1,y1,x2,y2,lineWidth,x,y){if(lineWidth===0){returnfalse;}var_l=lineWidth;// Quick rejectif((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)){returnfalse;}vard=quadraticProjectPoint(x0,y0,x1,y1,x2,y2,x,y,null);returnd<=_l/2;}varPI2$3=Math.PI*2;functionnormalizeRadian(angle){angle%=PI2$3;if(angle<0){angle+=PI2$3;}returnangle;}varPI2$2=Math.PI*2;/** * 圆弧描边包含判断 * @param {number} cx * @param {number} cy * @param {number} r * @param {number} startAngle * @param {number} endAngle * @param {boolean} anticlockwise * @param {number} lineWidth * @param {number} x * @param {number} y * @return {Boolean} */functioncontainStroke$4(cx,cy,r,startAngle,endAngle,anticlockwise,lineWidth,x,y){if(lineWidth===0){returnfalse;}var_l=lineWidth;x-=cx;y-=cy;vard=Math.sqrt(x*x+y*y);if((d-_l>r)||(d+_l<r)){returnfalse;}if(Math.abs(startAngle-endAngle)%PI2$2<1e-4){// Is a circlereturntrue;}if(anticlockwise){vartmp=startAngle;startAngle=normalizeRadian(endAngle);endAngle=normalizeRadian(tmp);}else{startAngle=normalizeRadian(startAngle);endAngle=normalizeRadian(endAngle);}if(startAngle>endAngle){endAngle+=PI2$2;}varangle=Math.atan2(y,x);if(angle<0){angle+=PI2$2;}return(angle>=startAngle&&angle<=endAngle)||(angle+PI2$2>=startAngle&&angle+PI2$2<=endAngle);}functionwindingLine(x0,y0,x1,y1,x,y){if((y>y0&&y>y1)||(y<y0&&y<y1)){return0;}// Ignore horizontal lineif(y1===y0){return0;}vardir=y1<y0?1:-1;vart=(y-y0)/(y1-y0);// Avoid winding error when intersection point is the connect point of two line of polygonif(t===1||t===0){dir=y1<y0?0.5:-0.5;}varx_=t*(x1-x0)+x0;// If (x, y) on the line, considered as "contain".returnx_===x?Infinity:x_>x?dir:0;}varCMD$1=PathProxy.CMD;varPI2$1=Math.PI*2;varEPSILON$2=1e-4;functionisAroundEqual(a,b){returnMath.abs(a-b)<EPSILON$2;}// 临时数组varroots=[-1,-1,-1];varextrema=[-1,-1];functionswapExtrema(){vartmp=extrema[0];extrema[0]=extrema[1];extrema[1]=tmp;}functionwindingCubic(x0,y0,x1,y1,x2,y2,x3,y3,x,y){// Quick rejectif((y>y0&&y>y1&&y>y2&&y>y3)||(y<y0&&y<y1&&y<y2&&y<y3)){return0;}varnRoots=cubicRootAt(y0,y1,y2,y3,y,roots);if(nRoots===0){return0;}else{varw=0;varnExtrema=-1;vary0_,y1_;for(vari=0;i<nRoots;i++){vart=roots[i];// Avoid winding error when intersection point is the connect point of two line of polygonvarunit=(t===0||t===1)?0.5:1;varx_=cubicAt(x0,x1,x2,x3,t);if(x_<x){// Quick rejectcontinue;}if(nExtrema<0){nExtrema=cubicExtrema(y0,y1,y2,y3,extrema);if(extrema[1]<extrema[0]&&nExtrema>1){swapExtrema();}y0_=cubicAt(y0,y1,y2,y3,extrema[0]);if(nExtrema>1){y1_=cubicAt(y0,y1,y2,y3,extrema[1]);}}if(nExtrema==2){// 分成三段单调函数if(t<extrema[0]){w+=y0_<y0?unit:-unit;}elseif(t<extrema[1]){w+=y1_<y0_?unit:-unit;}else{w+=y3<y1_?unit:-unit;}}else{// 分成两段单调函数if(t<extrema[0]){w+=y0_<y0?unit:-unit;}else{w+=y3<y0_?unit:-unit;}}}returnw;}}functionwindingQuadratic(x0,y0,x1,y1,x2,y2,x,y){// Quick rejectif((y>y0&&y>y1&&y>y2)||(y<y0&&y<y1&&y<y2)){return0;}varnRoots=quadraticRootAt(y0,y1,y2,y,roots);if(nRoots===0){return0;}else{vart=quadraticExtremum(y0,y1,y2);if(t>=0&&t<=1){varw=0;vary_=quadraticAt(y0,y1,y2,t);for(vari=0;i<nRoots;i++){// Remove one endpoint.varunit=(roots[i]===0||roots[i]===1)?0.5:1;varx_=quadraticAt(x0,x1,x2,roots[i]);if(x_<x){// Quick rejectcontinue;}if(roots[i]<t){w+=y_<y0?unit:-unit;}else{w+=y2<y_?unit:-unit;}}returnw;}else{// Remove one endpoint.varunit=(roots[0]===0||roots[0]===1)?0.5:1;varx_=quadraticAt(x0,x1,x2,roots[0]);if(x_<x){// Quick rejectreturn0;}returny2<y0?unit:-unit;}}}// TODO// Arc 旋转functionwindingArc(cx,cy,r,startAngle,endAngle,anticlockwise,x,y){y-=cy;if(y>r||y<-r){return0;}vartmp=Math.sqrt(r*r-y*y);roots[0]=-tmp;roots[1]=tmp;vardiff=Math.abs(startAngle-endAngle);if(diff<1e-4){return0;}if(diff%PI2$1<1e-4){// Is a circlestartAngle=0;endAngle=PI2$1;vardir=anticlockwise?1:-1;if(x>=roots[0]+cx&&x<=roots[1]+cx){returndir;}else{return0;}}if(anticlockwise){vartmp=startAngle;startAngle=normalizeRadian(endAngle);endAngle=normalizeRadian(tmp);}else{startAngle=normalizeRadian(startAngle);endAngle=normalizeRadian(endAngle);}if(startAngle>endAngle){endAngle+=PI2$1;}varw=0;for(vari=0;i<2;i++){varx_=roots[i];if(x_+cx>x){varangle=Math.atan2(y,x_);vardir=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;}}}returnw;}functioncontainPath(data,lineWidth,isStroke,x,y){varw=0;varxi=0;varyi=0;varx0=0;vary0=0;for(vari=0;i<data.length;){varcmd=data[i++];// Begin a new subpathif(cmd===CMD$1.M&&i>1){// Close previous subpathif(!isStroke){w+=windingLine(xi,yi,x0,y0,x,y);}// 如果被任何一个 subpath 包含// if (w !== 0) {// return true;// }}if(i==1){// 如果第一个命令是 L, C, Q// 则 previous point 同绘制命令的第一个 point//// 第一个命令为 Arc 的情况下会在后面特殊处理xi=data[i];yi=data[i+1];x0=xi;y0=yi;}switch(cmd){caseCMD$1.M:// moveTo 命令重新创建一个新的 subpath, 并且更新新的起点// 在 closePath 的时候使用x0=data[i++];y0=data[i++];xi=x0;yi=y0;break;caseCMD$1.L:if(isStroke){if(containStroke$1(xi,yi,data[i],data[i+1],lineWidth,x,y)){returntrue;}}else{// NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaNw+=windingLine(xi,yi,data[i],data[i+1],x,y)||0;}xi=data[i++];yi=data[i++];break;caseCMD$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)){returntrue;}}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;caseCMD$1.Q:if(isStroke){if(containStroke$3(xi,yi,data[i++],data[i++],data[i],data[i+1],lineWidth,x,y)){returntrue;}}else{w+=windingQuadratic(xi,yi,data[i++],data[i++],data[i],data[i+1],x,y)||0;}xi=data[i++];yi=data[i++];break;caseCMD$1.A:// TODO Arc 判断的开销比较大varcx=data[i++];varcy=data[i++];varrx=data[i++];varry=data[i++];vartheta=data[i++];vardTheta=data[i++];// TODO Arc 旋转varpsi=data[i++];varanticlockwise=1-data[i++];varx1=Math.cos(theta)*rx+cx;vary1=Math.sin(theta)*ry+cy;// 不是直接使用 arc 命令if(i>1){w+=windingLine(xi,yi,x1,y1,x,y);}else{// 第一个命令起点还未定义x0=x1;y0=y1;}// zr 使用scale来模拟椭圆, 这里也对x做一定的缩放var_x=(x-cx)*ry/rx+cx;if(isStroke){if(containStroke$4(cx,cy,ry,theta,theta+dTheta,anticlockwise,lineWidth,_x,y)){returntrue;}}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;caseCMD$1.R:x0=xi=data[i++];y0=yi=data[i++];varwidth=data[i++];varheight=data[i++];varx1=x0+width;vary1=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)){returntrue;}}else{// FIXME Clockwise ?w+=windingLine(x1,y0,x1,y1,x,y);w+=windingLine(x0,y1,x0,y0,x,y);}break;caseCMD$1.Z:if(isStroke){if(containStroke$1(xi,yi,x0,y0,lineWidth,x,y)){returntrue;}}else{// Close a subpathw+=windingLine(xi,yi,x0,y0,x,y);// 如果被任何一个 subpath 包含// FIXME subpaths may overlap// if (w !== 0) {// return true;// }}xi=x0;yi=y0;break;}}if(!isStroke&&!isAroundEqual(yi,y0)){w+=windingLine(xi,yi,x0,y0,x,y)||0;}returnw!==0;}functioncontain(pathData,x,y){returncontainPath(pathData,0,false,x,y);}functioncontainStroke(pathData,lineWidth,x,y){returncontainPath(pathData,lineWidth,true,x,y);}vargetCanvasPattern=Pattern.prototype.getCanvasPattern;varabs=Math.abs;varpathProxyForDraw=newPathProxy(true);/** * @alias module:zrender/graphic/Path*@extendsmodule:zrender/graphic/Displayable*@constructor*@param{Object}opts*/function Path(opts) { Displayable.call(this, opts); /***@type{module:zrender/core/PathProxy}*@readOnly*/ this.path = null;}Path.prototype = { constructor: Path, type: 'path', __dirtyPath: true, strokeContainThreshold: 5, brush: function (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; //Updategradientbecauseboundingrectmaychangedif(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 patternif(hasFillGradient){// PENDING If may have affect the statectx.fillStyle=this._fillGradient;}elseif(hasFillPattern){ctx.fillStyle=getCanvasPattern.call(fill,ctx);}if(hasStrokeGradient){ctx.strokeStyle=this._strokeGradient;}elseif(hasStrokePattern){ctx.strokeStyle=getCanvasPattern.call(stroke,ctx);}varlineDash=style.lineDash;varlineDashOffset=style.lineDashOffset;varctxLineDash=!!ctx.setLineDash;// Update path sx, syvarscale=this.getGlobalScale();path.setScale(scale[0],scale[1]);// Proxy context// Rebuild path in following 2 cases// 1. Path is dirty// 2. Path needs javascript implemented lineDash stroking.// In this case, lineDash information will not be saved in PathProxyif(this.__dirtyPath||(lineDash&&!ctxLineDash&&hasStroke)){path.beginPath(ctx);// Setting line dash before build pathif(lineDash&&!ctxLineDash){path.setLineDash(lineDash);path.setLineDashOffset(lineDashOffset);}this.buildPath(path,this.shape,false);// Clear path dirty flagif(this.path){this.__dirtyPath=false;}}else{// Replay path buildingctx.beginPath();this.path.rebuildPath(ctx);}if(hasFill){if(style.fillOpacity!=null){varoriginalGlobalAlpha=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){varoriginalGlobalAlpha=ctx.globalAlpha;ctx.globalAlpha=style.strokeOpacity*style.opacity;path.stroke(ctx);ctx.globalAlpha=originalGlobalAlpha;}else{path.stroke(ctx);}}if(lineDash&&ctxLineDash){// PENDING// Remove lineDashctx.setLineDash([]);}// Draw rect textif(style.text!=null){// Only restore transform when needs draw text.this.restoreTransform(ctx);this.drawRectText(ctx,this.getBoundingRect());}},// When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath// Like in circlebuildPath:function(ctx,shapeCfg,inBundle){},createPathProxy:function(){this.path=newPathProxy();},getBoundingRect:function(){varrect=this._rect;varstyle=this.style;varneedsUpdateRect=!rect;if(needsUpdateRect){varpath=this.path;if(!path){// Create path on demand.path=this.path=newPathProxy();}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// 1. Element changes scale or lineWidth// 2. Shape is changedvarrectWithStroke=this._rectWithStroke||(this._rectWithStroke=rect.clone());if(this.__dirty||needsUpdateRect){rectWithStroke.copy(rect);// FIXME Must after updateTransformvarw=style.lineWidth;// PENDING, Min line width is needed when line is horizontal or verticalvarlineScale=style.strokeNoScale?this.getLineScale():1;// Only add extra hover lineWidth when there are no fillif(!style.hasFill()){w=Math.max(w,this.strokeContainThreshold||4);}// Consider line width// Line scale can't be 0;if(lineScale>1e-10){rectWithStroke.width+=w/lineScale;rectWithStroke.height+=w/lineScale;rectWithStroke.x-=w/lineScale/2;rectWithStroke.y-=w/lineScale/2;}}// Return rect with strokereturnrectWithStroke;}returnrect;},contain:function(x,y){varlocalPos=this.transformCoordToLocal(x,y);varrect=this.getBoundingRect();varstyle=this.style;x=localPos[0];y=localPos[1];if(rect.contain(x,y)){varpathData=this.path.data;if(style.hasStroke()){varlineWidth=style.lineWidth;varlineScale=style.strokeNoScale?this.getLineScale():1;// Line scale can't be 0;if(lineScale>1e-10){// Only add extra hover lineWidth when there are no fillif(!style.hasFill()){lineWidth=Math.max(lineWidth,this.strokeContainThreshold);}if(containStroke(pathData,lineWidth/lineScale,x,y)){returntrue;}}}if(style.hasFill()){returncontain(pathData,x,y);}}returnfalse;},/** * @param {boolean} dirtyPath */dirty:function(dirtyPath){if(dirtyPath==null){dirtyPath=true;}// Only mark dirty, not mark cleanif(dirtyPath){this.__dirtyPath=dirtyPath;this._rect=null;}this.__dirty=this.__dirtyText=true;this.__zr&&this.__zr.refresh();// Used as a clipping pathif(this.__clipTarget){this.__clipTarget.dirty();}},/** * Alias for animate('shape') * @param {boolean} loop */animateShape:function(loop){returnthis.animate('shape',loop);},// Overwrite attrKVattrKV:function(key,value){// FIXMEif(key==='shape'){this.setShape(value);this.__dirtyPath=true;this._rect=null;}else{Displayable.prototype.attrKV.call(this,key,value);}},/** * @param {Object|string} key * @param {*} value */setShape:function(key,value){varshape=this.shape;// Path from string may not have shapeif(shape){if(isObject$1(key)){for(varnameinkey){if(key.hasOwnProperty(name)){shape[name]=key[name];}}}else{shape[key]=value;}this.dirty(true);}returnthis;},getLineScale:function(){varm=this.transform;// Get the line scale.// Determinant of `m` means how much the area is enlarged by the// transformation. So its square root can be used as a scale factor// for width.returnm&&abs(m[0]-1)>1e-10&&abs(m[3]-1)>1e-10?Math.sqrt(abs(m[0]*m[3]-m[2]*m[1])):1;}};/** * 扩展一个 Path element, 比如星形,圆等。 * Extend a path element * @param {Object} props * @param {string} props.type Path type * @param {Function} props.init Initialize * @param {Function} props.buildPath Overwrite buildPath method * @param {Object} [props.style] Extended default style config * @param {Object} [props.shape] Extended default shape config */Path.extend=function(defaults$$1){varSub=function(opts){Path.call(this,opts);if(defaults$$1.style){// Extend default stylethis.style.extendFrom(defaults$$1.style,false);}// Extend default shapevardefaultShape=defaults$$1.shape;if(defaultShape){this.shape=this.shape||{};varthisShape=this.shape;for(varnameindefaultShape){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 等引用对象for(varnameindefaults$$1){// Extending prototype values and methodsif(name!=='style'&&name!=='shape'){Sub.prototype[name]=defaults$$1[name];}}returnSub;};inherits(Path,Displayable);varCMD$2=PathProxy.CMD;varpoints=[[],[],[]];varmathSqrt$3=Math.sqrt;varmathAtan2=Math.atan2;vartransformPath=function(path,m){vardata=path.data;varcmd;varnPoint;vari;varj;vark;varp;varM=CMD$2.M;varC=CMD$2.C;varL=CMD$2.L;varR=CMD$2.R;varA=CMD$2.A;varQ=CMD$2.Q;for(i=0,j=0;i<data.length;){cmd=data[i++];j=i;nPoint=0;switch(cmd){caseM:nPoint=1;break;caseL:nPoint=1;break;caseC:nPoint=3;break;caseQ:nPoint=2;break;caseA:varx=m[4];vary=m[5];varsx=mathSqrt$3(m[0]*m[0]+m[1]*m[1]);varsy=mathSqrt$3(m[2]*m[2]+m[3]*m[3]);varangle=mathAtan2(-m[1]/sy,m[0]/sx);// cxdata[i]*=sx;data[i++]+=x;// cydata[i]*=sy;data[i++]+=y;// Scale rx and ry// FIXME Assume psi is 0 heredata[i++]*=sx;data[i++]*=sy;// Start angledata[i++]+=angle;// end angledata[i++]+=angle;// FIXME psii+=2;j=i;break;caseR:// x0, y0p[0]=data[i++];p[1]=data[i++];applyTransform(p,p,m);data[j++]=p[0];data[j++]=p[1];// x1, y1p[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++){varp=points[k];p[0]=data[i++];p[1]=data[i++];applyTransform(p,p,m);// Write backdata[j++]=p[0];data[j++]=p[1];}}};// command chars// var cc = [// 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',// 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'// ];varmathSqrt=Math.sqrt;varmathSin=Math.sin;varmathCos=Math.cos;varPI=Math.PI;varvMag=function(v){returnMath.sqrt(v[0]*v[0]+v[1]*v[1]);};varvRatio=function(u,v){return(u[0]*v[0]+u[1]*v[1])/(vMag(u)*vMag(v));};varvAngle=function(u,v){return(u[0]*v[1]<u[1]*v[0]?-1:1)*Math.acos(vRatio(u,v));};functionprocessArc(x1,y1,x2,y2,fa,fs,rx,ry,psiDeg,cmd,path){varpsi=psiDeg*(PI/180.0);varxp=mathCos(psi)*(x1-x2)/2.0+mathSin(psi)*(y1-y2)/2.0;varyp=-1*mathSin(psi)*(x1-x2)/2.0+mathCos(psi)*(y1-y2)/2.0;varlambda=(xp*xp)/(rx*rx)+(yp*yp)/(ry*ry);if(lambda>1){rx*=mathSqrt(lambda);ry*=mathSqrt(lambda);}varf=(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;varcxp=f*rx*yp/ry;varcyp=f*-ry*xp/rx;varcx=(x1+x2)/2.0+mathCos(psi)*cxp-mathSin(psi)*cyp;varcy=(y1+y2)/2.0+mathSin(psi)*cxp+mathCos(psi)*cyp;vartheta=vAngle([1,0],[(xp-cxp)/rx,(yp-cyp)/ry]);varu=[(xp-cxp)/rx,(yp-cyp)/ry];varv=[(-1*xp-cxp)/rx,(-1*yp-cyp)/ry];vardTheta=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);}varcommandReg=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;// Consider case:// (1) delimiter can be comma or space, where continuous commas// or spaces should be seen as one comma.// (2) value can be like:// '2e-4', 'l.5.9' (ignore 0), 'M-10-10', 'l-2.43e-1,34.9983',// 'l-.5E1,54', '121-23-44-11' (no delimiter)varnumberReg=/-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;// var valueSplitReg = /[\s,]+/;functioncreatePathProxyFromString(data){if(!data){returnnewPathProxy();}// var data = data.replace(/-/g, ' -')// .replace(/ /g, ' ')// .replace(/ /g, ',')// .replace(/,,/g, ',');// var n;// create pipes so that we can split the data// for (n = 0; n < cc.length; n++) {// cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);// }// data = data.replace(/-/g, ',-');// create array// var arr = cs.split('|');// init context pointvarcpx=0;varcpy=0;varsubpathX=cpx;varsubpathY=cpy;varprevCmd;varpath=newPathProxy();varCMD=PathProxy.CMD;// commandReg.lastIndex = 0;// var cmdResult;// while ((cmdResult = commandReg.exec(data)) != null) {// var cmdStr = cmdResult[1];// var cmdContent = cmdResult[2];varcmdList=data.match(commandReg);for(varl=0;l<cmdList.length;l++){varcmdText=cmdList[l];varcmdStr=cmdText.charAt(0);varcmd;// String#split is faster a little bit than String#replace or RegExp#exec.// var p = cmdContent.split(valueSplitReg);// var pLen = 0;// for (var i = 0; i < p.length; i++) {// // '' and other invalid str => NaN// var val = parseFloat(p[i]);// !isNaN(val) && (p[pLen++] = val);// }varp=cmdText.match(numberReg)||[];varpLen=p.length;for(vari=0;i<pLen;i++){p[i]=parseFloat(p[i]);}varoff=0;while(off<pLen){varctlPtx;varctlPty;varrx;varry;varpsi;varfa;varfs;varx1=cpx;vary1=cpy;// convert l, H, h, V, and v to Lswitch(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;varlen=path.len();varpathData=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;varlen=path.len();varpathData=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;varlen=path.len();varpathData=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;varlen=path.len();varpathData=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.cpx=subpathX;cpy=subpathY;}prevCmd=cmd;}path.toStatic();returnpath;}// TODO Optimize double memory cost problemfunctioncreatePathOptions(str,opts){varpathProxy=createPathProxyFromString(str);opts=opts||{};opts.buildPath=function(path){if(path.setData){path.setData(pathProxy.data);// Svg and vml renderer don't have contextvarctx=path.getContext();if(ctx){path.rebuildPath(ctx);}}else{varctx=path;pathProxy.rebuildPath(ctx);}};opts.applyTransform=function(m){transformPath(pathProxy,m);this.dirty(true);};returnopts;}/** * Create a Path object from path string data * http://www.w3.org/TR/SVG/paths.html#PathData*@param{Object}optsOtheroptions*/function createFromString(str, opts) { return new Path(createPathOptions(str, opts));}/***CreateaPathclassfrompathstringdata*@param{string}str*@param{Object}optsOtheroptions*/function extendFromString(str, opts) { return Path.extend(createPathOptions(str, opts));}/***Mergemultiplepaths*///TODOApplytransform// TODO stroke dash// TODO Optimize double memory cost problemfunctionmergePath$1(pathEls,opts){varpathList=[];varlen=pathEls.length;for(vari=0;i<len;i++){varpathEl=pathEls[i];if(!pathEl.path){pathEl.createPathProxy();}if(pathEl.__dirtyPath){pathEl.buildPath(pathEl.path,pathEl.shape,true);}pathList.push(pathEl.path);}varpathBundle=newPath(opts);// Need path proxy.pathBundle.createPathProxy();pathBundle.buildPath=function(path){path.appendPath(pathList);// Svg and vml renderer don't have contextvarctx=path.getContext();if(ctx){path.rebuildPath(ctx);}};returnpathBundle;}/** * @alias zrender/graphic/Text*@extendsmodule:zrender/graphic/Displayable*@constructor*@param{Object}opts*/var Text = function (opts) { //jshintignore:lineDisplayable.call(this,opts);};Text.prototype={constructor:Text,type:'text',brush:function(ctx,prevEl){varstyle=this.style;// Optimize, avoid normalize every time.this.__dirty&&normalizeTextStyle(style,true);// Use props with prefix 'text'.style.fill=style.stroke=style.shadowBlur=style.shadowColor=style.shadowOffsetX=style.shadowOffsetY=null;vartext=style.text;// Convert to stringtext!=null&&(text+='');// Do not apply style.bind in Text node. Because the real bind job// is in textHelper.renderText, and performance of text render should// be considered.// style.bind(ctx, this, prevEl);if(!needDrawText(text,style)){return;}this.setTransform(ctx);renderText(this,ctx,text,style,null,prevEl);this.restoreTransform(ctx);},getBoundingRect:function(){varstyle=this.style;// Optimize, avoid normalize every time.this.__dirty&&normalizeTextStyle(style,true);if(!this._rect){vartext=style.text;text!=null?(text+=''):(text='');varrect=getBoundingRect(style.text+'',style.font,style.textAlign,style.textVerticalAlign,style.textPadding,style.rich);rect.x+=style.x||0;rect.y+=style.y||0;if(getStroke(style.textStroke,style.textStrokeWidth)){varw=style.textStrokeWidth;rect.x-=w/2;rect.y-=w/2;rect.width+=w;rect.height+=w;}this._rect=rect;}returnthis._rect;}};inherits(Text,Displayable);/** * 圆形 * @module zrender/shape/Circle*/var Circle = Path.extend({ type: 'circle', shape: { cx: 0, cy: 0, r: 0 }, buildPath: function (ctx, shape, inBundle) { //BetterstrokinginShapeBundle// Always do it may have performence issue ( fill may be 2x more cost)if(inBundle){ctx.moveTo(shape.cx+shape.r,shape.cy);}// else {// if (ctx.allocate && !ctx.data.length) {// ctx.allocate(ctx.CMD_MEM_SIZE.A);// }// }// Better stroking in ShapeBundle// ctx.moveTo(shape.cx + shape.r, shape.cy);ctx.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**),// where exception "unexpected call to method or property access"// might be thrown when calling ctx.fill or ctx.stroke after a path// whose area size is zero is drawn and ctx.clip() is called and// shadowBlur is set. See #4572, #3112, #5777.// (e.g.,// ctx.moveTo(10, 10);// ctx.lineTo(20, 10);// ctx.closePath();// ctx.clip();// ctx.shadowBlur = 10;// ...// ctx.fill();// )varshadowTemp=[['shadowBlur',0],['shadowColor','#000'],['shadowOffsetX',0],['shadowOffsetY',0]];varfixClipWithShadow=function(orignalBrush){// version string can be: '11.0'return(env$1.browser.ie&&env$1.browser.version>=11)?function(){varclipPaths=this.__clipPaths;varstyle=this.style;varmodified;if(clipPaths){for(vari=0;i<clipPaths.length;i++){varclipPath=clipPaths[i];varshape=clipPath&&clipPath.shape;vartype=clipPath&&clipPath.type;if(shape&&((type==='sector'&&shape.startAngle===shape.endAngle)||(type==='rect'&&(!shape.width||!shape.height)))){for(varj=0;j<shadowTemp.length;j++){// It is save to put shadowTemp static, because shadowTemp// will be all modified each item brush called.shadowTemp[j][2]=style[shadowTemp[j][0]];style[shadowTemp[j][0]]=shadowTemp[j][1];}modified=true;break;}}}orignalBrush.apply(this,arguments);if(modified){for(varj=0;j<shadowTemp.length;j++){style[shadowTemp[j][0]]=shadowTemp[j][2];}}}:orignalBrush;};/** * 扇形 * @module zrender/graphic/shape/Sector*/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 (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(); }});/***圆环*@modulezrender/graphic/shape/Ring*/var Ring = Path.extend({ type: 'ring', shape: { cx: 0, cy: 0, r: 0, r0: 0 }, buildPath: function (ctx, shape) { var x = shape.cx; var y = shape.cy; var PI2 = Math.PI * 2; ctx.moveTo(x + shape.r, y); ctx.arc(x, y, shape.r, 0, PI2, false); ctx.moveTo(x + shape.r0, y); ctx.arc(x, y, shape.r0, 0, PI2, true); }});/***Catmull-Romspline插值折线*@modulezrender/shape/util/smoothSpline*@authorpissang(https://www.github.com/pissang)*Kener(@Kener-林峰,kener.linfeng@gmail.com)*errorrik(errorrik@gmail.com)*//***@inner*/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;}/***@aliasmodule:zrender/shape/util/smoothSpline*@param{Array}points线段顶点数组*@param{boolean}isLoop*@return{Array}*/var smoothSpline = function (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(vari=0;i<segs;i++){varpos=i/(segs-1)*(isLoop?len$$1:len$$1-1);varidx=Math.floor(pos);varw=pos-idx;varp0;varp1=points[idx%len$$1];varp2;varp3;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];}varw2=w*w;varw3=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)]);}returnret;};/** * 贝塞尔平滑曲线 * @module zrender/shape/util/smoothBezier*@authorpissang(https://www.github.com/pissang)*Kener(@Kener-林峰,kener.linfeng@gmail.com)*errorrik(errorrik@gmail.com)*//***贝塞尔平滑曲线*@aliasmodule:zrender/shape/util/smoothBezier*@param{Array}points线段顶点数组*@param{number}smooth平滑等级,0-1*@param{boolean}isLoop*@param{Array}constraint将计算出来的控制点约束在一个包围盒内*比如[[0,0],[100,100]],这个包围盒会与*整个折线的包围盒做一个并集用来约束控制点。*@param{Array}计算出来的控制点数组*/var smoothBezier = function (points, smooth, isLoop, constraint) { var cps = []; var v = []; var v1 = []; var v2 = []; var prevPoint; var nextPoint; var min$$1, 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]); } //与指定的包围盒做并集min(min$$1,min$$1,constraint[0]);max(max$$1,max$$1,constraint[1]);}for(vari=0,len$$1=points.length;i<len$$1;i++){varpoint=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 lengthscale(v,v,smooth);vard0=distance(point,prevPoint);vard1=distance(point,nextPoint);varsum=d0+d1;if(sum!==0){d0/=sum;d1/=sum;}scale(v1,v,-d0);scale(v2,v,d1);varcp0=add([],point,v1);varcp1=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());}returncps;};functionbuildPath$1(ctx,shape,closePath){varpoints=shape.points;varsmooth=shape.smooth;if(points&&points.length>=2){if(smooth&&smooth!=='spline'){varcontrolPoints=smoothBezier(points,smooth,closePath,shape.smoothConstraint);ctx.moveTo(points[0][0],points[0][1]);varlen=points.length;for(vari=0;i<(closePath?len:len-1);i++){varcp1=controlPoints[i*2];varcp2=controlPoints[i*2+1];varp=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(vari=1,l=points.length;i<l;i++){ctx.lineTo(points[i][0],points[i][1]);}}closePath&&ctx.closePath();}}/** * 多边形 * @module zrender/shape/Polygon*/var Polygon = Path.extend({ type: 'polygon', shape: { points: null, smooth: false, smoothConstraint: null }, buildPath: function (ctx, shape) { buildPath$1(ctx, shape, true); }});/***@modulezrender/graphic/shape/Polyline*/var Polyline = Path.extend({ type: 'polyline', shape: { points: null, smooth: false, smoothConstraint: null }, style: { stroke: '#000', fill: null }, buildPath: function (ctx, shape) { buildPath$1(ctx, shape, false); }});/***矩形*@modulezrender/graphic/shape/Rect*/var Rect = Path.extend({ type: 'rect', shape: { //左上、右上、右下、左下角的半径依次为r1、r2、r3、r4// r缩写为1 相当于 [1, 1, 1, 1]// r缩写为[1] 相当于 [1, 1, 1, 1]// r缩写为[1, 2] 相当于 [1, 2, 1, 2]// r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2]r:0,x:0,y:0,width:0,height:0},buildPath:function(ctx,shape){varx=shape.x;vary=shape.y;varwidth=shape.width;varheight=shape.height;if(!shape.r){ctx.rect(x,y,width,height);}else{buildPath(ctx,shape);}ctx.closePath();return;}});/** * 直线 * @module zrender/graphic/shape/Line*/var Line = Path.extend({ type: 'line', shape: { //Startpointx1:0,y1:0,// End pointx2:0,y2:0,percent:1},style:{stroke:'#000',fill:null},buildPath:function(ctx,shape){varx1=shape.x1;vary1=shape.y1;varx2=shape.x2;vary2=shape.y2;varpercent=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);},/** * Get point at percent * @param {number} percent * @return {Array.<number>} */pointAt:function(p){varshape=this.shape;return[shape.x1*(1-p)+shape.x2*p,shape.y1*(1-p)+shape.y2*p];}});/** * 贝塞尔曲线 * @module zrender/shape/BezierCurve*/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,// cpy2: 0// Curve show percent, for animatingpercent:1},style:{stroke:'#000',fill:null},buildPath:function(ctx,shape){varx1=shape.x1;vary1=shape.y1;varx2=shape.x2;vary2=shape.y2;varcpx1=shape.cpx1;varcpy1=shape.cpy1;varcpx2=shape.cpx2;varcpy2=shape.cpy2;varpercent=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);}},/** * Get point at percent * @param {number} t * @return {Array.<number>} */pointAt:function(t){returnsomeVectorAt(this.shape,t,false);},/** * Get tangent at percent * @param {number} t * @return {Array.<number>} */tangentAt:function(t){varp=someVectorAt(this.shape,t,true);returnnormalize(p,p);}});/** * 圆弧 * @module zrender/graphic/shape/Arc*/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 (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); }});//CompoundPathtoimproveperformancevarCompoundPath=Path.extend({type:'compound',shape:{paths:null},_updatePathDirty:function(){vardirtyPath=this.__dirtyPath;varpaths=this.shape.paths;for(vari=0;i<paths.length;i++){// Mark as dirty if any subpath is dirtydirtyPath=dirtyPath||paths[i].__dirtyPath;}this.__dirtyPath=dirtyPath;this.__dirty=this.__dirty||dirtyPath;},beforeBrush:function(){this._updatePathDirty();varpaths=this.shape.paths||[];varscale=this.getGlobalScale();// Update path scalefor(vari=0;i<paths.length;i++){if(!paths[i].path){paths[i].createPathProxy();}paths[i].path.setScale(scale[0],scale[1]);}},buildPath:function(ctx,shape){varpaths=shape.paths||[];for(vari=0;i<paths.length;i++){paths[i].buildPath(ctx,paths[i].shape,true);}},afterBrush:function(){varpaths=this.shape.paths||[];for(vari=0;i<paths.length;i++){paths[i].__dirtyPath=false;}},getBoundingRect:function(){this._updatePathDirty();returnPath.prototype.getBoundingRect.call(this);}});/** * @param {Array.<Object>} colorStops */varGradient=function(colorStops){this.colorStops=colorStops||[];};Gradient.prototype={constructor:Gradient,addColorStop:function(offset,color){this.colorStops.push({offset:offset,color:color});}};/** * x, y, x2, y2 are all percent from 0 to 1 * @param {number} [x=0] * @param {number} [y=0] * @param {number} [x2=1] * @param {number} [y2=0] * @param {Array.<Object>} colorStops * @param {boolean} [globalCoord=false] */varLinearGradient=function(x,y,x2,y2,colorStops,globalCoord){// Should do nothing more in this constructor. Because gradient can be// declard by `color: {type: 'linear', colorStops: ...}`, where// this constructor will not be called.this.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 clonedthis.type='linear';// If use global coordthis.global=globalCoord||false;Gradient.call(this,colorStops);};LinearGradient.prototype={constructor:LinearGradient};inherits(LinearGradient,Gradient);/** * x, y, r are all percent from 0 to 1 * @param {number} [x=0.5] * @param {number} [y=0.5] * @param {number} [r=0.5] * @param {Array.<Object>} [colorStops] * @param {boolean} [globalCoord=false] */varRadialGradient=function(x,y,r,colorStops,globalCoord){// Should do nothing more in this constructor. Because gradient can be// declard by `color: {type: 'radial', colorStops: ...}`, where// this constructor will not be called.this.x=x==null?0.5:x;this.y=y==null?0.5:y;this.r=r==null?0.5:r;// Can be clonedthis.type='radial';// If use global coordthis.global=globalCoord||false;Gradient.call(this,colorStops);};RadialGradient.prototype={constructor:RadialGradient};inherits(RadialGradient,Gradient);/** * Displayable for incremental rendering. It will be rendered in a separate layer * IncrementalDisplay have too main methods. `clearDisplayables` and `addDisplayables` * addDisplayables will render the added displayables incremetally. * * It use a not clearFlag to tell the painter don't clear the layer if it's the first element. */// TODO Style override ?functionIncrementalDisplayble(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(vari=0;i<displayables.length;i++){this.addDisplayable(displayables[i],notPersistent);}};IncrementalDisplayble.prototype.eachPendingDisplayable=function(cb){for(vari=this._cursor;i<this._displayables.length;i++){cb&&cb(this._displayables[i]);}for(vari=0;i<this._temporaryDisplayables.length;i++){cb&&cb(this._temporaryDisplayables[i]);}};IncrementalDisplayble.prototype.update=function(){this.updateTransform();for(vari=this._cursor;i<this._displayables.length;i++){vardisplayable=this._displayables[i];// PENDINGdisplayable.parent=this;displayable.update();displayable.parent=null;}for(vari=0;i<this._temporaryDisplayables.length;i++){vardisplayable=this._temporaryDisplayables[i];// PENDINGdisplayable.parent=this;displayable.update();displayable.parent=null;}};IncrementalDisplayble.prototype.brush=function(ctx,prevEl){// Render persistant displayables.for(vari=this._cursor;i<this._displayables.length;i++){vardisplayable=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.for(vari=0;i<this._temporaryDisplayables.length;i++){vardisplayable=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;};varm=[];IncrementalDisplayble.prototype.getBoundingRect=function(){if(!this._rect){varrect=newBoundingRect(Infinity,Infinity,-Infinity,-Infinity);for(vari=0;i<this._displayables.length;i++){vardisplayable=this._displayables[i];varchildRect=displayable.getBoundingRect().clone();if(displayable.needLocalTransform()){childRect.applyTransform(displayable.getLocalTransform(m));}rect.union(childRect);}this._rect=rect;}returnthis._rect;};IncrementalDisplayble.prototype.contain=function(x,y){varlocalPos=this.transformCoordToLocal(x,y);varrect=this.getBoundingRect();if(rect.contain(localPos[0],localPos[1])){for(vari=0;i<this._displayables.length;i++){vardisplayable=this._displayables[i];if(displayable.contain(x,y)){returntrue;}}}returnfalse;};inherits(IncrementalDisplayble,Displayable);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var round = Math.round;var mathMax$1 = Math.max;var mathMin$1 = Math.min;var EMPTY_OBJ = {};/***Extendshapewithparameters*/function extendShape(opts) { return Path.extend(opts);}/***Extendpath*/function extendPath(pathData, opts) { return extendFromString(pathData, opts);}/***Createapathelementfrompathdatastring*@param{string}pathData*@param{Object}opts*@param{module:zrender/core/BoundingRect}rect*@param{string}[layout=cover]'center'or'cover'*/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;}/***Createaimageelementfromimageurl*@param{string}imageUrlimageurl*@param{Object}optsoptions*@param{module:zrender/core/BoundingRect}rectconstrainrect*@param{string}[layout=cover]'center'or'cover'*/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 (img) { if (layout === 'center') { var boundingRect = { width: img.width, height: img.height }; path.setStyle(centerGraphic(rect, boundingRect)); } } }); return path;}/***Getpositionofcenteredelementinboundingbox.**@param{Object}rectelementlocalboundingbox*@param{Object}boundingRectconstraintboundingbox*@return{Object}elementpositioncontainingx,y,width,andheight*/function centerGraphic(rect, boundingRect) { //Setrecttocenter,keepwidth/heightratio.varaspect=boundingRect.width/boundingRect.height;varwidth=rect.height*aspect;varheight;if(width<=rect.width){height=rect.height;}else{width=rect.width;height=width/aspect;}varcx=rect.x+rect.width/2;varcy=rect.y+rect.height/2;return{x:cx-width/2,y:cy-height/2,width:width,height:height};}varmergePath=mergePath$1;/** * Resize a path to fit the rect * @param {module:zrender/graphic/Path}path*@param{Object}rect*/function resizePath(path, rect) { if (!path.applyTransform) { return; } var pathRect = path.getBoundingRect(); var m = pathRect.calculateTransform(rect); path.applyTransform(m);}/***Subpixeloptimizelineforcanvas**@param{Object}param*@param{Object}[param.shape]*@param{number}[param.shape.x1]*@param{number}[param.shape.y1]*@param{number}[param.shape.x2]*@param{number}[param.shape.y2]*@param{Object}[param.style]*@param{number}[param.style.lineWidth]*@return{Object}Modifiedparam*/function subPixelOptimizeLine(param) { var shape = param.shape; var lineWidth = param.style.lineWidth; if (round(shape.x1 * 2) === round(shape.x2 * 2)) { shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true); } if (round(shape.y1 * 2) === round(shape.y2 * 2)) { shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true); } return param;}/***Subpixeloptimizerectforcanvas**@param{Object}param*@param{Object}[param.shape]*@param{number}[param.shape.x]*@param{number}[param.shape.y]*@param{number}[param.shape.width]*@param{number}[param.shape.height]*@param{Object}[param.style]*@param{number}[param.style.lineWidth]*@return{Object}Modifiedparam*/function subPixelOptimizeRect(param) { var shape = param.shape; var lineWidth = param.style.lineWidth; var originX = shape.x; var originY = shape.y; var originWidth = shape.width; var originHeight = shape.height; shape.x = subPixelOptimize(shape.x, lineWidth, true); shape.y = subPixelOptimize(shape.y, lineWidth, true); shape.width = Math.max( subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x, originWidth === 0 ? 0 : 1); shape.height = Math.max( subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y, originHeight === 0 ? 0 : 1); return param;}/***Subpixeloptimizeforcanvas**@param{number}positionCoordinate,suchasx,y*@param{number}lineWidthShouldbenonnegativeinteger.*@param{boolean=}positiveOrNegativeDefaultfalse(negative).*@return{number}Optimizedposition.*/function subPixelOptimize(position, lineWidth, positiveOrNegative) { //Assurethat(position+lineWidth/2)isnearintegeredge,// otherwise line will be fuzzy in canvas.vardoubledPosition=round(position*2);return(doubledPosition+round(lineWidth))%2===0?doubledPosition/2:(doubledPosition+(positiveOrNegative?1:-1))/2;}functionhasFillOrStroke(fillOrStroke){returnfillOrStroke!=null&&fillOrStroke!=='none';}// Most lifted color are duplicated.varliftedColorMap=createHashMap();varliftedColorCount=0;functionliftColor(color){if(typeofcolor!=='string'){returncolor;}varliftedColor=liftedColorMap.get(color);if(!liftedColor){liftedColor=lift(color,-0.1);if(liftedColorCount<10000){liftedColorMap.set(color,liftedColor);liftedColorCount++;}}returnliftedColor;}functioncacheElementStl(el){if(!el.__hoverStlDirty){return;}el.__hoverStlDirty=false;varhoverStyle=el.__hoverStl;if(!hoverStyle){el.__normalStl=null;return;}varnormalStyle=el.__normalStl={};varelStyle=el.style;for(varnameinhoverStyle){// See comment in `doSingleEnterHover`.if(hoverStyle[name]!=null){normalStyle[name]=elStyle[name];}}// Always cache fill and stroke to normalStyle for lifting color.normalStyle.fill=elStyle.fill;normalStyle.stroke=elStyle.stroke;}functiondoSingleEnterHover(el){varhoverStl=el.__hoverStl;if(!hoverStl||el.__highlighted){return;}varuseHoverLayer=el.useHoverLayer;el.__highlighted=useHoverLayer?'layer':'plain';varzr=el.__zr;if(!zr&&useHoverLayer){return;}varelTarget=el;vartargetStyle=el.style;if(useHoverLayer){elTarget=zr.addHover(el);targetStyle=elTarget.style;}// Consider case: only `position: 'top'` is set on emphasis, then text// color should be returned to `autoColor`, rather than remain '#fff'.// So we should rollback then apply again after style merging.rollbackDefaultTextStyle(targetStyle);if(!useHoverLayer){cacheElementStl(elTarget);}// styles can be:// {// label: {// show: false,// position: 'outside',// fontSize: 18// },// emphasis: {// label: {// show: true// }// }// },// where properties of `emphasis` may not appear in `normal`. We previously use// module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`.// But consider rich text and setOption in merge mode, it is impossible to cover// all properties in merge. So we use merge mode when setting style here, where// only properties that is not `null/undefined` can be set. The disadventage:// null/undefined can not be used to remove style any more in `emphasis`.targetStyle.extendFrom(hoverStl);setDefaultHoverFillStroke(targetStyle,hoverStl,'fill');setDefaultHoverFillStroke(targetStyle,hoverStl,'stroke');applyDefaultTextStyle(targetStyle);if(!useHoverLayer){el.dirty(false);el.z2+=1;}}functionsetDefaultHoverFillStroke(targetStyle,hoverStyle,prop){if(!hasFillOrStroke(hoverStyle[prop])&&hasFillOrStroke(targetStyle[prop])){targetStyle[prop]=liftColor(targetStyle[prop]);}}functiondoSingleLeaveHover(el){if(el.__highlighted){doSingleRestoreHoverStyle(el);el.__highlighted=false;}}functiondoSingleRestoreHoverStyle(el){varhighlighted=el.__highlighted;if(highlighted==='layer'){el.__zr&&el.__zr.removeHover(el);}elseif(highlighted){varstyle=el.style;varnormalStl=el.__normalStl;if(normalStl){rollbackDefaultTextStyle(style);// Consider null/undefined value, should use// `setStyle` but not `extendFrom(stl, true)`.el.setStyle(normalStl);applyDefaultTextStyle(style);el.z2-=1;}}}functiontraverseCall(el,method){el.isGroup?el.traverse(function(child){!child.isGroup&&method(child);}):method(el);}/** * Set hover style of element. * * @param {module:zrender/Element}elShouldnotbe`zrender/container/Group`.*@param{Object|boolean}[hoverStl]Thespecifiedhoverstyle.*Ifsetas`false`,disablethehoverstyle.*Similarly,The`el.hoverStyle`canalsebeset*as`false`todisablethehoverstyle.*Otherwise,usethedefaulthoverstyleifnotprovided.*@param{Object}[opt]*@param{boolean}[opt.hoverSilentOnTouch=false]See`graphic.setAsHoverStyleTrigger`*/function setElementHoverStyle(el, hoverStl) { hoverStl = el.__hoverStl = hoverStl !== false && (hoverStl || {}); el.__hoverStlDirty = true; if (el.__highlighted) { doSingleLeaveHover(el); doSingleEnterHover(el); }}/***Emphasis(calledbyAPI)hashigherprioritythan`mouseover`.*Whenelementhasbeencalledtobeenteredemphasis,mouseover*shouldnottriggerthehighlighteffect(forexample,animation*scale)again,and`mouseout`shouldnotdownplaythehighlight*effect.Sothelistenerof`mouseover`and`mouseout`should*check`isInEmphasis`.**@param{module:zrender/Element}el*@return{boolean}*/function isInEmphasis(el) { return el && el.__isEmphasisEntered;}function onElementMouseOver(e) { if (this.__hoverSilentOnTouch && e.zrByTouch) { return; } //Onlyifelementisnotinemphasisstatus!this.__isEmphasisEntered&&traverseCall(this,doSingleEnterHover);}functiononElementMouseOut(e){if(this.__hoverSilentOnTouch&&e.zrByTouch){return;}// Only if element is not in emphasis status!this.__isEmphasisEntered&&traverseCall(this,doSingleLeaveHover);}functionenterEmphasis(){this.__isEmphasisEntered=true;traverseCall(this,doSingleEnterHover);}functionleaveEmphasis(){this.__isEmphasisEntered=false;traverseCall(this,doSingleLeaveHover);}/** * Set hover style of element. * * [Caveat]: * This method can be called repeatly and achieve the same result. * * [Usage]: * Call the method for a "root" element once. Do not call it for each descendants. * If the descendants elemenets of a group has itself hover style different from the * root group, we can simply mount the style on `el.hoverStyle` for them, but should * not call this method for them. * * @param {module:zrender/Element}el*@param{Object|boolean}[hoverStyle]See`graphic.setElementHoverStyle`.*@param{Object}[opt]*@param{boolean}[opt.hoverSilentOnTouch=false]See`graphic.setAsHoverStyleTrigger`.*/function setHoverStyle(el, hoverStyle, opt) { el.isGroup? el.traverse(function (child) { //IfelementhassepcifiedhoverStyle,thenuseitinsteadofgivenhoverStyle// Often used when item group has a label element and it's hoverStyle is different!child.isGroup&&setElementHoverStyle(child,child.hoverStyle||hoverStyle);}):setElementHoverStyle(el,el.hoverStyle||hoverStyle);setAsHoverStyleTrigger(el,opt);}/** * @param {Object|boolean} [opt] If `false`, means disable trigger. * @param {boolean} [opt.hoverSilentOnTouch=false] * In touch device, mouseover event will be trigger on touchstart event * (see module:zrender/dom/HandlerProxy).Bythismechanism,wecan*convenientlyusehoverStylewhentapontouchscreenwithoutadditional*codeforcompatibility.*Butifthechart/componenthasselectfeature,whichusuallyalsouse*hoverStyle,theremightbeconflictbetween'select-highlight'and*'hover-highlight'especiallywhenroamisenabled(seegeoforexample).*Inthiscase,hoverSilentOnTouchshouldbeusedtodisablehover-highlight*ontouchdevice.*/function setAsHoverStyleTrigger(el, opt) { var disable = opt === false; el.__hoverSilentOnTouch = opt != null && opt.hoverSilentOnTouch; //Simpleoptimize,sincethismethodmightbe// called for each elements of a group in some cases.if(!disable||el.__hoverStyleTrigger){varmethod=disable?'off':'on';// Duplicated function will be auto-ignored, see Eventful.js.el[method]('mouseover',onElementMouseOver)[method]('mouseout',onElementMouseOut);// Emphasis, normal can be triggered manuallyel[method]('emphasis',enterEmphasis)[method]('normal',leaveEmphasis);el.__hoverStyleTrigger=!disable;}}/** * @param {Object|module:zrender/graphic/Style}normalStyle*@param{Object}emphasisStyle*@param{module:echarts/model/Model}normalModel*@param{module:echarts/model/Model}emphasisModel*@param{Object}optCheck`opt`of`setTextStyleCommon`tofindotherprops.*@param{string|Function}[opt.defaultText]*@param{module:echarts/model/Model}[opt.labelFetcher]Fetchtextby*`opt.labelFetcher.getFormattedLabel(opt.labelDataIndex,'normal'/'emphasis',null,opt.labelDimIndex)`*@param{module:echarts/model/Model}[opt.labelDataIndex]Fetchtextby*`opt.textFetcher.getFormattedLabel(opt.labelDataIndex,'normal'/'emphasis',null,opt.labelDimIndex)`*@param{module:echarts/model/Model}[opt.labelDimIndex]Fetchtextby*`opt.textFetcher.getFormattedLabel(opt.labelDataIndex,'normal'/'emphasis',null,opt.labelDimIndex)`*@param{Object}[normalSpecified]*@param{Object}[emphasisSpecified]*/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; //Thisscenario,`label.normal.show=true;label.emphasis.show=false`,// is not supported util someone requests.varshowNormal=normalModel.getShallow('show');varshowEmphasis=emphasisModel.getShallow('show');// Consider performance, only fetch label when necessary.// If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set,// label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.varbaseText;if(showNormal||showEmphasis){if(labelFetcher){baseText=labelFetcher.getFormattedLabel(labelDataIndex,'normal',null,labelDimIndex);}if(baseText==null){baseText=isFunction$1(opt.defaultText)?opt.defaultText(labelDataIndex,opt):opt.defaultText;}}varnormalStyleText=showNormal?baseText:null;varemphasisStyleText=showEmphasis?retrieve2(labelFetcher?labelFetcher.getFormattedLabel(labelDataIndex,'emphasis',null,labelDimIndex):null,baseText):null;// Optimize: If style.text is null, text will not be drawn.if(normalStyleText!=null||emphasisStyleText!=null){// Always set `textStyle` even if `normalStyle.text` is null, because default// values have to be set on `normalStyle`.// If we set default values on `emphasisStyle`, consider case:// Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);`// Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);`// Then the 'red' will not work on emphasis.setTextStyle(normalStyle,normalModel,normalSpecified,opt);setTextStyle(emphasisStyle,emphasisModel,emphasisSpecified,opt,true);}normalStyle.text=normalStyleText;emphasisStyle.text=emphasisStyleText;}/** * Set basic textStyle properties. * @param {Object|module:zrender/graphic/Style}textStyle*@param{module:echarts/model/Model}model*@param{Object}[specifiedTextStyle]Canbeoverridedbysettingsinmodel.*@param{Object}[opt]See`opt`of`setTextStyleCommon`.*@param{boolean}[isEmphasis]*/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);returntextStyle;}/** * Set text option in the style. * @deprecated * @param {Object} textStyle * @param {module:echarts/model/Model}labelModel*@param{string|boolean}defaultColorDefaulttextcolor.*Ifsetasfalse,itwillbeprocessedasaemphasisstyle.*/function setText(textStyle, labelModel, defaultColor) { var opt = {isRectText: true}; var isEmphasis; if (defaultColor === false) { isEmphasis = true; } else { //Supportsettingcoloras'auto'togetvisualcolor.opt.autoColor=defaultColor;}setTextStyleCommon(textStyle,labelModel,opt,isEmphasis);// textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);}/** * { * disableBox: boolean, Whether diable drawing box of block (outer most). * isRectText: boolean, * autoColor: string, specify a color when color is 'auto', * for textFill, textStroke, textBackgroundColor, and textBorderColor. * If autoColor specified, it is used as default textFill. * useInsideStyle: * `true`: Use inside style (textFill, textStroke, textStrokeWidth) * if `textFill` is not specified. * `false`: Do not use inside style. * `null/undefined`:useinsidestyleif`isRectText`istrueand*`textFill`isnotspecifiedandtextPositioncontains`'inside'`.*forceRich:boolean*}*/function setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis) { //Considertherewillbeabnormalwhenmergehoverstyletonormalstyleifgivendefaultvalue.opt=opt||EMPTY_OBJ;if(opt.isRectText){vartextPosition=textStyleModel.getShallow('position')||(isEmphasis?null:'inside');// 'outside' is not a valid zr textPostion value, but used// in bar series, and magric type should be considered.textPosition==='outside'&&(textPosition='top');textStyle.textPosition=textPosition;textStyle.textOffset=textStyleModel.getShallow('offset');varlabelRotate=textStyleModel.getShallow('rotate');labelRotate!=null&&(labelRotate*=Math.PI/180);textStyle.textRotation=labelRotate;textStyle.textDistance=retrieve2(textStyleModel.getShallow('distance'),isEmphasis?null:5);}varecModel=textStyleModel.ecModel;varglobalTextStyle=ecModel&&ecModel.option.textStyle;// Consider case:// {// data: [{// value: 12,// label: {// rich: {// // no 'a' here but using parent 'a'.// }// }// }],// rich: {// a: { ... }// }// }varrichItemNames=getRichItemNames(textStyleModel);varrichResult;if(richItemNames){richResult={};for(varnameinrichItemNames){if(richItemNames.hasOwnProperty(name)){// Cascade is supported in rich.varrichTextStyle=textStyleModel.getModel(['rich',name]);// In rich, never `disableBox`.setTokenTextStyle(richResult[name]={},richTextStyle,globalTextStyle,opt,isEmphasis);}}}textStyle.rich=richResult;setTokenTextStyle(textStyle,textStyleModel,globalTextStyle,opt,isEmphasis,true);if(opt.forceRich&&!opt.textStyle){opt.textStyle={};}returntextStyle;}// Consider case:// {// data: [{// value: 12,// label: {// rich: {// // no 'a' here but using parent 'a'.// }// }// }],// rich: {// a: { ... }// }// }functiongetRichItemNames(textStyleModel){// Use object to remove duplicated names.varrichItemNameMap;while(textStyleModel&&textStyleModel!==textStyleModel.ecModel){varrich=(textStyleModel.option||EMPTY_OBJ).rich;if(rich){richItemNameMap=richItemNameMap||{};for(varnameinrich){if(rich.hasOwnProperty(name)){richItemNameMap[name]=1;}}}textStyleModel=textStyleModel.parentModel;}returnrichItemNameMap;}functionsetTokenTextStyle(textStyle,textStyleModel,globalTextStyle,opt,isEmphasis,isBlock){// In merge mode, default value should not be given.globalTextStyle=!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);// Save original textPosition, because style.textPosition will be repalced by// real location (like [10, 30]) in zrender.textStyle.insideRawTextPosition=textStyle.textPosition;if(!isEmphasis){if(isBlock){textStyle.insideRollbackOpt=opt;applyDefaultTextStyle(textStyle);}// Set default finally.if(textStyle.textFill==null){textStyle.textFill=opt.autoColor;}}// Do not use `getFont` here, because merge should be supported, where// part of these properties may be changed in emphasis style, and the// others should remain their original value got from normal style.textStyle.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;}functiongetAutoColor(color,opt){returncolor!=='auto'?color:(opt&&opt.autoColor)?opt.autoColor:null;}// When text position is `inside` and `textFill` not specified, we// provide a mechanism to auto make text border for better view. But// text position changing when hovering or being emphasis should be// considered, where the `insideRollback` enables to restore the style.functionapplyDefaultTextStyle(textStyle){varopt=textStyle.insideRollbackOpt;// Only insideRollbackOpt create (setTextStyleCommon used),// applyDefaultTextStyle works.if(!opt||textStyle.textFill!=null){return;}varuseInsideStyle=opt.useInsideStyle;vartextPosition=textStyle.insideRawTextPosition;varinsideRollback;varautoColor=opt.autoColor;if(useInsideStyle!==false&&(useInsideStyle===true||(opt.isRectText&&textPosition// textPosition can be [10, 30]&&typeoftextPosition==='string'&&textPosition.indexOf('inside')>=0))){insideRollback={textFill:null,textStroke:textStyle.textStroke,textStrokeWidth:textStyle.textStrokeWidth};textStyle.textFill='#fff';// Consider text with #fff overflow its container.if(textStyle.textStroke==null){textStyle.textStroke=autoColor;textStyle.textStrokeWidth==null&&(textStyle.textStrokeWidth=2);}}elseif(autoColor!=null){insideRollback={textFill:null};textStyle.textFill=autoColor;}// Always set `insideRollback`, for clearing previous.if(insideRollback){textStyle.insideRollback=insideRollback;}}functionrollbackDefaultTextStyle(style){varinsideRollback=style.insideRollback;if(insideRollback){style.textFill=insideRollback.textFill;style.textStroke=insideRollback.textStroke;style.textStrokeWidth=insideRollback.textStrokeWidth;style.insideRollback=null;}}functiongetFont(opt,ecModel){// ecModel or default text style model.vargTextStyleModel=ecModel||ecModel.getModel('textStyle');returntrim([// FIXME in node-canvas fontWeight is before fontStyleopt.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(' '));}functionanimateOrSetProps(isUpdate,el,props,animatableModel,dataIndex,cb){if(typeofdataIndex==='function'){cb=dataIndex;dataIndex=null;}// Do not check 'animation' property directly here. Consider this case:// animation model is an `itemModel`, whose does not have `isAnimationEnabled`// but its parent model (`seriesModel`) does.varanimationEnabled=animatableModel&&animatableModel.isAnimationEnabled();if(animationEnabled){varpostfix=isUpdate?'Update':'';varduration=animatableModel.getShallow('animationDuration'+postfix);varanimationEasing=animatableModel.getShallow('animationEasing'+postfix);varanimationDelay=animatableModel.getShallow('animationDelay'+postfix);if(typeofanimationDelay==='function'){animationDelay=animationDelay(dataIndex,animatableModel.getAnimationDelayParams?animatableModel.getAnimationDelayParams(el,dataIndex):null);}if(typeofduration==='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();}}/** * Update graphic element properties with or without animation according to the * configuration in series. * * Caution: this method will stop previous animation. * So if do not use this method to one element twice before * animation starts, unless you know what you are doing. * * @param {module:zrender/Element}el*@param{Object}props*@param{module:echarts/model/Model}[animatableModel]*@param{number}[dataIndex]*@param{Function}[cb]*@example*graphic.updateProps(el,{*position:[100,100]*},seriesModel,dataIndex,function(){console.log('Animation done!');});*// Or*graphic.updateProps(el,{*position:[100,100]*},seriesModel,function(){console.log('Animation done!');});*/function updateProps(el, props, animatableModel, dataIndex, cb) { animateOrSetProps(true, el, props, animatableModel, dataIndex, cb);}/***Initgraphicelementpropertieswithorwithoutanimationaccordingtothe*configurationinseries.**Caution:thismethodwillstoppreviousanimation.*Soifdonotusethismethodtooneelementtwicebefore*animationstarts,unlessyouknowwhatyouaredoing.**@param{module:zrender/Element}el*@param{Object}props*@param{module:echarts/model/Model}[animatableModel]*@param{number}[dataIndex]*@param{Function}cb*/function initProps(el, props, animatableModel, dataIndex, cb) { animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);}/***Gettransformmatrixoftarget(paramtarget),*incoordinateofitsancestor(paramancestor)**@param{module:zrender/mixin/Transformable}target*@param{module:zrender/mixin/Transformable}[ancestor]*/function getTransform(target, ancestor) { var mat = identity([]); while (target && target !== ancestor) { mul$1(mat, target.getLocalTransform(), mat); target = target.parent; } return mat;}/***Applytransformtoanvertex.*@param{Array.<number>}target[x,y]*@param{Array.<number>|TypedArray.<number>|Object}transformCanbe:*+Transformmatrix:like[1,0,0,1,0,0]*+{position,rotation,scale},thesameas`zrender/Transformable`.*@param{boolean=}invertWhetheruseinvertmatrix.*@return{Array.<number>}[x,y]*/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);}/***@param{string}direction'left''right''top''bottom'*@param{Array.<number>}transformTransformmatrix:like[1,0,0,1,0,0]*@param{boolean=}invertWhetheruseinvertmatrix.*@return{string}Transformeddirection.'left''right''top''bottom'*/function transformDirection(direction, transform, invert$$1) { //Pickabase,ensurethattransformresultwillnotbe(0,0).varhBase=(transform[4]===0||transform[5]===0||transform[0]===0)?1:Math.abs(2*transform[4]/transform[0]);varvBase=(transform[4]===0||transform[5]===0||transform[2]===0)?1:Math.abs(2*transform[4]/transform[2]);varvertex=[direction==='left'?-hBase:direction==='right'?hBase:0,direction==='top'?-vBase:direction==='bottom'?vBase:0];vertex=applyTransform$1(vertex,transform,invert$$1);returnMath.abs(vertex[0])>Math.abs(vertex[1])?(vertex[0]>0?'right':'left'):(vertex[1]>0?'bottom':'top');}/** * Apply group transition animation from g1 to g2. * If no animatableModel, no animation. */functiongroupTransition(g1,g2,animatableModel,cb){if(!g1||!g2){return;}functiongetElMap(g){varelMap={};g.traverse(function(el){if(!el.isGroup&&el.anid){elMap[el.anid]=el;}});returnelMap;}functiongetAnimatableProps(el){varobj={position:clone$1(el.position),rotation:el.rotation};if(el.shape){obj.shape=extend({},el.shape);}returnobj;}varelMap1=getElMap(g1);g2.traverse(function(el){if(!el.isGroup&&el.anid){varoldEl=elMap1[el.anid];if(oldEl){varnewProp=getAnimatableProps(el);el.attr(getAnimatableProps(oldEl));updateProps(el,newProp,animatableModel,el.dataIndex);}// else {// if (el.previousProps) {// graphic.updateProps// }// }}});}/** * @param {Array.<Array.<number>>} points Like: [[23, 44], [53, 66], ...] * @param {Object} rect {x, y, width, height} * @return {Array.<Array.<number>>} A new clipped points. */functionclipPointsByRect(points,rect){// FIXME: this way migth be incorrect when grpahic clipped by a corner.// and when element have border.returnmap(points,function(point){varx=point[0];x=mathMax$1(x,rect.x);x=mathMin$1(x,rect.x+rect.width);vary=point[1];y=mathMax$1(y,rect.y);y=mathMin$1(y,rect.y+rect.height);return[x,y];});}/** * @param {Object} targetRect {x, y, width, height} * @param {Object} rect {x, y, width, height} * @return {Object} A new clipped rect. If rect size are negative, return undefined. */functionclipRectByRect(targetRect,rect){varx=mathMax$1(targetRect.x,rect.x);varx2=mathMin$1(targetRect.x+targetRect.width,rect.x+rect.width);vary=mathMax$1(targetRect.y,rect.y);vary2=mathMin$1(targetRect.y+targetRect.height,rect.y+rect.height);// If the total rect is cliped, nothing, including the border,// should be painted. So return undefined.if(x2>=x&&y2>=y){return{x:x,y:y,width:x2-x,height:y2-y};}}/** * @param {string} iconStr Support 'image://' or 'path://' or direct svg path.*@param{Object}[opt]Propertiesof`module:zrender/Element`,except`style`.*@param{Object}[rect]{x,y,width,height}*@return{module:zrender/Element}Iconpathorimageelement.*/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),newZImage(opt)):(makePath(iconStr.replace('path://',''),opt,rect,'center'));}}vargraphic=(Object.freeze||Object)({extendShape:extendShape,extendPath:extendPath,makePath:makePath,makeImage:makeImage,mergePath:mergePath,resizePath:resizePath,subPixelOptimizeLine:subPixelOptimizeLine,subPixelOptimizeRect:subPixelOptimizeRect,subPixelOptimize:subPixelOptimize,setElementHoverStyle:setElementHoverStyle,isInEmphasis:isInEmphasis,setHoverStyle:setHoverStyle,setAsHoverStyleTrigger:setAsHoverStyleTrigger,setLabelStyle:setLabelStyle,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,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});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var PATH_COLOR = ['textStyle', 'color'];var textStyleMixin = { /***Getcolorpropertyorgetcolorfromoption.textStyle.color*@param{boolean}[isEmphasis]*@return{string}*/ getTextColor: function (isEmphasis) { var ecModel = this.ecModel; return this.getShallow('color') || ((!isEmphasis && ecModel)? ecModel.get(PATH_COLOR) : null); }, /***CreatefontstringfromfontStyle,fontWeight,fontSize,fontFamily*@return{string}*/ getFont: function () { return getFont({ fontStyle: this.getShallow('fontStyle'), fontWeight: this.getShallow('fontWeight'), fontSize: this.getShallow('fontSize'), fontFamily: this.getShallow('fontFamily') }, this.ecModel); }, getTextRect: function (text) { return getBoundingRect( text, this.getFont(), this.getShallow('align'), this.getShallow('verticalAlign') || this.getShallow('baseline'), this.getShallow('padding'), this.getShallow('rich'), this.getShallow('truncateText')); }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var getItemStyle = makeStyleMapper([ ['fill', 'color'],['stroke', 'borderColor'],['lineWidth', 'borderWidth'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor'],['textPosition'],['textAlign'] ]);var itemStyleMixin = { getItemStyle: function (excludes, includes) { var style = getItemStyle(this, excludes, includes); var lineDash = this.getBorderLineDash(); lineDash && (style.lineDash = lineDash); return style; }, getBorderLineDash: function () { var lineType = this.get('borderType'); return (lineType === 'solid' || lineType == null)? null : (lineType === 'dashed' ?[5, 5] : [1, 1]); }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@moduleecharts/model/Model*/var mixin$1 = mixin;var inner = makeInner();/***@aliasmodule:echarts/model/Model*@constructor*@param{Object}option*@param{module:echarts/model/Model}[parentModel]*@param{module:echarts/model/Global}[ecModel]*/function Model(option, parentModel, ecModel) { /***@type{module:echarts/model/Model}*@readOnly*/ this.parentModel = parentModel; /***@type{module:echarts/model/Global}*@readOnly*/ this.ecModel = ecModel; /***@type{Object}*@protected*/ this.option = option; //Simpleoptimization// if (this.init) {// if (arguments.length <= 4) {// this.init(option, parentModel, ecModel, extraOpt);// }// else {// this.init.apply(this, arguments);// }// }}Model.prototype={constructor:Model,/** * Model 的初始化函数 * @param {Object} option */init:null,/** * 从新的 Option merge */mergeOption:function(option){merge(this.option,option,true);},/** * @param {string|Array.<string>} path * @param {boolean} [ignoreParent=false] * @return {*} */get:function(path,ignoreParent){if(path==null){returnthis.option;}returndoGet(this.option,this.parsePath(path),!ignoreParent&&getParent(this,path));},/** * @param {string} key * @param {boolean} [ignoreParent=false] * @return {*} */getShallow:function(key,ignoreParent){varoption=this.option;varval=option==null?option:option[key];varparentModel=!ignoreParent&&getParent(this,key);if(val==null&&parentModel){val=parentModel.getShallow(key);}returnval;},/** * @param {string|Array.<string>} [path] * @param {module:echarts/model/Model}[parentModel]*@return{module:echarts/model/Model}*/ getModel: function (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); }, /***Ifmodelhasoption*/ isEmpty: function () { return this.option == null; }, restoreData: function () {}, //Pendingclone:function(){varCtor=this.constructor;returnnewCtor(clone(this.option));},setReadOnly:function(properties){// clazzUtil.setReadOnly(this, properties);},// If path is null/undefined, return null/undefined.parsePath:function(path){if(typeofpath==='string'){path=path.split('.');}returnpath;},/** * @param {Function} getParentMethod * param {Array.<string>|string} path * return {module:echarts/model/Model}*/ customizeGetParent: function (getParentMethod) { inner(this).getParent = getParentMethod; }, isAnimationEnabled: function () { 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++) { //Ignoreemptyif(!pathArr[i]){continue;}// obj could be number/string/... (like 0)obj=(obj&&typeofobj==='object')?obj[pathArr[i]]:null;if(obj==null){break;}}if(obj==null&&parentModel){obj=parentModel.get(pathArr);}returnobj;}// `path` can be null/undefinedfunctiongetParent(model,path){vargetParentMethod=inner(model).getParent;returngetParentMethod?getParentMethod.call(model,path):model.parentModel;}// Enable Model.extend.enableClassExtend(Model);enableClassCheck(Model);mixin$1(Model,lineStyleMixin);mixin$1(Model,areaStyleMixin);mixin$1(Model,textStyleMixin);mixin$1(Model,itemStyleMixin);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var base = 0;/***@public*@param{string}type*@return{string}*/function getUID(type) { //Consideringthecaseofcrossingjscontext,// use Math.random to make id as unique as possible.return[(type||''),base++,Math.random().toFixed(5)].join('_');}/** * @inner */functionenableSubTypeDefaulter(entity){varsubTypeDefaulters={};entity.registerSubTypeDefaulter=function(componentType,defaulter){componentType=parseClassType$1(componentType);subTypeDefaulters[componentType.main]=defaulter;};entity.determineSubType=function(componentType,option){vartype=option.type;if(!type){varcomponentTypeMain=parseClassType$1(componentType).main;if(entity.hasSubTypes(componentType)&&subTypeDefaulters[componentTypeMain]){type=subTypeDefaulters[componentTypeMain](option);}}returntype;};returnentity;}/** * Topological travel on Activity Network (Activity On Vertices). * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. * * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. * * If there is circle dependencey, Error will be thrown. * */functionenableTopologicalTravel(entity,dependencyGetter){/** * @public * @param {Array.<string>} targetNameList Target Component type list. * Can be ['aa', 'bb', 'aa.xx'] * @param {Array.<string>} fullNameList By which we can build dependency graph. * @param {Function} callback Params: componentType, dependencies. * @param {Object} context Scope of callback. */entity.topologicalTravel=function(targetNameList,fullNameList,callback,context){if(!targetNameList.length){return;}varresult=makeDepndencyGraph(fullNameList);vargraph=result.graph;varstack=result.noEntryList;vartargetNameSet={};each$1(targetNameList,function(name){targetNameSet[name]=true;});while(stack.length){varcurrComponentType=stack.pop();varcurrVertex=graph[currComponentType];varisInTargetNameSet=!!targetNameSet[currComponentType];if(isInTargetNameSet){callback.call(context,currComponentType,currVertex.originalDeps.slice());deletetargetNameSet[currComponentType];}each$1(currVertex.successor,isInTargetNameSet?removeEdgeAndAdd:removeEdge);}each$1(targetNameSet,function(){thrownewError('Circle dependency may exists');});functionremoveEdge(succComponentType){graph[succComponentType].entryCount--;if(graph[succComponentType].entryCount===0){stack.push(succComponentType);}}// Consider this case: legend depends on series, and we call// chart.setOption({series: [...]}), where only series is in option.// If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will// not be called, but only sereis.mergeOption is called. Thus legend// have no chance to update its local record about series (like which// name of series is available in legend).functionremoveEdgeAndAdd(succComponentType){targetNameSet[succComponentType]=true;removeEdge(succComponentType);}};/** * DepndencyGraph: {Object} * key: conponentType, * value: { * successor: [conponentTypes...], * originalDeps: [conponentTypes...], * entryCount: {number} * } */functionmakeDepndencyGraph(fullNameList){vargraph={};varnoEntryList=[];each$1(fullNameList,function(name){varthisItem=createDependencyGraphItem(graph,name);varoriginalDeps=thisItem.originalDeps=dependencyGetter(name);varavailableDeps=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);}varthatItem=createDependencyGraphItem(graph,dependentName);if(indexOf(thatItem.successor,dependentName)<0){thatItem.successor.push(name);}});});return{graph:graph,noEntryList:noEntryList};}functioncreateDependencyGraphItem(graph,name){if(!graph[name]){graph[name]={predecessor:[],successor:[]};}returngraph[name];}functiongetAvailableDependencies(originalDeps,fullNameList){varavailableDeps=[];each$1(originalDeps,function(dep){indexOf(fullNameList,dep)>=0&&availableDeps.push(dep);});returnavailableDeps;}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var RADIAN_EPSILON = 1e-4;function _trim(str) { return str.replace(/^\s+/, '').replace(/\s+$/,'');}/** * Linear mapping a value from domain to range * @memberOf module:echarts/util/number*@param{(number|Array.<number>)}val*@param{Array.<number>}domainDomainextentdomain[0]canbebiggerthandomain[1]*@param{Array.<number>}rangeRangeextentrange[0]canbebiggerthanrange[1]*@param{boolean}clamp*@return{(number|Array.<number>}*/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// 146.39 - 62.83 === 83.55999999999999.// See echarts/test/ut/spec/util/number.js#linearMap#accuracyError// It is a little verbose for efficiency considering this method// is a hotspot.if(clamp){if(subDomain>0){if(val<=domain[0]){returnrange[0];}elseif(val>=domain[1]){returnrange[1];}}else{if(val>=domain[0]){returnrange[0];}elseif(val<=domain[1]){returnrange[1];}}}else{if(val===domain[0]){returnrange[0];}if(val===domain[1]){returnrange[1];}}return(val-domain[0])/subDomain*subRange+range[0];}/** * Convert a percent string to absolute number. * Returns NaN if percent is not a valid string or number * @memberOf module:echarts/util/number*@param{string|number}percent*@param{number}all*@return{number}*/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(/%$/)){returnparseFloat(percent)/100*all;}returnparseFloat(percent);}returnpercent==null?NaN:+percent;}/** * (1) Fix rounding error of float numbers. * (2) Support return string to avoid scientific notation like '3.5e-7'. * * @param {number} x * @param {number} [precision] * @param {boolean} [returnStr] * @return {number|string} */functionround$1(x,precision,returnStr){if(precision==null){precision=10;}// Avoid range errorprecision=Math.min(Math.max(0,precision),20);x=(+x).toFixed(precision);returnreturnStr?x:+x;}/** * Get precision * @param {number} val *//***@param{string|number}val*@return{number}*/function getPrecisionSafe(val) { var str = val.toString(); //Considerscientificnotation:'3.4e-12''3.4e+12'vareIndex=str.indexOf('e');if(eIndex>0){varprecision=+str.slice(eIndex+1);returnprecision<0?-precision:0;}else{vardotIndex=str.indexOf('.');returndotIndex<0?0:str.length-1-dotIndex;}}/** * Minimal dicernible data precisioin according to a single pixel. * * @param {Array.<number>} dataExtent * @param {Array.<number>} pixelExtent * @return {number} precision */functiongetPixelPrecision(dataExtent,pixelExtent){varlog=Math.log;varLN10=Math.LN10;vardataQuantity=Math.floor(log(dataExtent[1]-dataExtent[0])/LN10);varsizeQuantity=Math.round(log(Math.abs(pixelExtent[1]-pixelExtent[0]))/LN10);// toFixed() digits argument must be between 0 and 20.varprecision=Math.min(Math.max(-dataQuantity+sizeQuantity,0),20);return!isFinite(precision)?20:precision;}/** * Get a data of given precision, assuring the sum of percentages * in valueList is 1. * The largest remainer method is used. * https://en.wikipedia.org/wiki/Largest_remainder_method**@param{Array.<number>}valueListalistofalldata*@param{number}idxindexofthedatatobeprocessedinvalueList*@param{number}precisionintegernumbershowingdigitsofprecision*@return{number}percentrangingfrom0to100*/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;});vartargetSeats=digits*100;varseats=map(votesPerQuota,function(votes){// Assign automatic seats.returnMath.floor(votes);});varcurrentSum=reduce(seats,function(acc,val){returnacc+val;},0);varremainder=map(votesPerQuota,function(votes,idx){returnvotes-seats[idx];});// Has remainding votes.while(currentSum<targetSeats){// Find next largest remainder.varmax=Number.NEGATIVE_INFINITY;varmaxId=null;for(vari=0,len=remainder.length;i<len;++i){if(remainder[i]>max){max=remainder[i];maxId=i;}}// Add a vote to max remainder.++seats[maxId];remainder[maxId]=0;++currentSum;}returnseats[idx]/digits;}// Number.MAX_SAFE_INTEGER, ie do not support./** * To 0 - 2 * PI, considering negative radian. * @param {number} radian * @return {number} */functionremRadian(radian){varpi2=Math.PI*2;return(radian%pi2+pi2)%pi2;}/** * @param {type} radian * @return {boolean} */functionisRadianAroundZero(val){returnval>-RADIAN_EPSILON&&val<RADIAN_EPSILON;}/* eslint-disable */varTIME_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/* eslint-enable *//** * @param {string|Date|number} value These values can be accepted: * + An instance of Date, represent a time in its own time zone. * + Or string in a subset of ISO 8601, only including: * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', * all of which will be treated as local time if time zone is not specified * (see <https://momentjs.com/>).*+Orotherstringformat,including(allofwhichwillbetreatedasloacaltime):*'2012','2012-3-1','2012/3/1','2012/03/01',*'2009/6/12 2:00','2009/6/12 2:05:08','2009/6/12 2:05:08.123'*+atimestamp,whichrepresentatimeinUTC.*@return{Date}date*/function parseDate(value) { if (value instanceof Date) { return value; } else if (typeof value === 'string') { //Differentbrowsersparsedateindifferentway,soweparseitmanually.// Some other issues:// new Date('1970-01-01') is UTC,// new Date('1970/01/01') and new Date('1970-1-01') is local.// See issue #3623varmatch=TIME_REG.exec(value);if(!match){// return Invalid Date.returnnewDate(NaN);}// Use local time when no timezone offset specifed.if(!match[8]){// match[n] can only be string or undefined.// But take care of '12' + 1 => '121'.returnnewDate(+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,// https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment).// For example, system timezone is set as "Time Zone: America/Toronto",// then these code will get different result:// `new Date(1478411999999).getTimezoneOffset(); // get 240`// `new Date(1478412000000).getTimezoneOffset(); // get 300`// So we should not use `new Date`, but use `Date.UTC`.else{varhour=+match[4]||0;if(match[8].toUpperCase()!=='Z'){hour-=match[8].slice(0,3);}returnnewDate(Date.UTC(+match[1],+(match[2]||1)-1,+match[3]||1,hour,+(match[5]||0),+match[6]||0,+match[7]||0));}}elseif(value==null){returnnewDate(NaN);}returnnewDate(Math.round(value));}/** * Quantity of a number. e.g. 0.1, 1, 10, 100 * * @param {number} val * @return {number} */functionquantity(val){returnMath.pow(10,quantityExponent(val));}functionquantityExponent(val){returnMath.floor(Math.log(val)/Math.LN10);}/** * find a “nice” number approximately equal to x. Round the number if round = true, * take ceiling if round = false. The primary observation is that the “nicest” * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. * * See "Nice Numbers for Graph Labels" of Graphic Gems. * * @param {number} val Non-negative value. * @param {boolean} round * @return {number} */functionnice(val,round){varexponent=quantityExponent(val);varexp10=Math.pow(10,exponent);varf=val/exp10;// 1 <= f < 10varnf;if(round){if(f<1.5){nf=1;}elseif(f<2.5){nf=2;}elseif(f<4){nf=3;}elseif(f<7){nf=5;}else{nf=10;}}else{if(f<1){nf=1;}elseif(f<2){nf=2;}elseif(f<3){nf=3;}elseif(f<5){nf=5;}else{nf=10;}}val=nf*exp10;// Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).// 20 is the uppper bound of toFixed.returnexponent>=-20?+val.toFixed(exponent<0?-exponent:0):val;}/** * BSD 3-Clause * * Copyright (c) 2010-2015, Michael Bostock * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/orothermaterialsprovidedwiththedistribution.***ThenameMichaelBostockmaynotbeusedtoendorseorpromoteproducts*derivedfromthissoftwarewithoutspecificpriorwrittenpermission.**THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS"AS IS"*ANDANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSEARE*DISCLAIMED.INNOEVENTSHALLMICHAELBOSTOCKBELIABLEFORANYDIRECT,*INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,*BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,*DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANYTHEORY*OFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT(INCLUDING*NEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSEOFTHISSOFTWARE,*EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.*//***@see<https://github.com/mbostock/d3/blob/master/src/arrays/quantile.js>*@see<http://en.wikipedia.org/wiki/Quantile>*@param{Array.<number>}ascArr*//***Orderintervalsasc,andsplitthemwhenoverlap.*expect(numberUtil.reformIntervals([*{interval:[18,62],close:[1,1]},*{interval:[-Infinity,-70],close:[0,0]},*{interval:[-70,-26],close:[1,1]},*{interval:[-26,18],close:[1,1]},*{interval:[62,150],close:[1,1]},*{interval:[106,150],close:[1,1]},*{interval:[150,Infinity],close:[0,0]}*])).toEqual([*{interval:[-Infinity,-70],close:[0,0]},*{interval:[-70,-26],close:[1,1]},*{interval:[-26,18],close:[0,1]},*{interval:[18,62],close:[0,1]},*{interval:[62,150],close:[0,1]},*{interval:[150,Infinity],close:[0,0]}*]);*@param{Array.<Object>}list,where`close`meanopenorclose*oftheinterval,andInfinitycanbeused.*@return{Array.<Object>}Theoriginlist,whichhasbeenreformed.*//***parseFloatNaNsnumeric-castfalsepositives(null|true|false|"")*...butmisinterpretsleading-numberstrings,particularlyhexliterals("0x...")*subtractionforcesinfinitiestoNaN**@param{*}v*@return{boolean}*//**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///importTextfrom'zrender/src/graphic/Text';/** * 每三位默认加,格式化 * @param {string|number} x * @return {string} */functionaddCommas(x){if(isNaN(x)){return'-';}x=(x+'').split('.');returnx[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,'$1,')+(x.length>1?('.'+x[1]):'');}/** * @param {string} str * @param {boolean} [upperCaseFirst=false] * @return {string} str */varnormalizeCssArray$1=normalizeCssArray;varreplaceReg=/([&<>"'])/g;varreplaceMap={'&':'&','<':'<','>':'>','"':'"','\'':'''};functionencodeHTML(source){returnsource==null?'':(source+'').replace(replaceReg,function(str,c){returnreplaceMap[c];});}varTPL_VAR_ALIAS=['a','b','c','d','e','f','g'];varwrapVar=function(varName,seriesIdx){return'{'+varName+(seriesIdx==null?'':seriesIdx)+'}';};/** * Template formatter * @param {string} tpl * @param {Array.<Object>|Object} paramsList * @param {boolean} [encode=false] * @return {string} */functionformatTpl(tpl,paramsList,encode){if(!isArray(paramsList)){paramsList=[paramsList];}varseriesLen=paramsList.length;if(!seriesLen){return'';}var$vars=paramsList[0].$vars||[];for(vari=0;i<$vars.length;i++){varalias=TPL_VAR_ALIAS[i];tpl=tpl.replace(wrapVar(alias),wrapVar(alias,0));}for(varseriesIdx=0;seriesIdx<seriesLen;seriesIdx++){for(vark=0;k<$vars.length;k++){varval=paramsList[seriesIdx][$vars[k]];tpl=tpl.replace(wrapVar(TPL_VAR_ALIAS[k],seriesIdx),encode?encodeHTML(val):val);}}returntpl;}/** * simple Template formatter * * @param {string} tpl * @param {Object} param * @param {boolean} [encode=false] * @return {string} *//***@param{Object|string}[opt]Ifstring,meanscolor.*@param{string}[opt.color]*@param{string}[opt.extraCssText]*@param{string}[opt.type='item']'item'or'subItem'*@param{string}[opt.renderMode='html']rendermodeoftooltip,'html'or'richText'*@param{string}[opt.markerId='X']idnameformarker.Ifonlyonemarkerisinarichtext,thiscanbeomitted.*@return{string}*/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 markerreturn{renderMode:renderMode,content:'{marker'+markerId+'|} ',style:{color:color}};}}functionpad(str,len){str+='';return'0000'.substr(0,len-str.length)+str;}/** * ISO Date format * @param {string} tpl * @param {number} value * @param {boolean} [isUTC=false] Default in local time. * see `module:echarts/scale/Time`*and`module:echarts/util/number#parseDate`.*@inner*/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;}/***Capitalfirst*@param{string}str*@return{string}*/var truncateText$1 = truncateText;/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Layouthelpersforeachcomponentpositioningvareach$3=each$1;/** * @public */varLOCATION_PARAMS=['left','right','top','bottom','width','height'];/** * @public */varHV_NAMES=[['width','left','right'],['height','top','bottom']];functionboxLayout(orient,group,gap,maxWidth,maxHeight){varx=0;vary=0;if(maxWidth==null){maxWidth=Infinity;}if(maxHeight==null){maxHeight=Infinity;}varcurrentLineMaxSize=0;group.eachChild(function(child,idx){varposition=child.position;varrect=child.getBoundingRect();varnextChild=group.childAt(idx+1);varnextChildRect=nextChild&&nextChild.getBoundingRect();varnextX;varnextY;if(orient==='horizontal'){varmoveX=rect.width+(nextChildRect?(-nextChildRect.x+rect.x):0);nextX=x+moveX;// Wrap when width exceeds maxWidth or meet a `newline` group// FIXME compare before adding gap?if(nextX>maxWidth||child.newline){x=0;nextX=moveX;y+=currentLineMaxSize+gap;currentLineMaxSize=rect.height;}else{// FIXME: consider rect.y is not `0`?currentLineMaxSize=Math.max(currentLineMaxSize,rect.height);}}else{varmoveY=rect.height+(nextChildRect?(-nextChildRect.y+rect.y):0);nextY=y+moveY;// Wrap when width exceeds maxHeight or meet a `newline` groupif(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);});}/** * VBox or HBox layouting * @param {string} orient * @param {module:zrender/container/Group}group*@param{number}gap*@param{number}[width=Infinity]*@param{number}[height=Infinity]*//***VBoxlayouting*@param{module:zrender/container/Group}group*@param{number}gap*@param{number}[width=Infinity]*@param{number}[height=Infinity]*/var vbox = curry(boxLayout, 'vertical');/***HBoxlayouting*@param{module:zrender/container/Group}group*@param{number}gap*@param{number}[width=Infinity]*@param{number}[height=Infinity]*/var hbox = curry(boxLayout, 'horizontal');/***Ifxorx2isnotspecifiedor'center''left''right',*thewidthwouldbeaslongaspossible.*Ifyory2isnotspecifiedor'middle''top''bottom',*theheightwouldbeaslongaspossible.**@param{Object}positionInfo*@param{number|string}[positionInfo.x]*@param{number|string}[positionInfo.y]*@param{number|string}[positionInfo.x2]*@param{number|string}[positionInfo.y2]*@param{Object}containerRect{width,height}*@param{string|number}margin*@return{Object}{width,height}*//***Parsepositioninfo.**@param{Object}positionInfo*@param{number|string}[positionInfo.left]*@param{number|string}[positionInfo.top]*@param{number|string}[positionInfo.right]*@param{number|string}[positionInfo.bottom]*@param{number|string}[positionInfo.width]*@param{number|string}[positionInfo.height]*@param{number|string}[positionInfo.aspect]Aspectiswidth/height*@param{Object}containerRect*@param{string|number}[margin]**@return{module:zrender/core/BoundingRect}*/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; //Ifwidthisnotspecified,calculatewidthfromleftandrightif(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// 1. Graph should not exceeds the container// 2. Aspect must be keeped// 3. Graph should take the space as more as possible// FIXME// Margin is not considered, because there is no case that both// using margin and aspect so far.if(isNaN(width)&&isNaN(height)){if(aspect>containerWidth/containerHeight){width=containerWidth*0.8;}else{height=containerHeight*0.8;}}// Calculate width or height with given aspectif(isNaN(width)){width=aspect*height;}if(isNaN(height)){height=width/aspect;}}// If left is not specified, calculate left from right and widthif(isNaN(left)){left=containerWidth-right-width-horizontalMargin;}if(isNaN(top)){top=containerHeight-bottom-height-verticalMargin;}// Align left and topswitch(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 NaNleft=left||0;top=top||0;if(isNaN(width)){// Width may be NaN if only one value is given except widthwidth=containerWidth-horizontalMargin-left-(right||0);}if(isNaN(height)){// Height may be NaN if only one value is given except heightheight=containerHeight-verticalMargin-top-(bottom||0);}varrect=newBoundingRect(left+margin[3],top+margin[0],width,height);rect.margin=margin;returnrect;}/** * Position a zr element in viewport * Group position is specified by either * {left, top}, {right, bottom} * If all properties exists, right and bottom will be igonred. * * Logic: * 1. Scale (against origin point in parent coord) * 2. Rotate (against origin point in parent coord) * 3. Traslate (with el.position by this method) * So this method only fixes the last step 'Traslate', which does not affect * scaling and rotating. * * If be called repeatly with the same input el, the same result will be gotten. * * @param {module:zrender/Element}elShouldhave`getBoundingRect`method.*@param{Object}positionInfo*@param{number|string}[positionInfo.left]*@param{number|string}[positionInfo.top]*@param{number|string}[positionInfo.right]*@param{number|string}[positionInfo.bottom]*@param{number|string}[positionInfo.width]Onlyforopt.boundingModel:'raw'*@param{number|string}[positionInfo.height]Onlyforopt.boundingModel:'raw'*@param{Object}containerRect*@param{string|number}margin*@param{Object}[opt]*@param{Array.<number>}[opt.hv=[1,1]]Onlyhorizontaloronlyvertical.*@param{Array.<number>}[opt.boundingMode='all']*SpecifyhowtocalculateboundingRectwhenlocating.*'all':PositiontheboundingRectthatistransformedanduioned*bothitselfanditsdescendants.*Thismodesimpliesconfinetheelementsinthebounding*oftheircontainer(e.g.,using'right: 0').*'raw':PositiontheboundingRectthatisnottransformedandonlyitself.*Thismodeisusefulwhenyouwantaelementcanoverflowits*container.(Considerarotatedcircleneedstobelocatedinacorner.)*InthismodepositionInfo.width/heightcanonlybenumber.*//***@param{Object}optionContainssomeofthepropertiesinHV_NAMES.*@param{number}hvIdx0:horizontal;1:vertical.*//***ConsiderCase:*Whendefulatoptionhas{left:0,width:100},andweset{right:0}*throughsetOptionormediaquery,usingnormalzrUtil.mergewillcause*{right:0}doesnottakeeffect.**@example*ComponentModel.extend({*init:function(){*...*varinputPositionParams=layout.getLayoutParams(option);*this.mergeOption(inputPositionParams);*},*mergeOption:function(newOption){*newOption&&zrUtil.merge(thisOption,newOption,true);*layout.mergeLayoutParam(thisOption,newOption);*}*});**@param{Object}targetOption*@param{Object}newOption*@param{Object|string}[opt]*@param{boolean|Array.<boolean>}[opt.ignoreSize=false]Usedforthecomponents*thatwidth(orheight)shouldnotbecalculatedbyleftandright(ortopandbottom).*/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) { //Considercase:newOption.widthisnull,whichis// set by user for removing width setting.hasProp(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.if(hasValue(newOption,names[1])){merged[names[2]]=null;}elseif(hasValue(newOption,names[2])){merged[names[1]]=null;}returnmerged;}// Case: newOption: {width: ..., right: ...},// or targetOption: {right: ...} and newOption: {width: ...},// There is no conflict when merged only has params count// little than enoughParamNumber.if(mergedValueCount===enoughParamNumber||!newValueCount){returnmerged;}// Case: newOption: {width: ..., right: ...},// Than we can make sure user only want those two, and ignore// all origin params in targetOption.elseif(newValueCount>=enoughParamNumber){returnnewParams;}else{// Chose another param from targetOption by priority.for(vari=0;i<names.length;i++){varname=names[i];if(!hasProp(newParams,name)&&hasProp(targetOption,name)){newParams[name]=targetOption[name];break;}}returnnewParams;}}functionhasProp(obj,name){returnobj.hasOwnProperty(name);}functionhasValue(obj,name){returnobj[name]!=null&&obj[name]!=='auto';}functioncopy(names,target,source){each$3(names,function(name){target[name]=source[name];});}}/** * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. * @param {Object} source * @return {Object} Result contains those props. */functiongetLayoutParams(source){returncopyLayoutParams({},source);}/** * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. * @param {Object} source * @return {Object} Result contains those props. */functioncopyLayoutParams(target,source){source&&target&&each$3(LOCATION_PARAMS,function(name){source.hasOwnProperty(name)&&(target[name]=source[name]);});returntarget;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var boxLayoutMixin = { getBoxLayoutParams: function () { 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') }; }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Componentmodel**@moduleecharts/model/Component*/var inner$1 = makeInner();/***@aliasmodule:echarts/model/Component*@constructor*@param{Object}option*@param{module:echarts/model/Model}parentModel*@param{module:echarts/model/Model}ecModel*/var ComponentModel = Model.extend({ type: 'component', /***@readOnly*@type{string}*/ id: '', /***Becausesimplifiedconceptisprobablybetter,series.name(orcomponent.name)*hasbeenhavingtoomanyresposibilities:*(1)Generatingid(whichrequiresnameinoptionshouldnotbemodified).*(2)AsanindextomappingserieswhenmergingoptionorcallingAPI(aname*canrefertomorethenonecomponents,whichisconvinientissomecase).*(3)Display.*@readOnly*/ name: '', /***@readOnly*@type{string}*/ mainType: '', /***@readOnly*@type{string}*/ subType: '', /***@readOnly*@type{number}*/ componentIndex: 0, /***@type{Object}*@protected*/ defaultOption: null, /***@type{module:echarts/model/Global}*@readOnly*/ ecModel: null, /***key:componentType*value:Componentmodellist,cannotbenull.*@type{Object.<string,Array.<module:echarts/model/Model>>}*@readOnly*/ dependentModels: [], /***@type{string}*@readOnly*/ uid: null, /***Supportmergelayoutparams.*Onlysupport'box'now(left/right/top/bottom/width/height).*@type{string|Object}Objectcanbe{ignoreSize:true}*@readOnly*/ layoutMode: null, $constructor: function (option, parentModel, ecModel, extraOpt) { Model.call(this, option, parentModel, ecModel, extraOpt); this.uid = getUID('ec_cpt_model'); }, init: function (option, parentModel, ecModel, extraOpt) { this.mergeDefaultAndTheme(option, ecModel); }, mergeDefaultAndTheme: function (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 (option, extraOpt) { merge(this.option, option, true); var layoutMode = this.layoutMode; if (layoutMode) { mergeLayoutParam(this.option, option, layoutMode); } }, //HookerafterinitormergeOptionoptionUpdated:function(newCptOption,isInit){},getDefaultOption:function(){varfields=inner$1(this);if(!fields.defaultOption){varoptList=[];varClass=this.constructor;while(Class){varopt=Class.prototype.defaultOption;opt&&optList.push(opt);Class=Class.superClass;}vardefaultOption={};for(vari=optList.length-1;i>=0;i--){defaultOption=merge(defaultOption,optList[i],true);}fields.defaultOption=defaultOption;}returnfields.defaultOption;},getReferringComponents:function(mainType){returnthis.ecModel.queryComponents({mainType:mainType,index:this.get(mainType+'Index',true),id:this.get(mainType+'Id',true)});}});// Reset ComponentModel.extend, add preConstruct.// clazzUtil.enableClassExtend(// ComponentModel,// function (option, parentModel, ecModel, extraOpt) {// // Set dependentModels, componentIndex, name, id, mainType, subType.// zrUtil.extend(this, extraOpt);// this.uid = componentUtil.getUID('componentModel');// // this.setReadOnly([// // 'type', 'id', 'uid', 'name', 'mainType', 'subType',// // 'dependentModels', 'componentIndex'// // ]);// }// );// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.enableClassManagement(ComponentModel,{registerWhenExtend:true});enableSubTypeDefaulter(ComponentModel);// Add capability of ComponentModel.topologicalTravel.enableTopologicalTravel(ComponentModel,getDependencies);functiongetDependencies(componentType){vardeps=[];each$1(ComponentModel.getClassesByMainType(componentType),function(Clazz){deps=deps.concat(Clazz.prototype.dependencies||[]);});// Ensure main type.deps=map(deps,function(type){returnparseClassType$1(type).main;});// Hack dataset for convenience.if(componentType!=='dataset'&&indexOf(deps,'dataset')<=0){deps.unshift('dataset');}returndeps;}mixin(ComponentModel,boxLayoutMixin);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var platform = '';//Navigatornotexistsinnodeif(typeofnavigator!=='undefined'){platform=navigator.platform||'';}varglobalDefault={// backgroundColor: 'rgba(0,0,0,0)',// https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization// color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],// Light colors:// color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],// color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],// Dark colors:color:['#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.// grid: {},textStyle:{// color: '#000',// decoration: 'none',// PENDINGfontFamily:platform.match(/^Win/)?'Microsoft YaHei':'sans-serif',// fontFamily: 'Arial, Verdana, sans-serif',fontSize:12,fontStyle:'normal',fontWeight:'normal'},// http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation// Default is source-overblendMode:null,animation:'auto',animationDuration:1000,animationDurationUpdate:300,animationEasing:'exponentialOut',animationEasingUpdate:'cubicOut',animationThreshold:2000,// Configuration for progressive/incremental renderingprogressiveThreshold:3000,progressive:400,// Threshold of if use single hover layer to optimize.// It is recommended that `hoverLayerThreshold` is equivalent to or less than// `progressiveThreshold`, otherwise hover will cause restart of progressive,// which is unexpected.// see example <echarts/test/heatmap-large.html>.hoverLayerThreshold:3000,// See: module:echarts/scale/TimeuseUTC:false};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var inner$2 = makeInner();function getNearestColorPalette(colors, requestColorNum) { var paletteNum = colors.length; //TODOcolorsmustbeinorderfor(vari=0;i<paletteNum;i++){if(colors[i].length>requestColorNum){returncolors[i];}}returncolors[paletteNum-1];}varcolorPaletteMixin={clearColorPalette:function(){inner$2(this).colorIdx=0;inner$2(this).colorNameMap={};},/** * @param {string} name MUST NOT be null/undefined.Otherwisecallthisfunction*twisewiththesameparameterswillgetdifferentresult.*@param{Object}[scope=this]*@param{Object}[requestColorNum]*@return{string}colorstring.*/ getColorFromPalette: function (name, scope, requestColorNum) { scope = scope || this; var scopeFields = inner$2(scope); var colorIdx = scopeFields.colorIdx || 0; var colorNameMap = scopeFields.colorNameMap = scopeFields.colorNameMap || {}; //Use`hasOwnProperty`toavoidconflictwithObject.prototype.if(colorNameMap.hasOwnProperty(name)){returncolorNameMap[name];}vardefaultColorPalette=normalizeToArray(this.get('color',true));varlayeredColorPalette=this.get('colorLayer',true);varcolorPalette=((requestColorNum==null||!layeredColorPalette)?defaultColorPalette:getNearestColorPalette(layeredColorPalette,requestColorNum));// In case can't find in layered color palette.colorPalette=colorPalette||defaultColorPalette;if(!colorPalette||!colorPalette.length){return;}varcolor=colorPalette[colorIdx];if(name){colorNameMap[name]=color;}scopeFields.colorIdx=(colorIdx+1)%colorPalette.length;returncolor;}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Helperformodelreferences.*Therearemanymannerstoreferaxis/coordSys.*///TODO// merge relevant logic to this file?// check: "modelHelper" of tooltip and "BrushTargetManager"./***@return{Object}Forexample:*{*coordSysName:'cartesian2d',*coordSysDims:['x','y',...],*axisMap:HashMap({*x:xAxisModel,*y:yAxisModel*}),*categoryAxisMap:HashMap({*x:xAxisModel,*y:undefined*}),*// It also indicate that whether there is category axis.*firstCategoryDimIndex:1,*// To replace user specified encode.*}*/function getCoordSysDefineBySeries(seriesModel) { var coordSysName = seriesModel.get('coordinateSystem'); var result = { coordSysName: coordSysName, coordSysDims: [], axisMap: createHashMap(), categoryAxisMap: createHashMap() }; var fetch = fetchers[coordSysName]; if (fetch) { fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); return result; }}var fetchers = { cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) { var xAxisModel = seriesModel.getReferringComponents('xAxis')[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 = 1; } }, singleAxis: function (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 (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 = 1; } }, geo: function (seriesModel, result, axisMap, categoryAxisMap) { result.coordSysDims = ['lng', 'lat']; }, parallel: function (seriesModel, result, axisMap, categoryAxisMap) { var ecModel = seriesModel.ecModel; var parallelModel = ecModel.getComponent( 'parallel', seriesModel.get('parallelIndex')); var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); each$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';}/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Avoidtypo.varSOURCE_FORMAT_ORIGINAL='original';varSOURCE_FORMAT_ARRAY_ROWS='arrayRows';varSOURCE_FORMAT_OBJECT_ROWS='objectRows';varSOURCE_FORMAT_KEYED_COLUMNS='keyedColumns';varSOURCE_FORMAT_UNKNOWN='unknown';// ??? CHANGE A NAMEvarSOURCE_FORMAT_TYPED_ARRAY='typedArray';varSERIES_LAYOUT_BY_COLUMN='column';varSERIES_LAYOUT_BY_ROW='row';/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***[sourceFormat]**+"original":*Thisformatisonlyusedinseries.data,where*itemStylecanbespecifiedindataitem.**+"arrayRows":*[*['product','score','amount'],*['Matcha Latte',89.3,95.8],*['Milk Tea',92.1,89.4],*['Cheese Cocoa',94.4,91.2],*['Walnut Brownie',85.4,76.9]*]**+"objectRows":*[*{product:'Matcha Latte',score:89.3,amount:95.8},*{product:'Milk Tea',score:92.1,amount:89.4},*{product:'Cheese Cocoa',score:94.4,amount:91.2},*{product:'Walnut Brownie',score:85.4,amount:76.9}*]**+"keyedColumns":*{*'product':['Matcha Latte','Milk Tea','Cheese Cocoa','Walnut Brownie'],*'count':[823,235,1042,988],*'score':[95.8,81.4,91.2,76.9]*}**+"typedArray"**+"unknown"*//***@constructor*@param{Object}fields*@param{string}fields.sourceFormat*@param{Array|Object}fields.fromDataset*@param{Array|Object}[fields.data]*@param{string}[seriesLayoutBy='column']*@param{Array.<Object|string>}[dimensionsDefine]*@param{Objet|HashMap}[encodeDefine]*@param{number}[startIndex=0]*@param{number}[dimensionsDetectCount]*/function Source(fields) { /***@type{boolean}*/ this.fromDataset = fields.fromDataset; /***Notnull/undefined.*@type{Array|Object}*/ this.data = fields.data || ( fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []); /***Seealso"detectSourceFormat".*Notnull/undefined.*@type{string}*/ this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; /***'row'or'column'*Notnull/undefined.*@type{string}seriesLayoutBy*/ this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN; /***dimensionsdefinitioninoption.*canbenull/undefined.*@type{Array.<Object|string>}*/ this.dimensionsDefine = fields.dimensionsDefine; /***encodedefinitioninoption.*canbenull/undefined.*@type{Objet|HashMap}*/ this.encodeDefine = fields.encodeDefine && createHashMap(fields.encodeDefine); /***Notnull/undefined,uint.*@type{number}*/ this.startIndex = fields.startIndex || 0; /***Canbenull/undefined(whenunknown),uint.*@type{number}*/ this.dimensionsDetectCount = fields.dimensionsDetectCount;}/***Wraporiginalseriesdataforsomecompatibilitycases.*/Source.seriesDataToSource = function (data) { return new Source({ data: data, sourceFormat: isTypedArray(data)? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL, fromDataset: false });};enableClassCheck(Source);/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var inner$3 = makeInner();/***@see{module:echarts/data/Source}*@param{module:echarts/component/dataset/DatasetModel}datasetModel*@return{string}sourceFormat*/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)) { //FIXMEWhethertoleratenullintoplevelarray?if(data.length===0){sourceFormat=SOURCE_FORMAT_ARRAY_ROWS;}for(vari=0,len=data.length;i<len;i++){varitem=data[i];if(item==null){continue;}elseif(isArray(item)){sourceFormat=SOURCE_FORMAT_ARRAY_ROWS;break;}elseif(isObject$1(item)){sourceFormat=SOURCE_FORMAT_OBJECT_ROWS;break;}}}elseif(isObject$1(data)){for(varkeyindata){if(data.hasOwnProperty(key)&&isArrayLike(data[key])){sourceFormat=SOURCE_FORMAT_KEYED_COLUMNS;break;}}}elseif(data!=null){thrownewError('Invalid data');}inner$3(datasetModel).sourceFormat=sourceFormat;}/** * [Scenarios]: * (1) Provide source data directly: * series: { * encode: {...}, * dimensions: [...] * seriesLayoutBy: 'row', * data: [[...]] * } * (2) Refer to datasetModel. * series: [{ * encode: {...} * // Ignore datasetIndex means `datasetIndex: 0` * // and the dimensions defination in dataset is used * }, { * encode: {...}, * seriesLayoutBy: 'column', * datasetIndex: 1 * }] * * Get data from series itself or datset. * @return {module:echarts/data/Source}source*/function getSource(seriesModel) { return inner$3(seriesModel).source;}/***MUSTbecalledbeforemergeOptionofallseries.*@param{module:echarts/model/Global}ecModel*/function resetSourceDefaulter(ecModel) { //`datasetMap`isusedtomakedefaultencode.inner$3(ecModel).datasetMap=createHashMap();}/** * [Caution]: * MUST be called after series option merged and * before "series.getInitailData()" called. * * [The rule of making default encode]: * Category axis (if exists) alway map to the first dimension. * Each other axis occupies a subsequent dimension. * * [Why make default encode]: * Simplify the typing of encode in option, avoiding the case like that: * series: [{encode: {x: 0, y: 1}}, {encode: {x: 0, y: 2}}, {encode: {x: 0, y: 3}}], * where the "y" have to be manually typed as "1, 2, 3, ...". * * @param {module:echarts/model/Series}seriesModel*/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; //Thesesettingsfromserieshashigherpriority.seriesLayoutBy=seriesLayoutBy||datasetOption.seriesLayoutBy;sourceHeader==null&&(sourceHeader=datasetOption.sourceHeader);dimensionsDefine=dimensionsDefine||datasetOption.dimensions;}varcompleteResult=completeBySourceData(data,sourceFormat,seriesLayoutBy,sourceHeader,dimensionsDefine);// Note: dataset option does not have `encode`.varencodeDefine=seriesOption.encode;if(!encodeDefine&&datasetModel){encodeDefine=makeDefaultEncode(seriesModel,datasetModel,data,sourceFormat,seriesLayoutBy,completeResult);}inner$3(seriesModel).source=newSource({data:data,fromDataset:fromDataset,seriesLayoutBy:seriesLayoutBy,sourceFormat:sourceFormat,dimensionsDefine:completeResult.dimensionsDefine,startIndex:completeResult.startIndex,dimensionsDetectCount:completeResult.dimensionsDetectCount,encodeDefine:encodeDefine});}// return {startIndex, dimensionsDefine, dimensionsCount}functioncompleteBySourceData(data,sourceFormat,seriesLayoutBy,sourceHeader,dimensionsDefine){if(!data){return{dimensionsDefine:normalizeDimensionsDefine(dimensionsDefine)};}vardimensionsDetectCount;varstartIndex;varfindPotentialName;if(sourceFormat===SOURCE_FORMAT_ARRAY_ROWS){// Rule: Most of the first line are string: it is header.// Caution: consider a line with 5 string and 1 number,// it still can not be sure it is a head, because the// 5 string may be 5 values of category columns.if(sourceHeader==='auto'||sourceHeader==null){arrayRowsTravelFirst(function(val){// '-' is regarded as null/undefined.if(val!=null&&val!=='-'){if(isString(val)){startIndex==null&&(startIndex=1);}else{startIndex=0;}}// 10 is an experience number, avoid long loop.},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;}elseif(sourceFormat===SOURCE_FORMAT_OBJECT_ROWS){if(!dimensionsDefine){dimensionsDefine=objectRowsCollectDimensions(data);findPotentialName=true;}}elseif(sourceFormat===SOURCE_FORMAT_KEYED_COLUMNS){if(!dimensionsDefine){dimensionsDefine=[];findPotentialName=true;each$1(data,function(colArr,key){dimensionsDefine.push(key);});}}elseif(sourceFormat===SOURCE_FORMAT_ORIGINAL){varvalue0=getDataItemValue(data[0]);dimensionsDetectCount=isArray(value0)&&value0.length||1;}elseif(sourceFormat===SOURCE_FORMAT_TYPED_ARRAY){if(__DEV__){assert$1(!!dimensionsDefine,'dimensions must be given if data is TypedArray.');}}varpotentialNameDimIndex;if(findPotentialName){each$1(dimensionsDefine,function(dim,idx){if((isObject$1(dim)?dim.name:dim)==='name'){potentialNameDimIndex=idx;}});}return{startIndex:startIndex,dimensionsDefine:normalizeDimensionsDefine(dimensionsDefine),dimensionsDetectCount:dimensionsDetectCount,potentialNameDimIndex:potentialNameDimIndex// TODO: potentialIdDimIdx};}// Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'],// which is reasonable. But dimension name is duplicated.// Returns undefined or an array contains only object without null/undefiend or string.functionnormalizeDimensionsDefine(dimensionsDefine){if(!dimensionsDefine){// The meaning of null/undefined is different from empty array.return;}varnameMap=createHashMap();returnmap(dimensionsDefine,function(item,index){item=extend({},isObject$1(item)?item:{name:item});// User can set null in dimensions.// We dont auto specify name, othewise a given name may// cause it be refered unexpectedly.if(item.name==null){returnitem;}// Also consider number form like 2012.item.name+='';// User may also specify displayName.// displayName will always exists except user not// specified or dim name is not specified or detected.// (A auto generated dim name will not be used as// displayName).if(item.displayName==null){item.displayName=item.name;}varexist=nameMap.get(item.name);if(!exist){nameMap.set(item.name,{count:1});}else{item.name+='-'+exist.count++;}returnitem;});}functionarrayRowsTravelFirst(cb,seriesLayoutBy,data,maxLoop){maxLoop==null&&(maxLoop=Infinity);if(seriesLayoutBy===SERIES_LAYOUT_BY_ROW){for(vari=0;i<data.length&&i<maxLoop;i++){cb(data[i]?data[i][0]:null,i);}}else{varvalue0=data[0]||[];for(vari=0;i<value0.length&&i<maxLoop;i++){cb(value0[i],i);}}}functionobjectRowsCollectDimensions(data){varfirstIndex=0;varobj;while(firstIndex<data.length&&!(obj=data[firstIndex++])){}// jshint ignore: lineif(obj){vardimensions=[];each$1(obj,function(value,key){dimensions.push(key);});returndimensions;}}// ??? TODO merge to completedimensions, where also has// default encode making logic. And the default rule// should depends on series? consider 'map'.functionmakeDefaultEncode(seriesModel,datasetModel,data,sourceFormat,seriesLayoutBy,completeResult){varcoordSysDefine=getCoordSysDefineBySeries(seriesModel);varencode={};// var encodeTooltip = [];// var encodeLabel = [];varencodeItemName=[];varencodeSeriesName=[];varseriesType=seriesModel.subType;// ??? TODO refactor: provide by series itself.// Consider the case: 'map' series is based on geo coordSys,// 'graph', 'heatmap' can be based on cartesian. But can not// give default rule simply here.varnSeriesMap=createHashMap(['pie','map','funnel']);varcSeriesMap=createHashMap(['line','bar','pictorialBar','scatter','effectScatter','candlestick','boxplot']);// Usually in this case series will use the first data// dimension as the "value" dimension, or other default// processes respectively.if(coordSysDefine&&cSeriesMap.get(seriesType)!=null){varecModel=seriesModel.ecModel;vardatasetMap=inner$3(ecModel).datasetMap;varkey=datasetModel.uid+'_'+seriesLayoutBy;vardatasetRecord=datasetMap.get(key)||datasetMap.set(key,{categoryWayDim:1,valueWayDim:0});// TODO// Auto detect first time axis and do arrangement.each$1(coordSysDefine.coordSysDims,function(coordDim){// In value way.if(coordSysDefine.firstCategoryDimIndex==null){vardataDim=datasetRecord.valueWayDim++;encode[coordDim]=dataDim;// ??? TODO give a better default series name rule?// especially when encode x y specified.// consider: when mutiple series share one dimension// category axis, series name should better use// the other dimsion name. On the other hand, use// both dimensions name.encodeSeriesName.push(dataDim);// encodeTooltip.push(dataDim);// encodeLabel.push(dataDim);}// In category way, category axis.elseif(coordSysDefine.categoryAxisMap.get(coordDim)){encode[coordDim]=0;encodeItemName.push(0);}// In category way, non-category axis.else{vardataDim=datasetRecord.categoryWayDim++;encode[coordDim]=dataDim;// encodeTooltip.push(dataDim);// encodeLabel.push(dataDim);encodeSeriesName.push(dataDim);}});}// Do not make a complex rule! Hard to code maintain and not necessary.// ??? TODO refactor: provide by series itself.// [{name: ..., value: ...}, ...] like:elseif(nSeriesMap.get(seriesType)!=null){// Find the first not ordinal. (5 is an experience value)varfirstNotOrdinal;for(vari=0;i<5&&firstNotOrdinal==null;i++){if(!doGuessOrdinal(data,sourceFormat,seriesLayoutBy,completeResult.dimensionsDefine,completeResult.startIndex,i)){firstNotOrdinal=i;}}if(firstNotOrdinal!=null){encode.value=firstNotOrdinal;varnameDimIndex=completeResult.potentialNameDimIndex||Math.max(firstNotOrdinal-1,0);// By default, label use itemName in charts.// So we dont set encodeLabel here.encodeSeriesName.push(nameDimIndex);encodeItemName.push(nameDimIndex);// encodeTooltip.push(firstNotOrdinal);}}// encodeTooltip.length && (encode.tooltip = encodeTooltip);// encodeLabel.length && (encode.label = encodeLabel);encodeItemName.length&&(encode.itemName=encodeItemName);encodeSeriesName.length&&(encode.seriesName=encodeSeriesName);returnencode;}/** * If return null/undefined,indicatethatshouldnotusedatasetModel.*/function getDatasetModel(seriesModel) { var option = seriesModel.option; //Caution:considerthescenario:// A dataset is declared and a series is not expected to use the dataset,// and at the beginning `setOption({series: { noData })` (just prepare other// option but no data), then `setOption({series: {data: [...]}); In this case,// the user should set an empty array to avoid that dataset is used by default.varthisData=option.data;if(!thisData){returnseriesModel.ecModel.getComponent('dataset',option.datasetIndex||0);}}/** * The rule should not be complex, otherwise user might not * be able to known where the data is wrong. * The code is ugly, but how to make it neat? * * @param {module:echars/data/Source}source*@param{number}dimIndex*@return{boolean}Whetherordinal.*/function guessOrdinal(source, dimIndex) { return doGuessOrdinal( source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex);}//dimIndexmaybeoverflowsourcedata.functiondoGuessOrdinal(data,sourceFormat,seriesLayoutBy,dimensionsDefine,startIndex,dimIndex){varresult;// Experience value.varmaxLoop=5;if(isTypedArray(data)){returnfalse;}// When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine// always exists in source.vardimName;if(dimensionsDefine){dimName=dimensionsDefine[dimIndex];dimName=isObject$1(dimName)?dimName.name:dimName;}if(sourceFormat===SOURCE_FORMAT_ARRAY_ROWS){if(seriesLayoutBy===SERIES_LAYOUT_BY_ROW){varsample=data[dimIndex];for(vari=0;i<(sample||[]).length&&i<maxLoop;i++){if((result=detectValue(sample[startIndex+i]))!=null){returnresult;}}}else{for(vari=0;i<data.length&&i<maxLoop;i++){varrow=data[startIndex+i];if(row&&(result=detectValue(row[dimIndex]))!=null){returnresult;}}}}elseif(sourceFormat===SOURCE_FORMAT_OBJECT_ROWS){if(!dimName){return;}for(vari=0;i<data.length&&i<maxLoop;i++){varitem=data[i];if(item&&(result=detectValue(item[dimName]))!=null){returnresult;}}}elseif(sourceFormat===SOURCE_FORMAT_KEYED_COLUMNS){if(!dimName){return;}varsample=data[dimName];if(!sample||isTypedArray(sample)){returnfalse;}for(vari=0;i<sample.length&&i<maxLoop;i++){if((result=detectValue(sample[i]))!=null){returnresult;}}}elseif(sourceFormat===SOURCE_FORMAT_ORIGINAL){for(vari=0;i<data.length&&i<maxLoop;i++){varitem=data[i];varval=getDataItemValue(item);if(!isArray(val)){returnfalse;}if((result=detectValue(val[dimIndex]))!=null){returnresult;}}}functiondetectValue(val){// Consider usage convenience, '1', '2' will be treated as "number".// `isFinit('')` get `true`.if(val!=null&&isFinite(val)&&val!==''){returnfalse;}elseif(isString(val)&&val!=='-'){returntrue;}}returnfalse;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***EChartsglobalmodel**@module{echarts/model/Global}*//***Caution:Ifthemechanismshouldbechangedsomeday,thesecases*shouldbeconsidered:**(1)In`mergeoption`mode,ifusingthesameoptiontocall`setOption`*manytimes,theresultshouldbethesame(tryourbesttoensurethat).*(2)In`mergeoption`mode,ifacomponenthasnoid/namespecified,it*willbemergedbyindex,andtheresultsequenceofthecomponentsis*consistenttotheoriginalsequence.*(3)`reset`feature(intoolbox).Finddetailedinfoincommentsabout*`mergeOption`inmodule:echarts/model/OptionManager.*/var OPTION_INNER_KEY = '\0_ec_inner';/***@aliasmodule:echarts/model/Global**@param{Object}option*@param{module:echarts/model/Model}parentModel*@param{Object}theme*/var GlobalModel = Model.extend({ init: function (option, parentModel, theme, optionManager) { theme = theme || {}; this.option = null; //Markasnotinitialized./***@type{module:echarts/model/Model}*@private*/ this._theme = new Model(theme); /***@type{module:echarts/model/OptionManager}*/ this._optionManager = optionManager; }, setOption: function (option, optionPreprocessorFuncs) { assert$1( !(OPTION_INNER_KEY in option), 'please use chart.getOption()'); this._optionManager.setOption(option, optionPreprocessorFuncs); this.resetOption(null); }, /***@param{string}typenull/undefined:resetall.*'recreate':forcerecreateall.*'timeline':onlyresettimelineoption*'media':onlyresetmediaqueryoption*@return{boolean}Whetheroptionchanged.*/ resetOption: function (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; }, /***@protected*/ mergeOption: function (newOption) { var option = this.option; var componentsMap = this._componentsMap; var newCptTypes = []; resetSourceDefaulter(this); //Ifnocomponentclass,mergedirectly.// For example: color, animaiton options, etc.each$1(newOption,function(componentOption,mainType){if(componentOption==null){return;}if(!ComponentModel.hasClass(mainType)){// globalSettingTask.dirty();option[mainType]=option[mainType]==null?clone(componentOption):merge(option[mainType],componentOption,true);}elseif(mainType){newCptTypes.push(mainType);}});ComponentModel.topologicalTravel(newCptTypes,ComponentModel.getAllClassMainTypes(),visitComponent,this);functionvisitComponent(mainType,dependencies){varnewCptOptionList=normalizeToArray(newOption[mainType]);varmapResult=mappingToExists(componentsMap.get(mainType),newCptOptionList);makeIdAndName(mapResult);// Set mainType and complete subType.each$1(mapResult,function(item,index){varopt=item.option;if(isObject$1(opt)){item.keyInfo.mainType=mainType;item.keyInfo.subType=determineSubType(mainType,opt,item.exist);}});vardependentModels=getComponentsByTypes(componentsMap,dependencies);option[mainType]=[];componentsMap.set(mainType,[]);each$1(mapResult,function(resultItem,index){varcomponentModel=resultItem.exist;varnewCptOption=resultItem.option;assert$1(isObject$1(newCptOption)||componentModel,'Empty component definition');// Consider where is no new option and should be merged using {},// see removeEdgeAndAdd in topologicalTravel and// ComponentModel.getAllClassMainTypes.if(!newCptOption){componentModel.mergeOption({},this);componentModel.optionUpdated({},false);}else{varComponentModelClass=ComponentModel.getClass(mainType,resultItem.keyInfo.subType,true);if(componentModel&&componentModelinstanceofComponentModelClass){componentModel.name=resultItem.keyInfo.name;// componentModel.settingTask && componentModel.settingTask.dirty();componentModel.mergeOption(newCptOption,this);componentModel.optionUpdated(newCptOption,false);}else{// PENDING Global as parent ?varextraOpt=extend({dependentModels:dependentModels,componentIndex:index},resultItem.keyInfo);componentModel=newComponentModelClass(newCptOption,this,this,extraOpt);extend(componentModel,extraOpt);componentModel.init(newCptOption,this,this,extraOpt);// Call optionUpdated after init.// newCptOption has been used as componentModel.option// and may be merged with theme and default, so pass null// to avoid confusion.componentModel.optionUpdated(null,true);}}componentsMap.get(mainType)[index]=componentModel;option[mainType][index]=componentModel.option;},this);// Backup series for filtering.if(mainType==='series'){createSeriesIndices(this,componentsMap.get('series'));}}this._seriesIndicesMap=createHashMap(this._seriesIndices=this._seriesIndices||[]);},/** * Get option for output (cloned option and inner info removed) * @public * @return {Object} */getOption:function(){varoption=clone(this.option);each$1(option,function(opts,mainType){if(ComponentModel.hasClass(mainType)){varopts=normalizeToArray(opts);for(vari=opts.length-1;i>=0;i--){// Remove options with inner id.if(isIdInner(opts[i])){opts.splice(i,1);}}option[mainType]=opts;}});deleteoption[OPTION_INNER_KEY];returnoption;},/** * @return {module:echarts/model/Model}*/ getTheme: function () { return this._theme; }, /***@param{string}mainType*@param{number}[idx=0]*@return{module:echarts/model/Component}*/ getComponent: function (mainType, idx) { var list = this._componentsMap.get(mainType); if (list) { return list[idx || 0]; } }, /***Ifnoneofindexandidandnameused,returnallcomponentswithmainType.*@param{Object}condition*@param{string}condition.mainType*@param{string}[condition.subType]Ifignore,onlyquerybymainType*@param{number|Array.<number>}[condition.index]Eitherinputindexoridorname.*@param{string|Array.<string>}[condition.id]Eitherinputindexoridorname.*@param{string|Array.<string>}[condition.name]Eitherinputindexoridorname.*@return{Array.<module:echarts/model/Component>}*/ queryComponents: function (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 { //ReturnallcomponentswithmainTyperesult=cpts.slice();}returnfilterBySubType(result,condition);},/** * The interface is different from queryComponents, * which is convenient for inner usage. * * @usage * var result = findComponents( * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}} * ); * var result = findComponents( * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}} * ); * var result = findComponents( * {mainType: 'series'}, * function (model, index) {...} * ); * //resultlike[component0,componnet1,...]**@param{Object}condition*@param{string}condition.mainTypeMandatory.*@param{string}[condition.subType]Optional.*@param{Object}[condition.query]like{xxxIndex,xxxId,xxxName},*wherexxxismainType.*Ifqueryattributeisnull/undefinedorhasnoindex/id/name,*donotfilteringbyqueryconditions,whichisconvenientfor*no-payloadsituationsorwhentargetofactionisglobal.*@param{Function}[condition.filter]parameter:component,returnboolean.*@return{Array.<module:echarts/model/Component>}*/ findComponents: function (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, //subTypewillbefilteredfinally.index:q[indexAttr],id:q[idAttr],name:q[nameAttr]}:null;}functiondoFilter(res){returncondition.filter?filter(res,condition.filter):res;}},/** * @usage * eachComponent('legend', function (legendModel, index) { * ... * }); * eachComponent(function (componentType, model, index) { * //componentTypedoesnotincludesubType*// (componentType is 'xxx' but not 'xxx.aa')*});*eachComponent(*{mainType:'dataZoom',query:{dataZoomId:'abc'}},*function(model,index){...}*);*eachComponent(*{mainType:'series',subType:'pie',query:{seriesName:'uio'}},*function(model,index){...}*);**@param{string|Object=}mainTypeWhenmainTypeisobject,thedefinition*isthesameasthemethod'findComponents'.*@param{Function}cb*@param{*}context*/ eachComponent: function (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); } }, /***@param{string}name*@return{Array.<module:echarts/model/Series>}*/ getSeriesByName: function (name) { var series = this._componentsMap.get('series'); return filter(series, function (oneSeries) { return oneSeries.name === name; }); }, /***@param{number}seriesIndex*@return{module:echarts/model/Series}*/ getSeriesByIndex: function (seriesIndex) { return this._componentsMap.get('series')[seriesIndex]; }, /***Getserieslistbeforefilteredbytype.*FIXME:renametogetRawSeriesByType?**@param{string}subType*@return{Array.<module:echarts/model/Series>}*/ getSeriesByType: function (subType) { var series = this._componentsMap.get('series'); return filter(series, function (oneSeries) { return oneSeries.subType === subType; }); }, /***@return{Array.<module:echarts/model/Series>}*/ getSeries: function () { return this._componentsMap.get('series').slice(); }, /***@return{number}*/ getSeriesCount: function () { return this._componentsMap.get('series').length; }, /***Afterfiltering,seriesmaybedifferent*fromerawseries.**@param{Function}cb*@param{*}context*/ eachSeries: function (cb, context) { assertSeriesInitialized(this); each$1(this._seriesIndices, function (rawSeriesIndex) { var series = this._componentsMap.get('series')[rawSeriesIndex]; cb.call(context, series, rawSeriesIndex); }, this); }, /***Iteraterawseriesbeforefiltered.**@param{Function}cb*@param{*}context*/ eachRawSeries: function (cb, context) { each$1(this._componentsMap.get('series'), cb, context); }, /***Afterfiltering,seriesmaybedifferent.*fromerawseries.**@parma{string}subType*@param{Function}cb*@param{*}context*/ eachSeriesByType: function (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); }, /***Iteraterawseriesbeforefilteredofgiventype.**@parma{string}subType*@param{Function}cb*@param{*}context*/ eachRawSeriesByType: function (subType, cb, context) { return each$1(this.getSeriesByType(subType), cb, context); }, /***@param{module:echarts/model/Series}seriesModel*/ isSeriesFiltered: function (seriesModel) { assertSeriesInitialized(this); return this._seriesIndicesMap.get(seriesModel.componentIndex) == null; }, /***@return{Array.<number>}*/ getCurrentSeriesIndices: function () { return (this._seriesIndices || []).slice(); }, /***@param{Function}cb*@param{*}context*/ filterSeries: function (cb, context) { assertSeriesInitialized(this); var filteredSeries = filter( this._componentsMap.get('series'), cb, context); createSeriesIndices(this, filteredSeries); }, restoreData: function (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); }}/***@inner*/function mergeTheme(option, theme) { //PENDING// NOT use `colorLayer` in theme if option has `color`varnotMergeColorLayer=option.color&&!option.colorLayer;each$1(theme,function(themeItem,name){if(name==='colorLayer'&¬MergeColorLayer){return;}// 如果有 component model 则把具体的 merge 逻辑交给该 model 处理if(!ComponentModel.hasClass(name)){if(typeofthemeItem==='object'){option[name]=!option[name]?clone(themeItem):merge(option[name],themeItem,false);}else{if(option[name]==null){option[name]=themeItem;}}}});}functioninitBase(baseOption){baseOption=baseOption;// Using OPTION_INNER_KEY to mark that this option can not be used outside,// i.e. `chart.setOption(chart.getModel().option);` is forbiden.this.option={};this.option[OPTION_INNER_KEY]=1;/** * Init with series: [], in case of calling findSeries method * before series initialized. * @type {Object.<string, Array.<module:echarts/model/Model>>}*@private*/ this._componentsMap = createHashMap({series: []}); /***Mappingbetweenfilteredserieslistandrawserieslist.*key:filteredseriesindices,value:rawseriesindices.*@type{Array.<nubmer>}*@private*/ this._seriesIndices; this._seriesIndicesMap; mergeTheme(baseOption, this._theme.option); //TODONeedsclonewhenmergingtotheunexistedpropertymerge(baseOption,globalDefault,false);this.mergeOption(baseOption);}/** * @inner * @param {Array.<string>|string} types model types * @return {Object} key: {string} type, value: {Array.<Object>} models */functiongetComponentsByTypes(componentsMap,types){if(!isArray(types)){types=types?[types]:[];}varret={};each$1(types,function(type){ret[type]=(componentsMap.get(type)||[]).slice();});returnret;}/** * @inner */functiondetermineSubType(mainType,newCptOption,existComponent){varsubType=newCptOption.type?newCptOption.type:existComponent?existComponent.subType// Use determineSubType only when there is no existComponent.:ComponentModel.determineSubType(mainType,newCptOption);// tooltip, markline, markpoint may always has no subTypereturnsubType;}/** * @inner */functioncreateSeriesIndices(ecModel,seriesModels){ecModel._seriesIndicesMap=createHashMap(ecModel._seriesIndices=map(seriesModels,function(series){returnseries.componentIndex;})||[]);}/** * @inner */functionfilterBySubType(components,condition){// Using hasOwnProperty for restrict. Consider// subType is undefined in user payload.returncondition.hasOwnProperty('subType')?filter(components,function(cpt){returncpt.subType===condition.subType;}):components;}/** * @inner */functionassertSeriesInitialized(ecModel){// Components that use _seriesIndices should depends on series component,// which make sure that their initialization is after series.if(__DEV__){if(!ecModel._seriesIndices){thrownewError('Option should contains series.');}}}mixin(GlobalModel,colorPaletteMixin);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var echartsAPIList = [ 'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption', 'getViewOfComponentModel', 'getViewOfSeriesModel'];//And`getCoordinateSystems`and`getComponentByElement`willbeinjectedinecharts.jsfunctionExtensionAPI(chartInstance){each$1(echartsAPIList,function(name){this[name]=bind(chartInstance[name],chartInstance);},this);}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var coordinateSystemCreators = {};function CoordinateSystemManager() { this._coordinateSystems = [];}CoordinateSystemManager.prototype = { constructor: CoordinateSystemManager, create: function (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 (ecModel, api) { each$1(this._coordinateSystems, function (coordSys) { coordSys.update && coordSys.update(ecModel, api); }); }, getCoordinateSystems: function () { return this._coordinateSystems.slice(); }};CoordinateSystemManager.register = function (type, coordinateSystemCreator) { coordinateSystemCreators[type] = coordinateSystemCreator;};CoordinateSystemManager.get = function (type) { return coordinateSystemCreators[type];};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***EChartsoptionmanager**@module{echarts/model/OptionManager}*/var each$4 = each$1;var clone$3 = clone;var map$1 = map;var merge$1 = merge;var QUERY_REG = /^(min|max)?(.+)$/;/** * TERM EXPLANATIONS: * * [option]: * * An object that contains definitions of components. For example: * var option = { * title: {...}, * legend: {...}, * visualMap: {...}, * series: [ * {data: [...]}, * {data: [...]}, * ... * ] * }; * * [rawOption]: * * An object input to echarts.setOption. 'rawOption' may be an * 'option', or may be an object contains multi-options. For example: * var option = { * baseOption: { * title: {...}, * legend: {...}, * series: [ * {data: [...]}, * {data: [...]}, * ... * ] * }, * timeline: {...}, * options: [ * {title: {...}, series: {data: [...]}}, * {title: {...}, series: {data: [...]}}, * ... * ], * media: [ * { * query: {maxWidth: 320}, * option: {series: {x: 20}, visualMap: {show: false}} * }, * { * query: {minWidth: 320, maxWidth: 720}, * option: {series: {x: 500}, visualMap: {show: true}} * }, * { * option: {series: {x: 1200}, visualMap: {show: true}} * } * ] * }; * * @alias module:echarts/model/OptionManager*@param{module:echarts/ExtensionAPI}api*/function OptionManager(api) { /***@private*@type{module:echarts/ExtensionAPI}*/ this._api = api; /***@private*@type{Array.<number>}*/ this._timelineOptions = []; /***@private*@type{Array.<Object>}*/ this._mediaList = []; /***@private*@type{Object}*/ this._mediaDefault; /***-1,meansdefault.*emptymeansnomedia.*@private*@type{Array.<number>}*/ this._currentMediaIndices = []; /***@private*@type{Object}*/ this._optionBackup; /***@private*@type{Object}*/ this._newBaseOption;}//timeline.notMergeisnotsupportedinec3.Firstlythereisrearly// case that notMerge is needed. Secondly supporting 'notMerge' requires// rawOption cloned and backuped when timeline changed, which does no// good to performance. What's more, that both timeline and setOption// method supply 'notMerge' brings complex and some problems.// Consider this case:// (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);// (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);OptionManager.prototype={constructor:OptionManager,/** * @public * @param {Object} rawOption Raw option. * @param {module:echarts/model/Global}ecModel*@param{Array.<Function>}optionPreprocessorFuncs*@return{Object}Initoption*/ setOption: function (rawOption, optionPreprocessorFuncs) { if (rawOption) { //ThatsetdatprimitiveisdangerousifuserreusethedatawhensetOptionagain.each$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,// it should ensure that the repeat modify correctly// (create a new object when modify itself).rawOption=clone$3(rawOption,true);// FIXME// 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。varoldOptionBackup=this._optionBackup;varnewParsedOption=parseRawOption.call(this,rawOption,optionPreprocessorFuncs,!oldOptionBackup);this._newBaseOption=newParsedOption.baseOption;// For setOption at second time (using merge mode);if(oldOptionBackup){// Only baseOption can be merged.mergeOption(oldOptionBackup.baseOption,newParsedOption.baseOption);// For simplicity, timeline options and media options do not support merge,// that is, if you `setOption` twice and both has timeline options, the latter// timeline opitons will not be merged to the formers, but just substitude them.if(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;}},/** * @param {boolean} isRecreate * @return {Object} */mountOption:function(isRecreate){varoptionBackup=this._optionBackup;// TODO// 如果没有reset功能则不clone。this._timelineOptions=map$1(optionBackup.timelineOptions,clone$3);this._mediaList=map$1(optionBackup.mediaList,clone$3);this._mediaDefault=clone$3(optionBackup.mediaDefault);this._currentMediaIndices=[];returnclone$3(isRecreate// this._optionBackup.baseOption, which is created at the first `setOption`// called, and is merged into every new option by inner method `mergeOption`// each time `setOption` called, can be only used in `isRecreate`, because// its reliability is under suspicion. In other cases option merge is// performed by `model.mergeOption`.?optionBackup.baseOption:this._newBaseOption);},/** * @param {module:echarts/model/Global}ecModel*@return{Object}*/ getTimelineOption: function (ecModel) { var option; var timelineOptions = this._timelineOptions; if (timelineOptions.length) { //getTimelineOptioncanonlybecalledafterecModelinited,// so we can get currentIndex from timelineModel.vartimelineModel=ecModel.getComponent('timeline');if(timelineModel){option=clone$3(timelineOptions[timelineModel.getCurrentIndex()],true);}}returnoption;},/** * @param {module:echarts/model/Global}ecModel*@return{Array.<Object>}*/ getMediaOption: function (ecModel) { var ecWidth = this._api.getWidth(); var ecHeight = this._api.getHeight(); var mediaList = this._mediaList; var mediaDefault = this._mediaDefault; var indices = []; var result = []; //Nomediadefined.if(!mediaList.length&&!mediaDefault){returnresult;}// Multi media may be applied, the latter defined media has higher priority.for(vari=0,len=mediaList.length;i<len;i++){if(applyMediaQuery(mediaList[i].query,ecWidth,ecHeight)){indices.push(i);}}// FIXME// 是否mediaDefault应该强制用户设置,否则可能修改不能回归。if(!indices.length&&mediaDefault){indices=[-1];}if(indices.length&&!indicesEquals(indices,this._currentMediaIndices)){result=map$1(indices,function(index){returnclone$3(index===-1?mediaDefault.option:mediaList[index].option);});}// Otherwise return nothing.this._currentMediaIndices=indices;returnresult;}};functionparseRawOption(rawOption,optionPreprocessorFuncs,isNew){vartimelineOptions=[];varmediaList=[];varmediaDefault;varbaseOption;// Compatible with ec2.vartimelineOpt=rawOption.timeline;if(rawOption.baseOption){baseOption=rawOption.baseOption;}// For timelineif(timelineOpt||rawOption.options){baseOption=baseOption||{};timelineOptions=(rawOption.options||[]).slice();}// For media queryif(rawOption.media){baseOption=baseOption||{};varmedia=rawOption.media;each$4(media,function(singleMedia){if(singleMedia&&singleMedia.option){if(singleMedia.query){mediaList.push(singleMedia);}elseif(!mediaDefault){// Use the first media default.mediaDefault=singleMedia;}}});}// For normal optionif(!baseOption){baseOption=rawOption;}// Set timelineOpt to baseOption in ec3,// which is convenient for merge option.if(!baseOption.timeline){baseOption.timeline=timelineOpt;}// Preprocess.each$4([baseOption].concat(timelineOptions).concat(map(mediaList,function(media){returnmedia.option;})),function(option){each$4(optionPreprocessorFuncs,function(preProcess){preProcess(option,isNew);});});return{baseOption:baseOption,timelineOptions:timelineOptions,mediaDefault:mediaDefault,mediaList:mediaList};}/** * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>*Support:width,height,aspectRatio*Canusemaxorminasprefix.*/function applyMediaQuery(query, ecWidth, ecHeight) { var realMap = { width: ecWidth, height: ecHeight, aspectratio: ecWidth /ecHeight// lowser case for convenientce.};varapplicatable=true;each$1(query,function(value,attr){varmatched=attr.match(QUERY_REG);if(!matched||!matched[1]||!matched[2]){return;}varoperator=matched[1];varrealAttr=matched[2].toLowerCase();if(!compare(realMap[realAttr],value,operator)){applicatable=false;}});returnapplicatable;}functioncompare(real,expect,operator){if(operator==='min'){returnreal>=expect;}elseif(operator==='max'){returnreal<=expect;}else{// Equalsreturnreal===expect;}}functionindicesEquals(indices1,indices2){// indices is always order by asc and has only finite number.returnindices1.join(',')===indices2.join(',');}/** * Consider case: * `chart.setOption(opt1);` * Then user do some interaction like dataZoom, dataView changing. * `chart.setOption(opt2);` * Then user press 'reset button' in toolbox. * * After doing that all of the interaction effects should be reset, the * chart should be the same as the result of invoke * `chart.setOption(opt1); chart.setOption(opt2);`. * * Although it is not able ensure that * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to * `chart.setOption(merge(opt1, opt2));` exactly, * this might be the only simple way to implement that feature. * * MEMO: We've considered some other approaches: * 1. Each model handle its self restoration but not uniform treatment. * (Too complex in logic and error-prone) * 2. Use a shadow ecModel. (Performace expensive) */functionmergeOption(oldOption,newOption){newOption=newOption||{};each$4(newOption,function(newCptOpt,mainType){if(newCptOpt==null){return;}varoldCptOpt=oldOption[mainType];if(!ComponentModel.hasClass(mainType)){oldOption[mainType]=merge$1(oldCptOpt,newCptOpt,true);}else{newCptOpt=normalizeToArray(newCptOpt);oldCptOpt=normalizeToArray(oldCptOpt);varmapResult=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);});}});}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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) { //TimelinecontrolStylehasotherpropertiesbesidesnormalandemphasisif(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;}}}functionremoveEC3NormalStatus(opt){convertNormalEmphasis(opt,'itemStyle');convertNormalEmphasis(opt,'lineStyle');convertNormalEmphasis(opt,'areaStyle');convertNormalEmphasis(opt,'label');convertNormalEmphasis(opt,'labelLine');// treemapconvertNormalEmphasis(opt,'upperLabel');// graphconvertNormalEmphasis(opt,'edgeLabel');}functioncompatTextStyle(opt,propName){// Check whether is not object (string\null\undefined ...)varlabelOptSingle=isObject$3(opt)&&opt[propName];vartextStyle=isObject$3(labelOptSingle)&&labelOptSingle.textStyle;if(textStyle){for(vari=0,len=TEXT_STYLE_OPTIONS.length;i<len;i++){varpropName=TEXT_STYLE_OPTIONS[i];if(textStyle.hasOwnProperty(propName)){labelOptSingle[propName]=textStyle[propName];}}}}functioncompatEC3CommonStyles(opt){if(opt){removeEC3NormalStatus(opt);compatTextStyle(opt,'label');opt.emphasis&&compatTextStyle(opt.emphasis,'label');}}functionprocessSeries(seriesOpt){if(!isObject$3(seriesOpt)){return;}compatEC2ItemStyle(seriesOpt);removeEC3NormalStatus(seriesOpt);compatTextStyle(seriesOpt,'label');// treemapcompatTextStyle(seriesOpt,'upperLabel');// graphcompatTextStyle(seriesOpt,'edgeLabel');if(seriesOpt.emphasis){compatTextStyle(seriesOpt.emphasis,'label');// treemapcompatTextStyle(seriesOpt.emphasis,'upperLabel');// graphcompatTextStyle(seriesOpt.emphasis,'edgeLabel');}varmarkPoint=seriesOpt.markPoint;if(markPoint){compatEC2ItemStyle(markPoint);compatEC3CommonStyles(markPoint);}varmarkLine=seriesOpt.markLine;if(markLine){compatEC2ItemStyle(markLine);compatEC3CommonStyles(markLine);}varmarkArea=seriesOpt.markArea;if(markArea){compatEC3CommonStyles(markArea);}vardata=seriesOpt.data;// Break with ec3: if `setOption` again, there may be no `type` in option,// then the backward compat based on option type will not be performed.if(seriesOpt.type==='graph'){data=data||seriesOpt.nodes;varedgeData=seriesOpt.links||seriesOpt.edges;if(edgeData&&!isTypedArray(edgeData)){for(vari=0;i<edgeData.length;i++){compatEC3CommonStyles(edgeData[i]);}}each$1(seriesOpt.categories,function(opt){removeEC3NormalStatus(opt);});}if(data&&!isTypedArray(data)){for(vari=0;i<data.length;i++){compatEC3CommonStyles(data[i]);}}// mark point datavarmarkPoint=seriesOpt.markPoint;if(markPoint&&markPoint.data){varmpData=markPoint.data;for(vari=0;i<mpData.length;i++){compatEC3CommonStyles(mpData[i]);}}// mark line datavarmarkLine=seriesOpt.markLine;if(markLine&&markLine.data){varmlData=markLine.data;for(vari=0;i<mlData.length;i++){if(isArray(mlData[i])){compatEC3CommonStyles(mlData[i][0]);compatEC3CommonStyles(mlData[i][1]);}else{compatEC3CommonStyles(mlData[i]);}}}// Seriesif(seriesOpt.type==='gauge'){compatTextStyle(seriesOpt,'axisLabel');compatTextStyle(seriesOpt,'title');compatTextStyle(seriesOpt,'detail');}elseif(seriesOpt.type==='treemap'){convertNormalEmphasis(seriesOpt.breadcrumb,'itemStyle');each$1(seriesOpt.levels,function(opt){removeEC3NormalStatus(opt);});}elseif(seriesOpt.type==='tree'){removeEC3NormalStatus(seriesOpt.leaves);}// sunburst starts from ec4, so it does not need to compat levels.}functiontoArr(o){returnisArray(o)?o:o?[o]:[];}functiontoObj(o){return(isArray(o)?o[0]:o)||{};}varcompatStyle=function(option,isTheme){each$5(toArr(option.series),function(seriesOpt){isObject$3(seriesOpt)&&processSeries(seriesOpt);});varaxes=['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){varparallelAxisDefault=parallelOpt&¶llelOpt.parallelAxisDefault;compatTextStyle(parallelAxisDefault,'axisLabel');compatTextStyle(parallelAxisDefault&¶llelAxisDefault.axisPointer,'label');});each$5(toArr(option.calendar),function(calendarOpt){convertNormalEmphasis(calendarOpt,'itemStyle');compatTextStyle(calendarOpt,'dayLabel');compatTextStyle(calendarOpt,'monthLabel');compatTextStyle(calendarOpt,'yearLabel');});// radar.name.textStyleeach$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);vardata=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');};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Compatitablewith2.0functionget(opt,path){path=path.split(',');varobj=opt;for(vari=0;i<path.length;i++){obj=obj&&obj[path[i]];if(obj==null){break;}}returnobj;}functionset$1(opt,path,val,overwrite){path=path.split(',');varobj=opt;varkey;for(vari=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;}}functioncompatLayoutProperties(option){each$1(LAYOUT_PROPERTIES,function(prop){if(prop[0]inoption&&!(prop[1]inoption)){option[prop[1]]=option[prop[0]];}});}varLAYOUT_PROPERTIES=[['x','left'],['y','top'],['x2','right'],['y2','bottom']];varCOMPATITABLE_COMPONENTS=['grid','geo','parallel','legend','toolbox','title','visualMap','dataZoom','timeline'];varbackwardCompat=function(option,isTheme){compatStyle(option,isTheme);// Make sure series array for model initialization.option.series=normalizeToArray(option.series);each$1(option.series,function(seriesOpt){if(!isObject$1(seriesOpt)){return;}varseriesType=seriesOpt.type;if(seriesType==='pie'||seriesType==='gauge'){if(seriesOpt.clockWise!=null){seriesOpt.clockwise=seriesOpt.clockWise;}}if(seriesType==='gauge'){varpointerColor=get(seriesOpt,'pointer.color');pointerColor!=null&&set$1(seriesOpt,'itemStyle.normal.color',pointerColor);}compatLayoutProperties(seriesOpt);});// dataRange has changed to visualMapif(option.dataRange){option.visualMap=option.dataRange;}each$1(COMPATITABLE_COMPONENTS,function(componentName){varoptions=option[componentName];if(options){if(!isArray(options)){options=[options];}each$1(options,function(option){compatLayoutProperties(option);});}});};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///(1)[Caution]:thelogiciscorrectbasedonthepremises:// data processing stage is blocked in stream.// See <module:echarts/stream/Scheduler#performDataProcessorTasks>// (2) Only register once when import repeatly.// Should be executed before after series filtered and before stack calculation.vardataStack=function(ecModel){varstackInfoMap=createHashMap();ecModel.eachSeries(function(seriesModel){varstack=seriesModel.get('stack');// Compatibal: when `stack` is set as '', do not stack.if(stack){varstackInfoList=stackInfoMap.get(stack)||stackInfoMap.set(stack,[]);vardata=seriesModel.getData();varstackInfo={// Used for calculate axis extent automatically.stackResultDimension:data.getCalculationInfo('stackResultDimension'),stackedOverDimension:data.getCalculationInfo('stackedOverDimension'),stackedDimension:data.getCalculationInfo('stackedDimension'),stackedByDimension:data.getCalculationInfo('stackedByDimension'),isStackedByIndex:data.getCalculationInfo('isStackedByIndex'),data:data,seriesModel:seriesModel};// If stacked on axis that do not support data stack.if(!stackInfo.stackedDimension||!(stackInfo.isStackedByIndex||stackInfo.stackedByDimension)){return;}stackInfoList.length&&data.setCalculationInfo('stackedOnSeries',stackInfoList[stackInfoList.length-1].seriesModel);stackInfoList.push(stackInfo);}});stackInfoMap.each(calculateStack);};functioncalculateStack(stackInfoList){each$1(stackInfoList,function(targetStackInfo,idxInStack){varresultVal=[];varresultNaN=[NaN,NaN];vardims=[targetStackInfo.stackResultDimension,targetStackInfo.stackedOverDimension];vartargetData=targetStackInfo.data;varisStackedByIndex=targetStackInfo.isStackedByIndex;// Should not write on raw data, because stack series model list changes// depending on legend selection.varnewData=targetData.map(dims,function(v0,v1,dataIndex){varsum=targetData.get(targetStackInfo.stackedDimension,dataIndex);// Consider `connectNulls` of line area, if value is NaN, stackedOver// should also be NaN, to draw a appropriate belt area.if(isNaN(sum)){returnresultNaN;}varbyValue;varstackedDataRawIndex;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.varstackedOver=NaN;for(varj=idxInStack-1;j>=0;j--){varstackInfo=stackInfoList[j];// Has been optimized by inverted indices on `stackedByDimension`.if(!isStackedByIndex){stackedDataRawIndex=stackInfo.data.rawIndexOf(stackInfo.stackedByDimension,byValue);}if(stackedDataRawIndex>=0){varval=stackInfo.data.getByRawIndex(stackInfo.stackResultDimension,stackedDataRawIndex);// Considering positive stack, negative stack and empty dataif((sum>=0&&val>0)// Positive stack||(sum<=0&&val<0)// Negative stack){sum+=val;stackedOver=val;break;}}}resultVal[0]=sum;resultVal[1]=stackedOver;returnresultVal;});targetData.hostModel.setData(newData);// Update for consequent calculationtargetStackInfo.data=newData;});}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///TODO// ??? refactor? check the outer usage of data provider.// merge with defaultDimValueGetter?/***Ifnormalarrayused,mutablechunksizeissupported.*Iftypedarrayused,chunksizemustbefixed.*/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; //Typedarray.TODOIE10+?if(sourceFormat===SOURCE_FORMAT_TYPED_ARRAY){if(__DEV__){if(dimSize==null){thrownewError('Typed array data must specify dimension size');}}this._offset=0;this._dimSize=dimSize;this._data=data;}varmethods=providerMethods[sourceFormat===SOURCE_FORMAT_ARRAY_ROWS?sourceFormat+'_'+source.seriesLayoutBy:sourceFormat];if(__DEV__){assert$1(methods,'Invalide sourceFormat: '+sourceFormat);}extend(this,methods);}varproviderProto=DefaultDataProvider.prototype;// If data is pure without style configurationproviderProto.pure=false;// If data is persistent and will not be released after use.providerProto.persistent=true;// ???! FIXME legacy data provider do not has method getSourceproviderProto.getSource=function(){returnthis._source;};varproviderMethods={'arrayRows_column':{pure:true,count:function(){returnMath.max(0,this._data.length-this._source.startIndex);},getItem:function(idx){returnthis._data[idx+this._source.startIndex];},appendData:appendDataSimply},'arrayRows_row':{pure:true,count:function(){varrow=this._data[0];returnrow?Math.max(0,row.length-this._source.startIndex):0;},getItem:function(idx){idx+=this._source.startIndex;varitem=[];vardata=this._data;for(vari=0;i<data.length;i++){varrow=data[i];item.push(row?row[idx]:null);}returnitem;},appendData:function(){thrownewError('Do not support appendData when set seriesLayoutBy: "row".');}},'objectRows':{pure:true,count:countSimply,getItem:getItemSimply,appendData:appendDataSimply},'keyedColumns':{pure:true,count:function(){vardimName=this._source.dimensionsDefine[0].name;varcol=this._data[dimName];returncol?col.length:0;},getItem:function(idx){varitem=[];vardims=this._source.dimensionsDefine;for(vari=0;i<dims.length;i++){varcol=this._data[dims[i].name];item.push(col?col[idx]:null);}returnitem;},appendData:function(newData){vardata=this._data;each$1(newData,function(newCol,key){varoldCol=data[key]||(data[key]=[]);for(vari=0;i<(newCol||[]).length;i++){oldCol.push(newCol[i]);}});}},'original':{count:countSimply,getItem:getItemSimply,appendData:appendDataSimply},'typedArray':{persistent:false,pure:true,count:function(){returnthis._data?(this._data.length/this._dimSize):0;},getItem:function(idx,out){idx=idx-this._offset;out=out||[];varoffset=this._dimSize*idx;for(vari=0;i<this._dimSize;i++){out[i]=this._data[offset+i];}returnout;},appendData:function(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.clean:function(){// PENDINGthis._offset+=this.count();this._data=null;}}};functioncountSimply(){returnthis._data.length;}functiongetItemSimply(idx){returnthis._data[idx];}functionappendDataSimply(newData){for(vari=0;i<newData.length;i++){this._data.push(newData[i]);}}varrawValueGetters={arrayRows:getRawValueSimply,objectRows:function(dataItem,dataIndex,dimIndex,dimName){returndimIndex!=null?dataItem[dimName]:dataItem;},keyedColumns:getRawValueSimply,original:function(dataItem,dataIndex,dimIndex,dimName){// FIXME// In some case (markpoint in geo (geo-map.html)), dataItem// is {coord: [...]}varvalue=getDataItemValue(dataItem);return(dimIndex==null||!(valueinstanceofArray))?value:value[dimIndex];},typedArray:getRawValueSimply};functiongetRawValueSimply(dataItem,dataIndex,dimIndex,dimName){returndimIndex!=null?dataItem[dimIndex]:dataItem;}vardefaultDimValueGetters={arrayRows:getDimValueSimply,objectRows:function(dataItem,dimName,dataIndex,dimIndex){returnconverDataValue(dataItem[dimName],this._dimensionInfos[dimName]);},keyedColumns:getDimValueSimply,original:function(dataItem,dimName,dataIndex,dimIndex){// Performance sensitive, do not use modelUtil.getDataItemValue.// If dataItem is an plain object with no value field, the var `value`// will be assigned with the object, but it will be tread correctly// in the `convertDataValue`.varvalue=dataItem&&(dataItem.value==null?dataItem:dataItem.value);// If any dataItem is like { value: 10 }if(!this._rawData.pure&&isDataItemOption(dataItem)){this.hasItemOption=true;}returnconverDataValue((valueinstanceofArray)?value[dimIndex]// If value is a single number or something else not array.:value,this._dimensionInfos[dimName]);},typedArray:function(dataItem,dimName,dataIndex,dimIndex){returndataItem[dimIndex];}};functiongetDimValueSimply(dataItem,dimName,dataIndex,dimIndex){returnconverDataValue(dataItem[dimIndex],this._dimensionInfos[dimName]);}/** * This helper method convert value in data. * @param {string|number|Date} value * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'. * If "dimInfo.ordinalParseAndSave", ordinal value can be parsed. */functionconverDataValue(value,dimInfo){// Performance sensitive.vardimType=dimInfo&&dimInfo.type;if(dimType==='ordinal'){// If given value is a category stringvarordinalMeta=dimInfo&&dimInfo.ordinalMeta;returnordinalMeta?ordinalMeta.parseAndCollect(value):value;}if(dimType==='time'// spead up when using timestamp&&typeofvalue!=='number'&&value!=null&&value!=='-'){value=+parseDate(value);}// dimType defaults 'number'.// If dimType is not ordinal and value is null or undefined or NaN or '-',// parse to NaN.return(value==null||value==='')?NaN// If string (like '-'), using '+' parse to NaN// If object, also parse to NaN:+value;}// ??? FIXME can these logic be more neat: getRawValue, getRawDataItem,// Consider persistent.// Caution: why use raw value to display on label or tooltip?// A reason is to avoid format. For example time value we do not know// how to format is expected. More over, if stack is used, calculated// value may be 0.91000000001, which have brings trouble to display.// TODO: consider how to treat null/undefined/NaN when display?/** * @param {module:echarts/data/List}data*@param{number}dataIndex*@param{string|number}[dim]dimNameordimIndex*@return{Array.<number>|string|number}canbenull/undefined.*/function retrieveRawValue(data, dataIndex, dim) { if (!data) { return; } //Considerdatamaybenotpersistent.vardataItem=data.getRawDataItem(dataIndex);if(dataItem==null){return;}varsourceFormat=data.getProvider().getSource().sourceFormat;vardimName;vardimIndex;vardimInfo=data.getDimensionInfo(dim);if(dimInfo){dimName=dimInfo.name;dimIndex=dimInfo.index;}returnrawValueGetters[sourceFormat](dataItem,dataIndex,dimIndex,dimName);}/** * Compatible with some cases (in pie, map) like: * data: [{name: 'xx', value: 5, selected: true}, ...] * where only sourceFormat is 'original' and 'objectRows' supported. * * ??? TODO * Supported detail options in data item when using 'arrayRows'. * * @param {module:echarts/data/List}data*@param{number}dataIndex*@param{string}attrlike'selected'*/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]; }}/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var DIMENSION_LABEL_REG = /\{@(.+?)\}/g;//PENDINGAlittleuglyvardataFormatMixin={/***Getparamsforformatter*@param{number}dataIndex*@param{string}[dataType]*@return{Object}*/ getDataParams: function (dataIndex, dataType) { var data = this.getData(dataType); var rawValue = this.getRawValue(dataIndex, dataType); var rawDataIndex = data.getRawIndex(dataIndex); var name = data.getName(dataIndex); var itemOpt = data.getRawDataItem(dataIndex); var color = data.getItemVisual(dataIndex, 'color'); var tooltipModel = this.ecModel.getComponent('tooltip'); var renderModeOption = tooltipModel && tooltipModel.get('renderMode'); var renderMode = getTooltipRenderMode(renderModeOption); var mainType = this.mainType; var isSeries = mainType === 'series'; 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, marker: getTooltipMarker({ color: color, renderMode: renderMode }), //Paramnamelistformapping`a`,`b`,`c`,`d`,`e`$vars:['seriesName','name','value']};},/** * Format label * @param {number} dataIndex * @param {string} [status='normal'] 'normal' or 'emphasis' * @param {string} [dataType] * @param {number} [dimIndex] * @param {string} [labelProp='label'] * @return {string} If not formatter, return null/undefined*/ getFormattedLabel: function (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; return formatter(params); } else if (typeof formatter === 'string') { var str = formatTpl(formatter, params); //Support'aaa{@[3]}bbb{@product}ccc'.// Do not support '}' in dim name util have to.returnstr.replace(DIMENSION_LABEL_REG,function(origin,dim){varlen=dim.length;if(dim.charAt(0)==='['&&dim.charAt(len-1)===']'){dim=+dim.slice(1,len-1);// Also: '[]' => 0}returnretrieveRawValue(data,dataIndex,dim);});}},/** * Get raw value in option * @param {number} idx * @param {string} [dataType] * @return {Array|number|string} */getRawValue:function(idx,dataType){returnretrieveRawValue(this.getData(dataType),idx);},/** * Should be implemented. * @param {number} dataIndex * @param {boolean} [multipleSeries=false] * @param {number} [dataType] * @return {string} tooltip string */formatTooltip:function(){// Empty function}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@param{Object}define*@returnSeethereturnof`createTask`.*/function createTask(define) { return new Task(define);}/***@constructor*@param{Object}define*@param{Function}define.resetCustomreset*@param{Function}[define.plan]Returns'reset'indicateresetimmediately.*@param{Function}[define.count]countisusedtodetermindatatask.*@param{Function}[define.onDirty]countisusedtodetermindatatask.*/function Task(define) { define = define || {}; this._reset = define.reset; this._plan = define.plan; this._count = define.count; this._onDirty = define.onDirty; this._dirty = true; //Contextmustbespecifiedimplicitly,to// avoid miss update context when model changed.this.context;}vartaskProto=Task.prototype;/** * @param {Object} performArgs * @param {number} [performArgs.step] Specified step. * @param {number} [performArgs.skip] Skip customer perform call. * @param {number} [performArgs.modBy] Sampling window size. * @param {number} [performArgs.modDataCount] Sampling count. */taskProto.perform=function(performArgs){varupTask=this._upstream;varskip=performArgs&&performArgs.skip;// TODO some refactor.// Pull data. Must pull data each time, because context.data// may be updated by Series.setData.if(this._dirty&&upTask){varcontext=this.context;context.data=context.outputData=upTask.context.outputData;}if(this.__pipeline){this.__pipeline.currentTask=this;}varplanResult;if(this._plan&&!skip){planResult=this._plan(this.context);}// Support sharding by mod, which changes the render sequence and makes the rendered graphic// elements uniformed distributed when progress, especially when moving or zooming.varlastModBy=normalizeModBy(this._modBy);varlastModDataCount=this._modDataCount||0;varmodBy=normalizeModBy(performArgs&&performArgs.modBy);varmodDataCount=performArgs&&performArgs.modDataCount||0;if(lastModBy!==modBy||lastModDataCount!==modDataCount){planResult='reset';}functionnormalizeModBy(val){!(val>=1)&&(val=1);// jshint ignore:linereturnval;}varforceFirstProgress;if(this._dirty||planResult==='reset'){this._dirty=false;forceFirstProgress=reset(this,skip);}this._modBy=modBy;this._modDataCount=modDataCount;varstep=performArgs&&performArgs.step;if(upTask){if(__DEV__){assert$1(upTask._outputDueEnd!=null);}this._dueEnd=upTask._outputDueEnd;}// DataTask or overallTaskelse{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.// If no progress, pass index from upstream to downstream each time plan called.if(this._progress){varstart=this._dueIndex;varend=Math.min(step!=null?this._dueIndex+step:Infinity,this._dueEnd);if(!skip&&(forceFirstProgress||start<end)){varprogress=this._progress;if(isArray(progress)){for(vari=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// input data is the same, so use `dueIndex` as `outputDueEnd`.varoutputDueEnd=this._settedOutputEnd!=null?this._settedOutputEnd:end;if(__DEV__){// ??? Can not rollback.assert$1(outputDueEnd>=this._outputDueEnd);}this._outputDueEnd=outputDueEnd;}else{// (1) Some overall task has no progress.// (2) Stubs, that its host overall task do not let it has progress, has no progress.// This should always be performed so it can be passed to downstream.this._dueIndex=this._outputDueEnd=this._settedOutputEnd!=null?this._settedOutputEnd:this._dueEnd;}returnthis.unfinished();};variterator=(function(){varend;varcurrent;varmodBy;varmodDataCount;varwinCount;varit={reset:function(s,e,sStep,sCount){current=s;end=e;modBy=sStep;modDataCount=sCount;winCount=Math.ceil(modDataCount/modBy);it.next=(modBy>1&&modDataCount>0)?modNext:sequentialNext;}};returnit;functionsequentialNext(){returncurrent<end?current++:null;}functionmodNext(){vardataIndex=(current%winCount)*modBy+Math.ceil(current/winCount);varresult=current>=end?null:dataIndex<modDataCount?dataIndex// If modDataCount is smaller than data.count() (consider `appendData` case),// Use normal linear rendering mode.:current;current++;returnresult;}})();taskProto.dirty=function(){this._dirty=true;this._onDirty&&this._onDirty(this.context);};functiondoProgress(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);}functionreset(taskIns,skip){taskIns._dueIndex=taskIns._outputDueEnd=taskIns._dueEnd=0;taskIns._settedOutputEnd=null;varprogress;varforceFirstProgress;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.if(isArray(progress)&&!progress.length){progress=null;}}taskIns._progress=progress;taskIns._modBy=taskIns._modDataCount=null;vardownstream=taskIns._downstream;downstream&&downstream.dirty();returnforceFirstProgress;}/** * @return {boolean} */taskProto.unfinished=function(){returnthis._progress&&this._dueIndex<this._dueEnd;};/** * @param {Object} downTask The downstream task. * @return {Object} The downstream task. */taskProto.pipe=function(downTask){if(__DEV__){assert$1(downTask&&!downTask._disposed&&downTask!==this);}// If already downstream, do not dirty downTask.if(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(){returnthis._upstream;};taskProto.getDownstream=function(){returnthis._downstream;};taskProto.setOutputEnd=function(end){// This only happend in dataTask, dataZoom, map, currently.// where dataZoom do not set end each time, but only set// when reset. So we should record the setted end, in case// that the stub of dataZoom perform again and earse the// setted end by upstream.this._outputDueEnd=this._settedOutputEnd=end;};///////////////////////////////////////////////////////////// For stream debug (Should be commented out after used!)// Usage: printTask(this, 'begin');// Usage: printTask(this, null, {someExtraProp});// function printTask(task, prefix, extra) {// window.ecTaskUID == null && (window.ecTaskUID = 0);// task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);// task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);// var props = [];// if (task.__pipeline) {// var val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;// props.push({text: 'idx', value: val});// } else {// var stubCount = 0;// task.agentStubMap.each(() => stubCount++);// props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});// }// props.push({text: 'uid', value: task.uidDebug});// if (task.__pipeline) {// props.push({text: 'pid', value: task.__pipeline.id});// task.agent && props.push(// {text: 'stubFor', value: task.agent.uidDebug}// );// }// props.push(// {text: 'dirty', value: task._dirty},// {text: 'dueIndex', value: task._dueIndex},// {text: 'dueEnd', value: task._dueEnd},// {text: 'outputDueEnd', value: task._outputDueEnd}// );// if (extra) {// Object.keys(extra).forEach(key => {// props.push({text: key, value: extra[key]});// });// }// var args = ['color: blue'];// var msg = `%c[${prefix || 'T'}] %c` + props.map(item => (// args.push('color: black', 'color: red'),// `${item.text}: %c${item.value}`// )).join('%c, ');// console.log.apply(console, [msg].concat(args));// // console.log(this);// }/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var inner$4 = makeInner();var SeriesModel = ComponentModel.extend({ type: 'series.__base__', /***@readOnly*/ seriesIndex: 0, //coodinateSystemwillbeinjectedintheecharts/CoordinateSystemcoordinateSystem:null,/** * @type {Object} * @protected */defaultOption:null,/** * Data provided for legend * @type {Function} */// PENDINGlegendDataProvider:null,/** * Access path of color for visual */visualColorAccessPath:'itemStyle.color',/** * Support merge layout params. * Only support 'box' now (left/right/top/bottom/width/height).*@type{string|Object}Objectcanbe{ignoreSize:true}*@readOnly*/ layoutMode: null, init: function (option, parentModel, ecModel, extraOpt) { /***@type{number}*@readOnly*/ 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.'); } /***@type{module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}*@private*/ inner$4(this).dataBeforeProcessed = data; //Ifwereversetheorder(makedatafirstly,andthenmake// dataBeforeProcessed by cloneShallow), cloneShallow will// cause data.graph.data !== data when using// module:echarts/data/Graph or module:echarts/data/Tree.// See module:echarts/data/helper/linkList// Theoretically, it is unreasonable to call `seriesModel.getData()` in the model// init or merge stage, because the data can be restored. So we do not `restoreData`// and `setData` here, which forbids calling `seriesModel.getData()` in this stage.// Call `seriesModel.getRawData()` instead.// this.restoreData();autoSeriesName(this);},/** * Util for merge default and theme to option * @param {Object} option * @param {module:echarts/model/Global}ecModel*/ mergeDefaultAndTheme: function (option, ecModel) { var layoutMode = this.layoutMode; var inputPositionParams = layoutMode? getLayoutParams(option) : {}; //Backwardcompat:usingsubTypeontheme.// But if name duplicate between series subType// (for example: parallel) add component mainType,// add suffix 'Series'.varthemeSubType=this.subType;if(ComponentModel.hasClass(themeSubType)){themeSubType+='Series';}merge(option,ecModel.getTheme().get(this.subType));merge(option,this.getDefaultOption());// Default label emphasis `show`defaultEmphasis(option,'label',['show']);this.fillDataTextStyle(option.data);if(layoutMode){mergeLayoutParam(option,inputPositionParams,layoutMode);}},mergeOption:function(newSeriesOption,ecModel){// this.settingTask.dirty();newSeriesOption=merge(this.option,newSeriesOption,true);this.fillDataTextStyle(newSeriesOption.data);varlayoutMode=this.layoutMode;if(layoutMode){mergeLayoutParam(this.option,newSeriesOption,layoutMode);}prepareSource(this);vardata=this.getInitialData(newSeriesOption,ecModel);wrapData(data,this);this.dataTask.dirty();this.dataTask.context.data=data;inner$4(this).dataBeforeProcessed=data;autoSeriesName(this);},fillDataTextStyle:function(data){// Default data label emphasis `show`// FIXME Tree structure data ?// FIXME Performance ?if(data&&!isTypedArray(data)){varprops=['show'];for(vari=0;i<data.length;i++){if(data[i]&&data[i].label){defaultEmphasis(data[i],'label',props);}}}},/** * Init a data structure from data related option in series * Must be overwritten */getInitialData:function(){},/** * Append data to list * @param {Object} params * @param {Array|TypedArray} params.data */appendData:function(params){// FIXME ???// (1) If data from dataset, forbidden append.// (2) support append data of dataset.vardata=this.getRawData();data.appendData(params.data);},/** * Consider some method like `filter`, `map` need make new data, * We should make sure that `seriesModel.getData()` get correct * data in the stream procedure. So we fetch data from upstream * each time `task.perform` called. * @param {string} [dataType] * @return {module:echarts/data/List}*/ getData: function (dataType) { var task = getCurrentTask(this); if (task) { var data = task.context.data; return dataType == null ? data : data.getLinkedData(dataType); } else { //Whenseriesisnotalive(thatmayhappenwhenclicktoolbox// restore or setOption with not merge mode), series data may// be still need to judge animation or something when graphic// elements want to know whether fade out.returninner$4(this).data;}},/** * @param {module:echarts/data/List}data*/ setData: function (data) { var task = getCurrentTask(this); if (task) { var context = task.context; //Considercase:filter,datasample.if(context.data!==data&&task.modifyOutputEnd){task.setOutputEnd(data.count());}context.outputData=data;// Caution: setData should update context.data,// Because getData may be called multiply in a// single stage and expect to get the data just// set. (For example, AxisProxy, x y both call// getData and setDate sequentially).// So the context.data should be fetched from// upstream each time when a stage starts to be// performed.if(task!==this.dataTask){context.data=data;}}inner$4(this).data=data;},/** * @see {module:echarts/data/helper/sourceHelper#getSource}*@return{module:echarts/data/Source}source*/ getSource: function () { return getSource(this); }, /***Getdatabeforeprocessed*@return{module:echarts/data/List}*/ getRawData: function () { return inner$4(this).dataBeforeProcessed; }, /***Getbaseaxisifhascoordinatesystemandhasaxis.*BydefaultusecoordSys.getBaseAxis();*Canbeoverridedforsomechart.*@return{type}description*/ getBaseAxis: function () { var coordSys = this.coordinateSystem; return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); }, //FIXME/***Defaulttooltipformatter**@param{number}dataIndex*@param{boolean}[multipleSeries=false]*@param{number}[dataType]*@param{string}[renderMode='html']validvalues:'html'and'richText'.*'html'isusedforrenderingtooltipinextraDOMform,andtheresult*stringisusedasDOMHTMLcontent.*'richText'isusedforrenderingtooltipinrichtextform,forthosewhere*DOMoperationisnotsupported.*@return{Object}formattedtooltipwith`html`and`markers`*/ formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) { var series = this; renderMode = renderMode || 'html'; var newLine = renderMode === 'html' ? '<br/>' : '\n';varisRichText=renderMode==='richText';varmarkers={};varmarkerId=0;functionformatArrayValue(value){// ??? TODO refactor these logic.// check: category-no-encode-has-axis-data in dataset.htmlvarvertially=reduce(value,function(vertially,val,idx){vardimItem=data.getDimensionInfo(idx);returnvertially|=dimItem&&dimItem.tooltip!==false&&dimItem.displayName!=null;},0);varresult=[];tooltipDims.length?each$1(tooltipDims,function(dim){setEachItem(retrieveRawValue(data,dataIndex,dim),dim);})// By default, all dims is used on tooltip.:each$1(value,setEachItem);functionsetEachItem(val,dim){vardimInfo=data.getDimensionInfo(dim);// If `dimInfo.tooltip` is not set, show tooltip.if(!dimInfo||dimInfo.otherDims.tooltip===false){return;}vardimType=dimInfo.type;varmarkName='sub'+series.seriesIndex+'at'+markerId;vardimHead=getTooltipMarker({color:color,type:'subItem',renderMode:renderMode,markerId:markName});vardimHeadStr=typeofdimHead==='string'?dimHead:dimHead.content;varvalStr=(vertially?dimHeadStr+encodeHTML(dimInfo.displayName||'-')+': ':'')// FIXME should not format time for raw data?+encodeHTML(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;}}varnewLine=vertially?(isRichText?'\n':'<br/>'):'';varcontent=newLine+result.join(newLine||', ');return{renderMode:renderMode,content:content,style:markers};}functionformatSingleValue(val){// return encodeHTML(addCommas(val));return{renderMode:renderMode,content:encodeHTML(addCommas(val)),style:markers};}vardata=this.getData();vartooltipDims=data.mapDimension('defaultedTooltip',true);vartooltipDimLen=tooltipDims.length;varvalue=this.getRawValue(dataIndex);varisValueArr=isArray(value);varcolor=data.getItemVisual(dataIndex,'color');if(isObject$1(color)&&color.colorStops){color=(color.colorStops[0]||{}).color;}color=color||'transparent';// Complicated rule for pretty tooltip.varformattedValue=(tooltipDimLen>1||(isValueArr&&!tooltipDimLen))?formatArrayValue(value):tooltipDimLen?formatSingleValue(retrieveRawValue(data,dataIndex,tooltipDims[0])):formatSingleValue(isValueArr?value[0]:value);varcontent=formattedValue.content;varmarkName=series.seriesIndex+'at'+markerId;varcolorEl=getTooltipMarker({color:color,type:'item',renderMode:renderMode,markerId:markName});markers[markName]=color;++markerId;varname=data.getName(dataIndex);varseriesName=this.name;if(!isNameSpecified(this)){seriesName='';}seriesName=seriesName?encodeHTML(seriesName)+(!multipleSeries?newLine:': '):'';varcolorStr=typeofcolorEl==='string'?colorEl:colorEl.content;varhtml=!multipleSeries?seriesName+colorStr+(name?encodeHTML(name)+': '+content:content):colorStr+seriesName+content;return{html:html,markers:markers};},/** * @return {boolean} */isAnimationEnabled:function(){if(env$1.node){returnfalse;}varanimationEnabled=this.getShallow('animation');if(animationEnabled){if(this.getData().count()>this.getShallow('animationThreshold')){animationEnabled=false;}}returnanimationEnabled;},restoreData:function(){this.dataTask.dirty();},getColorFromPalette:function(name,scope,requestColorNum){varecModel=this.ecModel;// PENDINGvarcolor=colorPaletteMixin.getColorFromPalette.call(this,name,scope,requestColorNum);if(!color){color=ecModel.getColorFromPalette(name,scope,requestColorNum);}returncolor;},/** * Use `data.mapDimension(coordDim, true)` instead. * @deprecated */coordDimToDataDim:function(coordDim){returnthis.getRawData().mapDimension(coordDim,true);},/** * Get progressive rendering count each step * @return {number} */getProgressive:function(){returnthis.get('progressive');},/** * Get progressive rendering count each step * @return {number} */getProgressiveThreshold:function(){returnthis.get('progressiveThreshold');},/** * Get data indices for show tooltip content. See tooltip. * @abstract * @param {Array.<string>|string} dim * @param {Array.<number>} value * @param {module:echarts/coord/single/SingleAxis}baseAxis*@return{Object}{dataIndices,nestestValue}.*/ getAxisTooltipData: null, /***Seetooltip.*@abstract*@param{number}dataIndex*@return{Array.<number>}Pointoftooltip.null/undefinedcanbereturned.*/ getTooltipPosition: null, /***@see{module:echarts/stream/Scheduler}*/ pipeTask: null, /***Convinientforoverrideinextendedclass.*@protected*@type{Function}*/ preventIncremental: null, /***@public*@readOnly*@type{Object}*/ pipelineContext: null});mixin(SeriesModel, dataFormatMixin);mixin(SeriesModel, colorPaletteMixin);/***MUSTbecalledafter`prepareSource`called*Hereweneedtomakeautoseries,especiallyforautolegend.Butwe*donotmodifyseries.nameinoptiontoavoidsideeffects.*/function autoSeriesName(seriesModel) { //Userspecifiednamehashigherpriority,otherwiseitmaycause// series can not be queried unexpectedly.varname=seriesModel.name;if(!isNameSpecified(seriesModel)){seriesModel.name=getSeriesAutoName(seriesModel)||name;}}functiongetSeriesAutoName(seriesModel){vardata=seriesModel.getRawData();vardataDims=data.mapDimension('seriesName',true);varnameArr=[];each$1(dataDims,function(dataDim){vardimInfo=data.getDimensionInfo(dataDim);dimInfo.displayName&&nameArr.push(dimInfo.displayName);});returnnameArr.join(' ');}functiondataTaskCount(context){returncontext.model.getRawData().count();}functiondataTaskReset(context){varseriesModel=context.model;seriesModel.setData(seriesModel.getRawData().cloneShallow());returndataTaskProgress;}functiondataTaskProgress(param,context){// Avoid repead cloneShallow when data just created in reset.if(param.end>context.outputData.count()){context.model.getRawData().cloneShallow(context.outputData);}}// TODO refactorfunctionwrapData(data,seriesModel){each$1(data.CHANGABLE_METHODS,function(methodName){data.wrapMethod(methodName,curry(onDataSelfChange,seriesModel));});}functiononDataSelfChange(seriesModel){vartask=getCurrentTask(seriesModel);if(task){// Consider case: filter, selectRangetask.setOutputEnd(this.count());}}functiongetCurrentTask(seriesModel){varscheduler=(seriesModel.ecModel||{}).scheduler;varpipeline=scheduler&&scheduler.getPipeline(seriesModel.uid);if(pipeline){// When pipline finished, the currrentTask keep the last// task (renderTask).vartask=pipeline.currentTask;if(task){varagentStubMap=task.agentStubMap;if(agentStubMap){task=agentStubMap.get(seriesModel.uid);}}returntask;}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var Component = function () { /***@type{module:zrender/container/Group}*@readOnly*/ this.group = new Group(); /***@type{string}*@readOnly*/ this.uid = getUID('viewComponent');};Component.prototype = { constructor: Component, init: function (ecModel, api) {}, render: function (componentModel, ecModel, api, payload) {}, dispose: function () {}, /***@param{string}eventType*@param{Object}query*@param{module:zrender/Element}targetEl*@param{Object}packedEvent*@return{boolen}Passonlywhenreturn`true`.*/ filterForExposedEvent: null};var componentProto = Component.prototype;componentProto.updateView = componentProto.updateLayout = componentProto.updateVisual = function (seriesModel, ecModel, api, payload) { //Donothing;};// Enable Component.extend.enableClassExtend(Component);// Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.enableClassManagement(Component,{registerWhenExtend:true});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@return{string}Iflargemodechanged,returnstring'reset';*/var createRenderPlanner = function () { var inner = makeInner(); return function (seriesModel) { var fields = inner(seriesModel); var pipelineContext = seriesModel.pipelineContext; var originalLarge = fields.large; var originalProgressive = fields.progressiveRender; var large = fields.large = pipelineContext.large; var progressive = fields.progressiveRender = pipelineContext.progressiveRender; return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset'; };};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var inner$5 = makeInner();var renderPlanner = createRenderPlanner();function Chart() { /***@type{module:zrender/container/Group}*@readOnly*/ this.group = new Group(); /***@type{string}*@readOnly*/ this.uid = getUID('viewChart'); this.renderTask = createTask({ plan: renderTaskPlan, reset: renderTaskReset }); this.renderTask.context = {view: this};}Chart.prototype = { type: 'chart', /***Initthechart.*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*/ init: function (ecModel, api) {}, /***Renderthechart.*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ render: function (seriesModel, ecModel, api, payload) {}, /***Highlightseriesorspecifieddataitem.*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ highlight: function (seriesModel, ecModel, api, payload) { toggleHighlight(seriesModel.getData(), payload, 'emphasis'); }, /***Downplayseriesorspecifieddataitem.*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ downplay: function (seriesModel, ecModel, api, payload) { toggleHighlight(seriesModel.getData(), payload, 'normal'); }, /***Removeself.*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*/ remove: function (ecModel, api) { this.group.removeAll(); }, /***Disposeself.*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*/ dispose: function () {}, /***Renderingpreparationinprogressivemode.*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ incrementalPrepareRender: null, /***Renderinprogressivemode.*@param{Object}paramsSeetaskParamsin`stream/task.js`*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ incrementalRender: null, /***Updatetransformdirectly.*@param{module:echarts/model/Series}seriesModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*@return{Object}{update:true}*/ updateTransform: null, /***Theviewcontainsthegivenpoint.*@interface*@param{Array.<number>}point*@return{boolean}*/ //containPoint:function(){}/** * @param {string} eventType * @param {Object} query * @param {module:zrender/Element}targetEl*@param{Object}packedEvent*@return{boolen}Passonlywhenreturn`true`.*/ filterForExposedEvent: null};var chartProto = Chart.prototype;chartProto.updateView = chartProto.updateLayout = chartProto.updateVisual = function (seriesModel, ecModel, api, payload) { this.render(seriesModel, ecModel, api, payload); };/***Setstateofsingleelement*@param{module:zrender/Element}el*@param{string}state*/function elSetState(el, state) { if (el) { el.trigger(state); if (el.type === 'group') { for (var i = 0; i < el.childCount(); i++) { elSetState(el.childAt(i), state); } } }}/***@param{module:echarts/data/List}data*@param{Object}payload*@param{string}state'normal'|'emphasis'*/function toggleHighlight(data, payload, state) { var dataIndex = queryDataIndex(data, payload); if (dataIndex != null) { each$1(normalizeToArray(dataIndex), function (dataIdx) { elSetState(data.getItemGraphicEl(dataIdx), state); }); } else { data.eachItemGraphicEl(function (el) { elSetState(el, state); }); }}//EnableChart.extend.enableClassExtend(Chart,['dispose']);// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.enableClassManagement(Chart,{registerWhenExtend:true});Chart.markUpdateMethod=function(payload,methodName){inner$5(payload).updateMethod=methodName;};functionrenderTaskPlan(context){returnrenderPlanner(context.model);}functionrenderTaskReset(context){varseriesModel=context.model;varecModel=context.ecModel;varapi=context.api;varpayload=context.payload;// ???! remove updateView updateVisualvarprogressiveRender=seriesModel.pipelineContext.progressiveRender;varview=context.view;varupdateMethod=payload&&inner$5(payload).updateMethod;varmethodName=progressiveRender?'incrementalPrepareRender':(updateMethod&&view[updateMethod])?updateMethod// `appendData` is also supported when data amount// is less than progressive threshold.:'render';if(methodName!=='render'){view[methodName](seriesModel,ecModel,api,payload);}returnprogressMethodMap[methodName];}varprogressMethodMap={incrementalPrepareRender:{progress:function(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// view.render should not be called in reset, otherwise it will be called// twise. Use `forceFirstProgress` to make sure that view.render is called// in any cases.forceFirstProgress:true,progress:function(params,context){context.view.render(context.model,context.ecModel,context.api,context.payload);}}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@public*@param{(Function)}fn*@param{number}[delay=0]Unit:ms.*@param{boolean}[debounce=false]*true:Ifcallintervallessthan`delay`,onlythelastcallworks.*false:Ifcallintervallessthan`delay,callworksonfixedrate.*@return{(Function)}throttledfn.*/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 () { 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); //Hereweshouldmakesurethat:the`exec`SHOULDNOTbecalledlater// than a new call of `cb`, that is, preserving the command order. Consider// calculating "scale rate" when roaming as an example. When a call of `cb`// happens, either the `exec` is called dierectly, or the call is delayed.// But the delayed call should never be later than next call of `cb`. Under// this assurance, we can simply update view state each time `dispatchAction`// triggered by user roaming, but not need to add extra code to avoid the// state being "rolled-back".if(thisDebounce){timer=setTimeout(exec,thisDelay);}else{if(diff>=0){exec();}else{timer=setTimeout(exec,-diff);}}lastCall=currCall;};/** * Clear throttle. * @public */cb.clear=function(){if(timer){clearTimeout(timer);timer=null;}};/** * Enable debounce once. */cb.debounceNextCall=function(debounceDelay){debounceNextCall=debounceDelay;};returncb;}/** * Create throttle method or update throttle rate. * * @example * ComponentView.prototype.render = function () { * ... * throttle.createOrUpdate( * this, * '_dispatchAction', * this.model.get('throttle'), * 'fixRate' * ); * }; * ComponentView.prototype.remove = function () { * throttle.clear(this, '_dispatchAction'); * }; * ComponentView.prototype.dispose = function () { * throttle.clear(this, '_dispatchAction'); * }; * * @public * @param {Object} obj * @param {string} fnAttr * @param {number} [rate] * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce' * @return {Function} throttled function. *//***Clearthrottle.Exampleseethrottle.createOrUpdate.**@public*@param{Object}obj*@param{string}fnAttr*//**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var seriesColor = { createOnAllSeries: true, performRawSeries: true, reset: function (seriesModel, ecModel) { var data = seriesModel.getData(); var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.color').split('.'); var color = seriesModel.get(colorAccessPath) //SetinitemStyle||seriesModel.getColorFromPalette(// TODO series count changed.seriesModel.name,null,ecModel.getSeriesCount());// Default color// FIXME Set color function or use the platte colordata.setVisual('color',color);// Only visible series has each data be visual encodedif(!ecModel.isSeriesFiltered(seriesModel)){if(typeofcolor==='function'&&!(colorinstanceofGradient)){data.each(function(idx){data.setItemVisual(idx,'color',color(seriesModel.getDataParams(idx)));});}// itemStyle in each data itemvardataEach=function(data,idx){varitemModel=data.getItemModel(idx);varcolor=itemModel.get(colorAccessPath,true);if(color!=null){data.setItemVisual(idx,'color',color);}};return{dataEach:data.hasItemOption?dataEach:null};}}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var lang = { toolbox: { brush: { title: { rect: '矩形选择', polygon: '圈选', lineX: '横向选择', lineY: '纵向选择', keep: '保持选择', clear: '清除选择' } }, dataView: { title: '数据视图', lang: ['数据视图', '关闭', '刷新'] }, dataZoom: { title: { zoom: '区域缩放', back: '区域缩放还原' } }, magicType: { title: { line: '切换为折线图', bar: '切换为柱状图', stack: '切换为堆叠', tiled: '切换为平铺' } }, restore: { title: '还原' }, saveAsImage: { title: '保存为图片', lang: ['右键另存为图片'] } }, series: { typeNames: { pie: '饼图', bar: '柱状图', line: '折线图', scatter: '散点图', effectScatter: '涟漪散点图', radar: '雷达图', tree: '树图', treemap: '矩形树图', boxplot: '箱型图', candlestick: 'K线图', k: 'K线图', heatmap: '热力图', map: '地图', parallel: '平行坐标图', lines: '线图', graph: '关系图', sankey: '桑基图', funnel: '漏斗图', gauge: '仪表盘图', pictorialBar: '象形柱图', themeRiver: '主题河流图', sunburst: '旭日图' } }, aria: { general: { withTitle: '这是一个关于“{title}”的图表。', withoutTitle: '这是一个图表,' }, series: { single: { prefix: '', withName: '图表类型是{seriesType},表示{seriesName}。', withoutName: '图表类型是{seriesType}。' }, multiple: { prefix: '它由{seriesCount}个图表系列组成。', withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},', withoutName: '第{seriesId}个系列是一个{seriesType},', separator: { middle: ';', end: '。' } } }, data: { allData: '其数据是——', partialData: '其中,前{displayCnt}项是——', withName: '{name}的数据是{value}', withoutName: '{value}', separator: { middle: ',', end: '' } } }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var aria = function (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) { //Noseries,noarialabelreturn;}else{vartitle=getTitle();if(title){ariaLabel=replace(getConfig('general.withTitle'),{title:title});}else{ariaLabel=getConfig('general.withoutTitle');}varseriesLabels=[];varprefix=seriesCnt>1?'series.multiple.prefix':'series.single.prefix';ariaLabel+=replace(getConfig(prefix),{seriesCount:seriesCnt});ecModel.eachSeries(function(seriesModel,idx){if(idx<displaySeriesCnt){varseriesLabel;varseriesName=seriesModel.get('name');varseriesTpl='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)});vardata=seriesModel.getData();window.data=data;if(data.count()>maxDataCnt){// Show part of dataseriesLabel+=replace(getConfig('data.partialData'),{displayCnt:maxDataCnt});}else{seriesLabel+=getConfig('data.allData');}vardataLabels=[];for(vari=0;i<data.count();i++){if(i<maxDataCnt){varname=data.getName(i);varvalue=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);}functionreplace(str,keyValues){if(typeofstr!=='string'){returnstr;}varresult=str;each$1(keyValues,function(value,key){result=result.replace(newRegExp('\\{\\s*'+key+'\\s*\\}','g'),value);});returnresult;}functiongetConfig(path){varuserConfig=ariaModel.get(path);if(userConfig==null){varpathArr=path.split('.');varresult=lang.aria;for(vari=0;i<pathArr.length;++i){result=result[pathArr[i]];}returnresult;}else{returnuserConfig;}}functiongetTitle(){vartitle=ecModel.getModel('title').option;if(title&&title.length){title=title[0];}returntitle&&title.text;}functiongetSeriesTypeName(type){returnlang.series.typeNames[type]||'自定义图';}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var PI$1 = Math.PI;/***@param{module:echarts/ExtensionAPI}api*@param{Object}[opts]*@param{string}[opts.text]*@param{string}[opts.color]*@param{string}[opts.textColor]*@return{module:zrender/Element}*/var loadingDefault = function (api, opts) { opts = opts || {}; defaults(opts, { text: 'loading', color: '#c23531', textColor: '#000', maskColor: 'rgba(255, 255, 255, 0.8)', zlevel: 0 }); var mask = new Rect({ style: { fill: opts.maskColor }, zlevel: opts.zlevel, z: 10000 }); var arc = new Arc({ shape: { startAngle: -PI$1 /2,endAngle:-PI$1/2+0.1,r:10},style:{stroke:opts.color,lineCap:'round',lineWidth:5},zlevel:opts.zlevel,z:10001});varlabelRect=newRect({style:{fill:'none',text:opts.text,textPosition:'right',textDistance:10,textFill:opts.textColor},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');vargroup=newGroup();group.add(arc);group.add(labelRect);group.add(mask);// Inject resizegroup.resize=function(){varcx=api.getWidth()/2;varcy=api.getHeight()/2;arc.setShape({cx:cx,cy:cy});varr=arc.shape.r;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();returngroup;};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@moduleecharts/stream/Scheduler*//***@constructor*/function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) { this.ecInstance = ecInstance; this.api = api; this.unfinished; //Fixcurrentprocessorsincasethatinsomerearcasesthat// processors might be registered after echarts instance created.// Register processors incrementally for a echarts instance is// not supported by this stream architecture.vardataProcessorHandlers=this._dataProcessorHandlers=dataProcessorHandlers.slice();varvisualHandlers=this._visualHandlers=visualHandlers.slice();this._allHandlers=dataProcessorHandlers.concat(visualHandlers);/** * @private * @type { * [handlerUID: string]: { * seriesTaskMap?: { * [seriesUID: string]: Task * }, * overallTask?: Task * } * } */this._stageTaskMap=createHashMap();}varproto=Scheduler.prototype;/** * @param {module:echarts/model/Global}ecModel*@param{Object}payload*/proto.restoreData = function (ecModel, payload) { //TODO:Onlyrestroeneededseriesandcomponents,butnotallcomponents.// Currently `restoreData` of all of the series and component will be called.// But some independent components like `title`, `legend`, `graphic`, `toolbox`,// `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,// and some components like coordinate system, axes, dataZoom, visualMap only// need their target series refresh.// (1) If we are implementing this feature some day, we should consider these cases:// if a data processor depends on a component (e.g., dataZoomProcessor depends// on the settings of `dataZoom`), it should be re-performed if the component// is modified by `setOption`.// (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,// it should be re-performed when the result array of `getTargetSeries` changed.// We use `dependencies` to cover these issues.// (3) How to update target series when coordinate system related components modified.// TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,// and this case all of the tasks will be set as dirty.ecModel.restoreData(payload);// Theoretically an overall task not only depends on each of its target series, but also// depends on all of the series.// The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks// dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure// that the overall task is set as dirty and to be performed, otherwise it probably cause// state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it// probably cause state chaos (consider `dataZoomProcessor`).this._stageTaskMap.each(function(taskRecord){varoverallTask=taskRecord.overallTask;overallTask&&overallTask.dirty();});};// If seriesModel provided, incremental threshold is check by series data.proto.getPerformArgs=function(task,isBlock){// For overall taskif(!task.__pipeline){return;}varpipeline=this._pipelineMap.get(task.__pipeline.id);varpCtx=pipeline.context;varincremental=!isBlock&&pipeline.progressiveEnabled&&(!pCtx||pCtx.progressiveRender)&&task.__idxInPipeline>pipeline.blockIndex;varstep=incremental?pipeline.step:null;varmodDataCount=pCtx&&pCtx.modDataCount;varmodBy=modDataCount!=null?Math.ceil(modDataCount/step):null;return{step:step,modBy:modBy,modDataCount:modDataCount};};proto.getPipeline=function(pipelineId){returnthis._pipelineMap.get(pipelineId);};/** * Current, progressive rendering starts from visual and layout. * Always detect render mode in the same stage, avoiding that incorrect * detection caused by data filtering. * Caution: * `updateStreamModes` use `seriesModel.getData()`. */proto.updateStreamModes=function(seriesModel,view){varpipeline=this._pipelineMap.get(seriesModel.uid);vardata=seriesModel.getData();vardataLen=data.count();// `progressiveRender` means that can render progressively in each// animation frame. Note that some types of series do not provide// `view.incrementalPrepareRender` but support `chart.appendData`. We// use the term `incremental` but not `progressive` to describe the// case that `chart.appendData`.varprogressiveRender=pipeline.progressiveEnabled&&view.incrementalPrepareRender&&dataLen>=pipeline.threshold;varlarge=seriesModel.get('large')&&dataLen>=seriesModel.get('largeThreshold');// TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.// see `test/candlestick-large3.html`varmodDataCount=seriesModel.get('progressiveChunkMode')==='mod'?dataLen:null;seriesModel.pipelineContext=pipeline.context={progressiveRender:progressiveRender,modDataCount:modDataCount,large:large};};proto.restorePipelines=function(ecModel){varscheduler=this;varpipelineMap=scheduler._pipelineMap=createHashMap();ecModel.eachSeries(function(seriesModel){varprogressive=seriesModel.getProgressive();varpipelineId=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(){varstageTaskMap=this._stageTaskMap;varecModel=this.ecInstance.getModel();varapi=this.api;each$1(this._allHandlers,function(handler){varrecord=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){varrenderTask=view.renderTask;varcontext=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.performStageTasks(this,this._dataProcessorHandlers,ecModel,payload,{block:true});};// opt// opt.visualType: 'visual' or 'layout'// opt.setDirtyproto.performVisualTasks=function(ecModel,payload,opt){performStageTasks(this,this._visualHandlers,ecModel,payload,opt);};functionperformStageTasks(scheduler,stageHandlers,ecModel,payload,opt){opt=opt||{};varunfinished;each$1(stageHandlers,function(stageHandler,idx){if(opt.visualType&&opt.visualType!==stageHandler.visualType){return;}varstageHandlerRecord=scheduler._stageTaskMap.get(stageHandler.uid);varseriesTaskMap=stageHandlerRecord.seriesTaskMap;varoverallTask=stageHandlerRecord.overallTask;if(overallTask){varoverallNeedDirty;varagentStubMap=overallTask.agentStubMap;agentStubMap.each(function(stub){if(needSetDirty(opt,stub)){stub.dirty();overallNeedDirty=true;}});overallNeedDirty&&overallTask.dirty();updatePayload(overallTask,payload);varperformArgs=scheduler.getPerformArgs(overallTask,opt.block);// Execute stubs firstly, which may set the overall task dirty,// then execute the overall task. And stub will call seriesModel.setData,// which ensures that in the overallTask seriesModel.getData() will not// return incorrect data.agentStubMap.each(function(stub){stub.perform(performArgs);});unfinished|=overallTask.perform(performArgs);}elseif(seriesTaskMap){seriesTaskMap.each(function(task,pipelineId){if(needSetDirty(opt,task)){task.dirty();}varperformArgs=scheduler.getPerformArgs(task,opt.block);performArgs.skip=!stageHandler.performRawSeries&&ecModel.isSeriesFiltered(task.context.model);updatePayload(task,payload);unfinished|=task.perform(performArgs);});}});functionneedSetDirty(opt,task){returnopt.setDirty&&(!opt.dirtyMap||opt.dirtyMap.get(task.__pipeline.id));}scheduler.unfinished|=unfinished;}proto.performSeriesTasks=function(ecModel){varunfinished;ecModel.eachSeries(function(seriesModel){// Progress to the end for dataInit and dataRestore.unfinished|=seriesModel.dataTask.perform();});this.unfinished|=unfinished;};proto.plan=function(){// Travel pipelines, check block.this._pipelineMap.each(function(pipeline){vartask=pipeline.tail;do{if(task.__block){pipeline.blockIndex=task.__idxInPipeline;break;}task=task.getUpstream();}while(task);});};varupdatePayload=proto.updatePayload=function(task,payload){payload!=='remain'&&(task.context.payload=payload);};functioncreateSeriesStageTask(scheduler,stageHandler,stageHandlerRecord,ecModel,api){varseriesTaskMap=stageHandlerRecord.seriesTaskMap||(stageHandlerRecord.seriesTaskMap=createHashMap());varseriesType=stageHandler.seriesType;vargetTargetSeries=stageHandler.getTargetSeries;// If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,// to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,// it works but it may cause other irrelevant charts blocked.if(stageHandler.createOnAllSeries){ecModel.eachRawSeries(create);}elseif(seriesType){ecModel.eachRawSeriesByType(seriesType,create);}elseif(getTargetSeries){getTargetSeries(ecModel,api).each(create);}functioncreate(seriesModel){varpipelineId=seriesModel.uid;// Init tasks for each seriesModel only once.// Reuse original task instance.vartask=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.varpipelineMap=scheduler._pipelineMap;seriesTaskMap.each(function(task,pipelineId){if(!pipelineMap.get(pipelineId)){task.dispose();seriesTaskMap.removeKey(pipelineId);}});}functioncreateOverallStageTask(scheduler,stageHandler,stageHandlerRecord,ecModel,api){varoverallTask=stageHandlerRecord.overallTask=stageHandlerRecord.overallTask// For overall task, the function only be called on reset stage.||createTask({reset:overallTaskReset});overallTask.context={ecModel:ecModel,api:api,overallReset:stageHandler.overallReset,scheduler:scheduler};// Reuse orignal stubs.varagentStubMap=overallTask.agentStubMap=overallTask.agentStubMap||createHashMap();varseriesType=stageHandler.seriesType;vargetTargetSeries=stageHandler.getTargetSeries;varoverallProgress=true;varmodifyOutputEnd=stageHandler.modifyOutputEnd;// An overall task with seriesType detected or has `getTargetSeries`, we add// stub in each pipelines, it will set the overall task dirty when the pipeline// progress. Moreover, to avoid call the overall task each frame (too frequent),// we set the pipeline block.if(seriesType){ecModel.eachRawSeriesByType(seriesType,createStub);}elseif(getTargetSeries){getTargetSeries(ecModel,api).each(createStub);}// Otherwise, (usually it is legancy case), the overall task will only be// executed when upstream dirty. Otherwise the progressive rendering of all// pipelines will be disabled unexpectedly. But it still needs stubs to receive// dirty info from upsteam.else{overallProgress=false;each$1(ecModel.getSeries(),createStub);}functioncreateStub(seriesModel){varpipelineId=seriesModel.uid;varstub=agentStubMap.get(pipelineId);if(!stub){stub=agentStubMap.set(pipelineId,createTask({reset:stubReset,onDirty:stubOnDirty}));// When the result of `getTargetSeries` changed, the overallTask// should be set as dirty and re-performed.overallTask.dirty();}stub.context={model:seriesModel,overallProgress:overallProgress,modifyOutputEnd:modifyOutputEnd};stub.agent=overallTask;stub.__block=overallProgress;pipe(scheduler,seriesModel,stub);}// Clear unused stubs.varpipelineMap=scheduler._pipelineMap;agentStubMap.each(function(stub,pipelineId){if(!pipelineMap.get(pipelineId)){stub.dispose();// When the result of `getTargetSeries` changed, the overallTask// should be set as dirty and re-performed.overallTask.dirty();agentStubMap.removeKey(pipelineId);}});}functionoverallTaskReset(context){context.overallReset(context.ecModel,context.api,context.payload);}functionstubReset(context,upstreamContext){returncontext.overallProgress&&stubProgress;}functionstubProgress(){this.agent.dirty();this.getDownstream().dirty();}functionstubOnDirty(){this.agent&&this.agent.dirty();}functionseriesTaskPlan(context){returncontext.plan&&context.plan(context.model,context.ecModel,context.api,context.payload);}functionseriesTaskReset(context){if(context.useClearVisual){context.data.clearAllVisual();}varresetDefines=context.resetDefines=normalizeToArray(context.reset(context.model,context.ecModel,context.api,context.payload));returnresetDefines.length>1?map(resetDefines,function(v,idx){returnmakeSeriesTaskProgress(idx);}):singleSeriesTaskProgress;}varsingleSeriesTaskProgress=makeSeriesTaskProgress(0);functionmakeSeriesTaskProgress(resetDefineIdx){returnfunction(params,context){vardata=context.data;varresetDefine=context.resetDefines[resetDefineIdx];if(resetDefine&&resetDefine.dataEach){for(vari=params.start;i<params.end;i++){resetDefine.dataEach(data,i);}}elseif(resetDefine&&resetDefine.progress){resetDefine.progress(params,data);}};}functionseriesTaskCount(context){returncontext.data.count();}functionpipe(scheduler,seriesModel,task){varpipelineId=seriesModel.uid;varpipeline=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);returnstageHandler;};/** * Only some legacy stage handlers (usually in echarts extensions) are pure function. * To ensure that they can work normally, they should work in block mode, that is, * they should not be started util the previous tasks finished. So they cause the * progressive rendering disabled. We try to detect the series type, to narrow down * the block range to only the series type they concern, but not all series. */functiondetectSeriseType(legacyFunc){seriesType=null;try{// Assume there is no async when calling `eachSeriesByType`.legacyFunc(ecModelMock,apiMock);}catch(e){}returnseriesType;}varecModelMock={};varapiMock={};varseriesType;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;}};functionmockMethods(target,Clz){/* eslint-disable */for(varnameinClz.prototype){// Do not use hasOwnPropertytarget[name]=noop;}/* eslint-enable */}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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 ]};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var contrastColor = '#eee';var axisCommon = function () { 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 } } }, 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;/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Thismoduleisimportedbyechartsdirectly.**Notice:*Alwayskeepthisfileexistsforbackwardcompatibility.*Becausebefore4.1.0,datasetisanoptionalcomponent,*someusersmayimportthismodulemanually.*/ComponentModel.extend({ type: 'dataset', /***@protected*/ defaultOption: { //'row','column'seriesLayoutBy:SERIES_LAYOUT_BY_COLUMN,// null/'auto': auto detect header, see "module:echarts/data/helper/sourceHelper"sourceHeader:null,dimensions:null,source:null},optionUpdated:function(){detectSourceFormat(this);}});Component.extend({type:'dataset'});/** * 椭圆形状 * @module zrender/graphic/shape/Ellipse*/var Ellipse = Path.extend({ type: 'ellipse', shape: { cx: 0, cy: 0, rx: 0, ry: 0 }, buildPath: function (ctx, shape) { var k = 0.5522848; var x = shape.cx; var y = shape.cy; var a = shape.rx; var b = shape.ry; var ox = a * k; //水平控制点偏移量varoy=b*k;// 垂直控制点偏移量// 从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线ctx.moveTo(x-a,y);ctx.bezierCurveTo(x-a,y-oy,x-ox,y-b,x,y-b);ctx.bezierCurveTo(x+ox,y-b,x+a,y-oy,x+a,y);ctx.bezierCurveTo(x+a,y+oy,x+ox,y+b,x,y+b);ctx.bezierCurveTo(x-ox,y+b,x-a,y+oy,x-a,y);ctx.closePath();}});// import RadialGradient from '../graphic/RadialGradient';// import Pattern from '../graphic/Pattern';// import * as vector from '../core/vector';// Most of the values can be separated by comma and/or white space.varDILIMITER_REG=/[\s,]+/;/** * For big svg string, this method might be time consuming. * * @param {string} svg xml string * @return {Object} xml root. */functionparseXML(svg){if(isString(svg)){varparser=newDOMParser();svg=parser.parseFromString(svg,'text/xml');}// Document node. If using $.get, doc node may be input.if(svg.nodeType===9){svg=svg.firstChild;}// nodeName of <!DOCTYPE svg> is also 'svg'.while(svg.nodeName.toLowerCase()!=='svg'||svg.nodeType!==1){svg=svg.nextSibling;}returnsvg;}functionSVGParser(){this._defs={};this._root=null;this._isDefine=false;this._isText=false;}SVGParser.prototype.parse=function(xml,opt){opt=opt||{};varsvg=parseXML(xml);if(!svg){thrownewError('Illegal svg');}varroot=newGroup();this._root=root;// parse view portvarviewBox=svg.getAttribute('viewBox')||'';// If width/height not specified, means "100%" of `opt.width/height`.// TODO: Other percent value not supported yet.varwidth=parseFloat(svg.getAttribute('width')||opt.width);varheight=parseFloat(svg.getAttribute('height')||opt.height);// If width/height not specified, set as null for output.isNaN(width)&&(width=null);isNaN(height)&&(height=null);// Apply inline style on svg element.parseAttributes(svg,root,null,true);varchild=svg.firstChild;while(child){this._parseNode(child,root);child=child.nextSibling;}varviewBoxRect;varviewBoxTransform;if(viewBox){varviewBoxArr=trim(viewBox).split(DILIMITER_REG);// Some invalid case like viewBox: 'none'.if(viewBoxArr.length>=4){viewBoxRect={x:parseFloat(viewBoxArr[0]||0),y:parseFloat(viewBoxArr[1]||0),width:parseFloat(viewBoxArr[2]),height:parseFloat(viewBoxArr[3])};}}if(viewBoxRect&&width!=null&&height!=null){viewBoxTransform=makeViewBoxTransform(viewBoxRect,width,height);if(!opt.ignoreViewBox){// If set transform on the output group, it probably bring trouble when// some users only intend to show the clipped content inside the viewBox,// but not intend to transform the output group. So we keep the output// group no transform. If the user intend to use the viewBox as a// camera, just set `opt.ignoreViewBox` as `true` and set transfrom// manually according to the viewBox info in the output of this method.varelRoot=root;root=newGroup();root.add(elRoot);elRoot.scale=viewBoxTransform.scale.slice();elRoot.position=viewBoxTransform.position.slice();}}// Some shapes might be overflow the viewport, which should be// clipped despite whether the viewBox is used, as the SVG does.if(!opt.ignoreRootClip&&width!=null&&height!=null){root.setClipPath(newRect({shape:{x:0,y:0,width:width,height:height}}));}// Set width/height on group just for output the viewport size.return{root:root,width:width,height:height,viewBoxRect:viewBoxRect,viewBoxTransform:viewBoxTransform};};SVGParser.prototype._parseNode=function(xmlNode,parentGroup){varnodeName=xmlNode.nodeName.toLowerCase();// TODO// support <style>...</style> in svg, where nodeName is 'style',// CSS classes is defined globally wherever the style tags are declared.if(nodeName==='defs'){// define flagthis._isDefine=true;}elseif(nodeName==='text'){this._isText=true;}varel;if(this._isDefine){varparser=defineParsers[nodeName];if(parser){vardef=parser.call(this,xmlNode);varid=xmlNode.getAttribute('id');if(id){this._defs[id]=def;}}}else{varparser=nodeParsers[nodeName];if(parser){el=parser.call(this,xmlNode,parentGroup);parentGroup.add(el);}}varchild=xmlNode.firstChild;while(child){if(child.nodeType===1){this._parseNode(child,el);}// Is textif(child.nodeType===3&&this._isText){this._parseText(child,el);}child=child.nextSibling;}// Quit defineif(nodeName==='defs'){this._isDefine=false;}elseif(nodeName==='text'){this._isText=false;}};SVGParser.prototype._parseText=function(xmlNode,parentGroup){if(xmlNode.nodeType===1){vardx=xmlNode.getAttribute('dx')||0;vardy=xmlNode.getAttribute('dy')||0;this._textX+=parseFloat(dx);this._textY+=parseFloat(dy);}vartext=newText({style:{text:xmlNode.textContent,transformText:true},position:[this._textX||0,this._textY||0]});inheritStyle(parentGroup,text);parseAttributes(xmlNode,text,this._defs);varfontSize=text.style.fontSize;if(fontSize&&fontSize<9){// PENDINGtext.style.fontSize=9;text.scale=text.scale||[1,1];text.scale[0]*=fontSize/9;text.scale[1]*=fontSize/9;}varrect=text.getBoundingRect();this._textX+=rect.width;parentGroup.add(text);returntext;};varnodeParsers={'g':function(xmlNode,parentGroup){varg=newGroup();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);returng;},'rect':function(xmlNode,parentGroup){varrect=newRect();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'));// console.log(rect.transform);returnrect;},'circle':function(xmlNode,parentGroup){varcircle=newCircle();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)});returncircle;},'line':function(xmlNode,parentGroup){varline=newLine();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)});returnline;},'ellipse':function(xmlNode,parentGroup){varellipse=newEllipse();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)});returnellipse;},'polygon':function(xmlNode,parentGroup){varpoints=xmlNode.getAttribute('points');if(points){points=parsePoints(points);}varpolygon=newPolygon({shape:{points:points||[]}});inheritStyle(parentGroup,polygon);parseAttributes(xmlNode,polygon,this._defs);returnpolygon;},'polyline':function(xmlNode,parentGroup){varpath=newPath();inheritStyle(parentGroup,path);parseAttributes(xmlNode,path,this._defs);varpoints=xmlNode.getAttribute('points');if(points){points=parsePoints(points);}varpolyline=newPolyline({shape:{points:points||[]}});returnpolyline;},'image':function(xmlNode,parentGroup){varimg=newZImage();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')});returnimg;},'text':function(xmlNode,parentGroup){varx=xmlNode.getAttribute('x')||0;vary=xmlNode.getAttribute('y')||0;vardx=xmlNode.getAttribute('dx')||0;vardy=xmlNode.getAttribute('dy')||0;this._textX=parseFloat(x)+parseFloat(dx);this._textY=parseFloat(y)+parseFloat(dy);varg=newGroup();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);returng;},'tspan':function(xmlNode,parentGroup){varx=xmlNode.getAttribute('x');vary=xmlNode.getAttribute('y');if(x!=null){// new offset xthis._textX=parseFloat(x);}if(y!=null){// new offset ythis._textY=parseFloat(y);}vardx=xmlNode.getAttribute('dx')||0;vardy=xmlNode.getAttribute('dy')||0;varg=newGroup();inheritStyle(parentGroup,g);parseAttributes(xmlNode,g,this._defs);this._textX+=dx;this._textY+=dy;returng;},'path':function(xmlNode,parentGroup){// TODO svg fill rule// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule// path.style.globalCompositeOperation = 'xor';vard=xmlNode.getAttribute('d')||'';// Performance sensitive.varpath=createFromString(d);inheritStyle(parentGroup,path);parseAttributes(xmlNode,path,this._defs);returnpath;}};vardefineParsers={'lineargradient':function(xmlNode){varx1=parseInt(xmlNode.getAttribute('x1')||0,10);vary1=parseInt(xmlNode.getAttribute('y1')||0,10);varx2=parseInt(xmlNode.getAttribute('x2')||10,10);vary2=parseInt(xmlNode.getAttribute('y2')||0,10);vargradient=newLinearGradient(x1,y1,x2,y2);_parseGradientColorStops(xmlNode,gradient);returngradient;},'radialgradient':function(xmlNode){}};function_parseGradientColorStops(xmlNode,gradient){varstop=xmlNode.firstChild;while(stop){if(stop.nodeType===1){varoffset=stop.getAttribute('offset');if(offset.indexOf('%')>0){// percentageoffset=parseInt(offset,10)/100;}elseif(offset){// number from 0 to 1offset=parseFloat(offset);}else{offset=0;}varstopColor=stop.getAttribute('stop-color')||'#000000';gradient.addColorStop(offset,stopColor);}stop=stop.nextSibling;}}functioninheritStyle(parent,child){if(parent&&parent.__inheritedStyle){if(!child.__inheritedStyle){child.__inheritedStyle={};}defaults(child.__inheritedStyle,parent.__inheritedStyle);}}functionparsePoints(pointsString){varlist=trim(pointsString).split(DILIMITER_REG);varpoints=[];for(vari=0;i<list.length;i+=2){varx=parseFloat(list[i]);vary=parseFloat(list[i+1]);points.push([x,y]);}returnpoints;}varattributesMap={'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'};functionparseAttributes(xmlNode,el,defs,onlyInlineStyle){varzrStyle=el.__inheritedStyle||{};varisTextEl=el.type==='text';// TODO Shadowif(xmlNode.nodeType===1){parseTransformAttribute(xmlNode,el);extend(zrStyle,parseStyleAttribute(xmlNode));if(!onlyInlineStyle){for(varsvgAttrNameinattributesMap){if(attributesMap.hasOwnProperty(svgAttrName)){varattrValue=xmlNode.getAttribute(svgAttrName);if(attrValue!=null){zrStyle[attributesMap[svgAttrName]]=attrValue;}}}}}varelFillProp=isTextEl?'textFill':'fill';varelStrokeProp=isTextEl?'textStroke':'stroke';el.style=el.style||newStyle();varelStyle=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){varelPropName=(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 strokeel[elStrokeProp]=true;}el.__inheritedStyle=zrStyle;}varurlRegex=/url\(\s*#(.*?)\)/;functiongetPaint(str,defs){// if (str === 'none') {// return;// }varurlMatch=defs&&str&&str.match(urlRegex);if(urlMatch){varurl=trim(urlMatch[1]);vardef=defs[url];returndef;}returnstr;}vartransformRegex=/(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g;functionparseTransformAttribute(xmlNode,node){vartransform=xmlNode.getAttribute('transform');if(transform){transform=transform.replace(/,/g,' ');varm=null;vartransformOps=[];transform.replace(transformRegex,function(str,type,value){transformOps.push(type,value);});for(vari=transformOps.length-1;i>0;i-=2){varvalue=transformOps[i];vartype=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':varvalue=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.varstyleRegex=/([^\s:;]+)\s*:\s*([^:;]+)/g;functionparseStyleAttribute(xmlNode){varstyle=xmlNode.getAttribute('style');varresult={};if(!style){returnresult;}varstyleList={};styleRegex.lastIndex=0;varstyleRegResult;while((styleRegResult=styleRegex.exec(style))!=null){styleList[styleRegResult[1]]=styleRegResult[2];}for(varsvgAttrNameinattributesMap){if(attributesMap.hasOwnProperty(svgAttrName)&&styleList[svgAttrName]!=null){result[attributesMap[svgAttrName]]=styleList[svgAttrName];}}returnresult;}/** * @param {Array.<number>} viewBoxRect * @param {number} width * @param {number} height * @return {Object} {scale, position} */functionmakeViewBoxTransform(viewBoxRect,width,height){varscaleX=width/viewBoxRect.width;varscaleY=height/viewBoxRect.height;varscale=Math.min(scaleX,scaleY);// preserveAspectRatio 'xMidYMid'varviewBoxScale=[scale,scale];varviewBoxPosition=[-(viewBoxRect.x+viewBoxRect.width/2)*scale+width/2,-(viewBoxRect.y+viewBoxRect.height/2)*scale+height/2];return{scale:viewBoxScale,position:viewBoxPosition};}/** * @param {string|XMLElement} xml * @param {Object} [opt] * @param {number} [opt.width] Default width if svg width not specified or is a percent value. * @param {number} [opt.height] Default height if svg height not specified or is a percent value. * @param {boolean} [opt.ignoreViewBox] * @param {boolean} [opt.ignoreRootClip] * @return {Object} result: * { * root: Group, The root of the the result tree of zrender shapes, * width: number, the viewport width of the SVG, * height: number, the viewport height of the SVG, * viewBoxRect: {x, y, width, height}, the declared viewBox rect of the SVG, if exists, * viewBoxTransform: the {scale, position} calculated by viewBox and viewport, is exists. * } *//**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var storage = createHashMap();//Forminimizethecodesizeofcommonechartspackage,// do not put too much logic in this module.varmapDataStorage={// The format of record: see `echarts.registerMap`.// Compatible with previous `echarts.registerMap`.registerMap:function(mapName,rawGeoJson,rawSpecialAreas){varrecords;if(isArray(rawGeoJson)){records=rawGeoJson;}elseif(rawGeoJson.svg){records=[{type:'svg',source:rawGeoJson.svg,specialAreas:rawGeoJson.specialAreas}];}else{// Backward compatibility.if(rawGeoJson.geoJson&&!rawGeoJson.features){rawSpecialAreas=rawGeoJson.specialAreas;rawGeoJson=rawGeoJson.geoJson;}records=[{type:'geoJSON',source:rawGeoJson,specialAreas:rawSpecialAreas}];}each$1(records,function(record){vartype=record.type;type==='geoJson'&&(type=record.type='geoJSON');varparse=parsers[type];if(__DEV__){assert$1(parse,'Illegal map type: '+type);}parse(record);});returnstorage.set(mapName,records);},retrieveMap:function(mapName){returnstorage.get(mapName);}};varparsers={geoJSON:function(record){varsource=record.source;record.geoJSON=!isString(source)?source:(typeofJSON!=='undefined'&&JSON.parse)?JSON.parse(source):(newFunction('return ('+source+');'))();},// Only perform parse to XML object here, which might be time// consiming for large SVG.// Although convert XML to zrender element is also time consiming,// if we do it here, the clone of zrender elements has to be// required. So we do it once for each geo instance, util real// performance issues call for optimizing it.svg:function(record){record.svgXML=parseXML(record.source);}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var assert = assert$1;var each = each$1;var isFunction = isFunction$1;var isObject = isObject$1;var parseClassType = ComponentModel.parseClassType;var version = '4.2.0';var dependencies = { zrender: '4.0.5'};var TEST_FRAME_REMAIN_TIME = 1;var PRIORITY_PROCESSOR_FILTER = 1000;var PRIORITY_PROCESSOR_STATISTIC = 5000;var PRIORITY_VISUAL_LAYOUT = 1000;var PRIORITY_VISUAL_GLOBAL = 2000;var PRIORITY_VISUAL_CHART = 3000;var PRIORITY_VISUAL_COMPONENT = 4000;//FIXME// necessary?varPRIORITY_VISUAL_BRUSH=5000;varPRIORITY={PROCESSOR:{FILTER:PRIORITY_PROCESSOR_FILTER,STATISTIC:PRIORITY_PROCESSOR_STATISTIC},VISUAL:{LAYOUT:PRIORITY_VISUAL_LAYOUT,GLOBAL:PRIORITY_VISUAL_GLOBAL,CHART:PRIORITY_VISUAL_CHART,COMPONENT:PRIORITY_VISUAL_COMPONENT,BRUSH:PRIORITY_VISUAL_BRUSH}};// Main process have three entries: `setOption`, `dispatchAction` and `resize`,// where they must not be invoked nestedly, except the only case: invoke// dispatchAction with updateMethod "none" in main process.// This flag is used to carry out this rule.// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).varIN_MAIN_PROCESS='__flagInMainProcess';varOPTION_UPDATED='__optionUpdated';varACTION_REG=/^[a-zA-Z0-9_]+$/;functioncreateRegisterEventWithLowercaseName(method){returnfunction(eventName,handler,context){// Event name is all lowercaseeventName=eventName&&eventName.toLowerCase();Eventful.prototype[method].call(this,eventName,handler,context);};}/** * @module echarts~MessageCenter */functionMessageCenter(){Eventful.call(this);}MessageCenter.prototype.on=createRegisterEventWithLowercaseName('on');MessageCenter.prototype.off=createRegisterEventWithLowercaseName('off');MessageCenter.prototype.one=createRegisterEventWithLowercaseName('one');mixin(MessageCenter,Eventful);/** * @module echarts~ECharts */functionECharts(dom,theme$$1,opts){opts=opts||{};// Get theme by nameif(typeoftheme$$1==='string'){theme$$1=themeStorage[theme$$1];}/** * @type {string} */this.id;/** * Group id * @type {string} */this.group;/** * @type {HTMLElement} * @private */this._dom=dom;vardefaultRenderer='canvas';if(__DEV__){defaultRenderer=(typeofwindow==='undefined'?global:window).__ECHARTS__DEFAULT__RENDERER__||defaultRenderer;}/** * @type {module:zrender/ZRender}*@private*/ var zr = this._zr = init$1(dom, { renderer: opts.renderer || defaultRenderer, devicePixelRatio: opts.devicePixelRatio, width: opts.width, height: opts.height }); /***Expect60pfs.*@type{Function}*@private*/ this._throttledZrFlush = throttle(bind(zr.flush, zr), 17); var theme$$1 = clone(theme$$1); theme$$1 && backwardCompat(theme$$1, true); /***@type{Object}*@private*/ this._theme = theme$$1; /***@type{Array.<module:echarts/view/Chart>}*@private*/ this._chartsViews = []; /***@type{Object.<string,module:echarts/view/Chart>}*@private*/ this._chartsMap = {}; /***@type{Array.<module:echarts/view/Component>}*@private*/ this._componentsViews = []; /***@type{Object.<string,module:echarts/view/Component>}*@private*/ this._componentsMap = {}; /***@type{module:echarts/CoordinateSystem}*@private*/ this._coordSysMgr = new CoordinateSystemManager(); /***@type{module:echarts/ExtensionAPI}*@private*/ var api = this._api = createExtensionAPI(this); //SortondemandfunctionprioritySortFunc(a,b){returna.__prio-b.__prio;}sort(visualFuncs,prioritySortFunc);sort(dataProcessorFuncs,prioritySortFunc);/** * @type {module:echarts/stream/Scheduler}*/ this._scheduler = new Scheduler(this, api, dataProcessorFuncs, visualFuncs); Eventful.call(this, this._ecEventProcessor = new EventProcessor()); /***@type{module:echarts~MessageCenter}*@private*/ this._messageCenter = new MessageCenter(); //Initmouseeventsthis._initEvents();// In case some people write `window.onresize = chart.resize`this.resize=bind(this.resize,this);// Can't dispatch action during rendering procedurethis._pendingActions=[];zr.animation.on('frame',this._onframe,this);bindRenderedEvent(zr,this);// ECharts instance can be used as value.setAsPrimitive(this);}varechartsProto=ECharts.prototype;echartsProto._onframe=function(){if(this._disposed){return;}varscheduler=this._scheduler;// Lazy updateif(this[OPTION_UPDATED]){varsilent=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.elseif(scheduler.unfinished){// Stream progress.varremainTime=TEST_FRAME_REMAIN_TIME;varecModel=this._model;varapi=this._api;scheduler.unfinished=false;do{varstartTime=+newDate();scheduler.performSeriesTasks(ecModel);// Currently dataProcessorFuncs do not check threshold.scheduler.performDataProcessorTasks(ecModel);updateStreamModes(this,ecModel);// Do not update coordinate system here. Because that coord system update in// each frame is not a good user experience. So we follow the rule that// the extent of the coordinate system is determin in the first frame (the// frame is executed immedietely after task reset.// this._coordSysMgr.update(ecModel, api);// console.log('--- ec frame visual ---', remainTime);scheduler.performVisualTasks(ecModel);renderSeries(this,this._model,api,'remain');remainTime-=(+newDate()-startTime);}while(remainTime>0&&scheduler.unfinished);// Call flush explicitly for trigger finished event.if(!scheduler.unfinished){this._zr.flush();}// Else, zr flushing be ensue within the same frame,// because zr flushing is after onframe event.}};/** * @return {HTMLElement} */echartsProto.getDom=function(){returnthis._dom;};/** * @return {module:zrender~ZRender} */echartsProto.getZr=function(){returnthis._zr;};/** * Usage: * chart.setOption(option, notMerge, lazyUpdate); * chart.setOption(option, { * notMerge: ..., * lazyUpdate: ..., * silent: ... * }); * * @param {Object} option * @param {Object|boolean} [opts] opts or notMerge. * @param {boolean} [opts.notMerge=false] * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently. */echartsProto.setOption=function(option,notMerge,lazyUpdate){if(__DEV__){assert(!this[IN_MAIN_PROCESS],'`setOption` should not be called during main process.');}varsilent;if(isObject(notMerge)){lazyUpdate=notMerge.lazyUpdate;silent=notMerge.silent;notMerge=notMerge.notMerge;}this[IN_MAIN_PROCESS]=true;if(!this._model||notMerge){varoptionManager=newOptionManager(this._api);vartheme$$1=this._theme;varecModel=this._model=newGlobalModel(null,null,theme$$1,optionManager);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// fetched after `setOption`.this._zr.flush();this[OPTION_UPDATED]=false;this[IN_MAIN_PROCESS]=false;flushPendingActions.call(this,silent);triggerUpdatedEvent.call(this,silent);}};/** * @DEPRECATED */echartsProto.setTheme=function(){console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');};/** * @return {module:echarts/model/Global}*/echartsProto.getModel = function () { return this._model;};/***@return{Object}*/echartsProto.getOption = function () { return this._model && this._model.getOption();};/***@return{number}*/echartsProto.getWidth = function () { return this._zr.getWidth();};/***@return{number}*/echartsProto.getHeight = function () { return this._zr.getHeight();};/***@return{number}*/echartsProto.getDevicePixelRatio = function () { return this._zr.painter.dpr || window.devicePixelRatio || 1;};/***Getcanvaswhichhasallthingrendered*@param{Object}opts*@param{string}[opts.backgroundColor]*@return{string}*/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; //varlist=zr.storage.getDisplayList();// Stop animations// Never works before in init animation, so remove it.// zrUtil.each(list, function (el) {// el.stopAnimation(true);// });returnzr.painter.getRenderedCanvas(opts);};/** * Get svg data url * @return {string} */echartsProto.getSvgDataUrl=function(){if(!env$1.svgSupported){return;}varzr=this._zr;varlist=zr.storage.getDisplayList();// Stop animationseach$1(list,function(el){el.stopAnimation(true);});returnzr.painter.pathToDataUrl();};/** * @return {string} * @param {Object} opts * @param {string} [opts.type='png'] * @param {string} [opts.pixelRatio=1] * @param {string} [opts.backgroundColor] * @param {string} [opts.excludeComponents] */echartsProto.getDataURL=function(opts){opts=opts||{};varexcludeComponents=opts.excludeComponents;varecModel=this._model;varexcludesComponentViews=[];varself=this;each(excludeComponents,function(componentType){ecModel.eachComponent({mainType:componentType},function(component){varview=self._componentsMap[component.__viewId];if(!view.group.ignore){excludesComponentViews.push(view);view.group.ignore=true;}});});varurl=this._zr.painter.getType()==='svg'?this.getSvgDataUrl():this.getRenderedCanvas(opts).toDataURL('image/'+(opts&&opts.type||'png'));each(excludesComponentViews,function(view){view.group.ignore=false;});returnurl;};/** * @return {string} * @param {Object} opts * @param {string} [opts.type='png'] * @param {string} [opts.pixelRatio=1] * @param {string} [opts.backgroundColor] */echartsProto.getConnectedDataURL=function(opts){if(!env$1.canvasSupported){return;}vargroupId=this.group;varmathMin=Math.min;varmathMax=Math.max;varMAX_NUMBER=Infinity;if(connectedGroups[groupId]){varleft=MAX_NUMBER;vartop=MAX_NUMBER;varright=-MAX_NUMBER;varbottom=-MAX_NUMBER;varcanvasList=[];vardpr=(opts&&opts.pixelRatio)||1;each$1(instances,function(chart,id){if(chart.group===groupId){varcanvas=chart.getRenderedCanvas(clone(opts));varboundingRect=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;varwidth=right-left;varheight=bottom-top;vartargetCanvas=createCanvas();targetCanvas.width=width;targetCanvas.height=height;varzr=init$1(targetCanvas);each(canvasList,function(item){varimg=newZImage({style:{x:item.left*dpr-left,y:item.top*dpr-top,image:item.dom}});zr.add(img);});zr.refreshImmediately();returntargetCanvas.toDataURL('image/'+(opts&&opts.type||'png'));}else{returnthis.getDataURL(opts);}};/** * Convert from logical coordinate system to pixel coordinate system. * See CoordinateSystem#convertToPixel. * @param {string|Object} finder * If string, e.g., 'geo', means {geoIndex: 0}. * If Object, could contain some of these properties below: * { * seriesIndex /seriesId/seriesName,*geoIndex/geoId,geoName,*bmapIndex/bmapId/bmapName,*xAxisIndex/xAxisId/xAxisName,*yAxisIndex/yAxisId/yAxisName,*gridIndex/gridId/gridName,*...(canbeextended)*}*@param{Array|number}value*@return{Array|number}result*/echartsProto.convertToPixel = curry(doConvertPixel, 'convertToPixel');/***Convertfrompixelcoordinatesystemtologicalcoordinatesystem.*SeeCoordinateSystem#convertFromPixel.*@param{string|Object}finder*Ifstring,e.g.,'geo',means{geoIndex:0}.*IfObject,couldcontainsomeofthesepropertiesbelow:*{*seriesIndex/seriesId/seriesName,*geoIndex/geoId/geoName,*bmapIndex/bmapId/bmapName,*xAxisIndex/xAxisId/xAxisName,*yAxisIndex/yAxisId/yAxisName*gridIndex/gridId/gridName,*...(canbeextended)*}*@param{Array|number}value*@return{Array|number}result*/echartsProto.convertFromPixel = curry(doConvertPixel, 'convertFromPixel');function doConvertPixel(methodName, finder, value) { 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.'); }}/***Isthespecifiedcoordinatesystemsorcomponentscontainthegivenpixelpoint.*@param{string|Object}finder*Ifstring,e.g.,'geo',means{geoIndex:0}.*IfObject,couldcontainsomeofthesepropertiesbelow:*{*seriesIndex/seriesId/seriesName,*geoIndex/geoId/geoName,*bmapIndex/bmapId/bmapName,*xAxisIndex/xAxisId/xAxisName,*yAxisIndex/yAxisId/yAxisName,*gridIndex/gridId/gridName,*...(canbeextended)*}*@param{Array|number}value*@return{boolean}result*/echartsProto.containPixel = function (finder, value) { 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;};/***Getvisualfromseriesordata.*@param{string|Object}finder*Ifstring,e.g.,'series',means{seriesIndex:0}.*IfObject,couldcontainsomeofthesepropertiesbelow:*{*seriesIndex/seriesId/seriesName,*dataIndex/dataIndexInside*}*IfdataIndexisnotspecified,seriesvisualwillbefetched,*butnotdataitemvisual.*IfallofseriesIndex,seriesId,seriesNamearenotspecified,*visualwillbefetchedfromfirstseries.*@param{string}visualType'color','symbol','symbolSize'*/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);};/***Getviewofcorrespondingcomponentmodel*@param{module:echarts/model/Component}componentModel*@return{module:echarts/view/Component}*/echartsProto.getViewOfComponentModel = function (componentModel) { return this._componentsMap[componentModel.__viewId];};/***Getviewofcorrespondingseriesmodel*@param{module:echarts/model/Series}seriesModel*@return{module:echarts/view/Chart}*/echartsProto.getViewOfSeriesModel = function (seriesModel) { return this._chartsMap[seriesModel.__viewId];};var updateMethods = { prepareAndUpdate: function (payload) { prepare(this); updateMethods.update.call(this, payload); }, /***@param{Object}payload*@private*/ update: function (payload) { //console.profile&&console.profile('update');varecModel=this._model;varapi=this._api;varzr=this._zr;varcoordSysMgr=this._coordSysMgr;varscheduler=this._scheduler;// update before setOptionif(!ecModel){return;}scheduler.restoreData(ecModel,payload);scheduler.performSeriesTasks(ecModel);// TODO// Save total ecModel here for undo/redo (after restoring data and before processing data).// Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.// Create new coordinate system each update// In LineView may save the old coordinate system and use it to get the orignal pointcoordSysMgr.create(ecModel,api);scheduler.performDataProcessorTasks(ecModel,payload);// Current stream render is not supported in data process. So we can update// stream modes after data processing, where the filtered data is used to// deteming whether use progressive rendering.updateStreamModes(this,ecModel);// We update stream modes before coordinate system updated, then the modes info// can be fetched when coord sys updating (consider the barGrid extent fix). But// the drawback is the full coord info can not be fetched. Fortunately this full// coord is not requied in stream mode updater currently.coordSysMgr.update(ecModel,api);clearColorPalette(ecModel);scheduler.performVisualTasks(ecModel,payload);render(this,ecModel,api,payload);// Set backgroundvarbackgroundColor=ecModel.get('backgroundColor')||'transparent';// In IE8if(!env$1.canvasSupported){varcolorArr=parse(backgroundColor);backgroundColor=stringify(colorArr,'rgb');if(colorArr[3]===0){backgroundColor='transparent';}}else{zr.setBackgroundColor(backgroundColor);}performPostUpdateFuncs(ecModel,api);// console.profile && console.profileEnd('update');},/** * @param {Object} payload * @private */updateTransform:function(payload){varecModel=this._model;varecIns=this;varapi=this._api;// update before setOptionif(!ecModel){return;}// ChartView.markUpdateMethod(payload, 'updateTransform');varcomponentDirtyList=[];ecModel.eachComponent(function(componentType,componentModel){varcomponentView=ecIns.getViewOfComponentModel(componentModel);if(componentView&&componentView.__alive){if(componentView.updateTransform){varresult=componentView.updateTransform(componentModel,ecModel,api,payload);result&&result.update&&componentDirtyList.push(componentView);}else{componentDirtyList.push(componentView);}}});varseriesDirtyMap=createHashMap();ecModel.eachSeries(function(seriesModel){varchartView=ecIns._chartsMap[seriesModel.__viewId];if(chartView.updateTransform){varresult=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.// this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);this._scheduler.performVisualTasks(ecModel,payload,{setDirty:true,dirtyMap:seriesDirtyMap});// Currently, not call render of components. Geo render cost a lot.// renderComponents(ecIns, ecModel, api, payload, componentDirtyList);renderSeries(ecIns,ecModel,api,payload,seriesDirtyMap);performPostUpdateFuncs(ecModel,this._api);},/** * @param {Object} payload * @private */updateView:function(payload){varecModel=this._model;// update before setOptionif(!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.this._scheduler.performVisualTasks(ecModel,payload,{setDirty:true});render(this,this._model,this._api,payload);performPostUpdateFuncs(ecModel,this._api);},/** * @param {Object} payload * @private */updateVisual:function(payload){updateMethods.update.call(this,payload);// var ecModel = this._model;// // update before setOption// if (!ecModel) {// return;// }// ChartView.markUpdateMethod(payload, 'updateVisual');// clearColorPalette(ecModel);// // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.// this._scheduler.performVisualTasks(ecModel, payload, {visualType: 'visual', setDirty: true});// render(this, this._model, this._api, payload);// performPostUpdateFuncs(ecModel, this._api);},/** * @param {Object} payload * @private */updateLayout:function(payload){updateMethods.update.call(this,payload);// var ecModel = this._model;// // update before setOption// if (!ecModel) {// return;// }// ChartView.markUpdateMethod(payload, 'updateLayout');// // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.// // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);// this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true});// render(this, this._model, this._api, payload);// performPostUpdateFuncs(ecModel, this._api);}};functionprepare(ecIns){varecModel=ecIns._model;varscheduler=ecIns._scheduler;scheduler.restorePipelines(ecModel);scheduler.prepareStageTasks();prepareView(ecIns,'component',ecModel,scheduler);prepareView(ecIns,'chart',ecModel,scheduler);scheduler.plan();}/** * @private */functionupdateDirectly(ecIns,method,payload,mainType,subType){varecModel=ecIns._model;// broadcastif(!mainType){// FIXME// Chart will not be update directly here, except set dirty.// But there is no such scenario now.each(ecIns._componentsViews.concat(ecIns._chartsViews),callView);return;}varquery={};query[mainType+'Id']=payload[mainType+'Id'];query[mainType+'Index']=payload[mainType+'Index'];query[mainType+'Name']=payload[mainType+'Name'];varcondition={mainType:mainType,query:query};subType&&(condition.subType=subType);// subType may be '' by parseClassType;varexcludeSeriesId=payload.excludeSeriesId;if(excludeSeriesId!=null){excludeSeriesId=createHashMap(normalizeToArray(excludeSeriesId));}// If dispatchAction before setOption, do nothing.ecModel&&ecModel.eachComponent(condition,function(model){if(!excludeSeriesId||excludeSeriesId.get(model.id)==null){callView(ecIns[mainType==='series'?'_chartsMap':'_componentsMap'][model.__viewId]);}},ecIns);functioncallView(view){view&&view.__alive&&view[method]&&view[method](view.__model,ecModel,ecIns._api,payload);}}/** * Resize the chart * @param {Object} opts * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)*@param{number}[opts.height]Canbe'auto'(thesameasnull/undefined)*@param{boolean}[opts.silent=false]*/echartsProto.resize = function (opts) { if (__DEV__) { assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.'); } this._zr.resize(opts); var ecModel = this._model; //Resizeloadingeffectthis._loadingFX&&this._loadingFX.resize();if(!ecModel){return;}varoptionChanged=ecModel.resetOption('media');varsilent=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);};functionupdateStreamModes(ecIns,ecModel){varchartsMap=ecIns._chartsMap;varscheduler=ecIns._scheduler;ecModel.eachSeries(function(seriesModel){scheduler.updateStreamModes(seriesModel,chartsMap[seriesModel.__viewId]);});}/** * Show loading effect * @param {string} [name='default'] * @param {Object} [cfg] */echartsProto.showLoading=function(name,cfg){if(isObject(name)){cfg=name;name='';}name=name||'default';this.hideLoading();if(!loadingEffects[name]){if(__DEV__){console.warn('Loading effects '+name+' not exists.');}return;}varel=loadingEffects[name](this._api,cfg);varzr=this._zr;this._loadingFX=el;zr.add(el);};/** * Hide loading effect */echartsProto.hideLoading=function(){this._loadingFX&&this._zr.remove(this._loadingFX);this._loadingFX=null;};/** * @param {Object} eventObj * @return {Object} */echartsProto.makeActionFromEvent=function(eventObj){varpayload=extend({},eventObj);payload.type=eventActionMap[eventObj.type];returnpayload;};/** * @pubilc * @param {Object} payload * @param {string} [payload.type] Action type * @param {Object|boolean} [opt] If pass boolean, means opt.silent * @param {boolean} [opt.silent=false] Whether trigger events. * @param {boolean} [opt.flush=undefined] * true: Flush immediately, and then pixel in canvas can be fetched * immediately. Caution: it might affect performance. * false: Not not flush. * undefined: Auto decide whether perform flush. */echartsProto.dispatchAction=function(payload,opt){if(!isObject(opt)){opt={silent:!!opt};}if(!actions[payload.type]){return;}// Avoid dispatch action before setOption. Especially in `connect`.if(!this._model){return;}// May dispatchAction in rendering procedureif(this[IN_MAIN_PROCESS]){this._pendingActions.push(payload);return;}doDispatchAction.call(this,payload,opt.silent);if(opt.flush){this._zr.flush(true);}elseif(opt.flush!==false&&env$1.browser.weChat){// In WeChat embeded browser, `requestAnimationFrame` and `setInterval`// hang when sliding page (on touch event), which cause that zr does not// refresh util user interaction finished, which is not expected.// But `dispatchAction` may be called too frequently when pan on touch// screen, which impacts performance if do not throttle them.this._throttledZrFlush();}flushPendingActions.call(this,opt.silent);triggerUpdatedEvent.call(this,opt.silent);};functiondoDispatchAction(payload,silent){varpayloadType=payload.type;varescapeConnect=payload.escapeConnect;varactionWrap=actions[payloadType];varactionInfo=actionWrap.actionInfo;varcptType=(actionInfo.update||'update').split(':');varupdateMethod=cptType.pop();cptType=cptType[0]!=null&&parseClassType(cptType[0]);this[IN_MAIN_PROCESS]=true;varpayloads=[payload];varbatched=false;// Batch actionif(payload.batch){batched=true;payloads=map(payload.batch,function(item){item=defaults(extend({},item),payload);item.batch=null;returnitem;});}vareventObjBatch=[];vareventObj;varisHighDown=payloadType==='highlight'||payloadType==='downplay';each(payloads,function(batchItem){// Action can specify the event by return it.eventObj=actionWrap.action(batchItem,this._model,this._api);// Emit event outsideeventObj=eventObj||extend({},batchItem);// Convert type to eventTypeeventObj.type=actionInfo.event||eventObj.type;eventObjBatch.push(eventObj);// light update does not perform data process, layout and visual.if(isHighDown){// method, payload, mainType, subTypeupdateDirectly(this,updateMethod,batchItem,'series');}elseif(cptType){updateDirectly(this,updateMethod,batchItem,cptType.main,cptType.sub);}},this);if(updateMethod!=='none'&&!isHighDown&&!cptType){// Still dirtyif(this[OPTION_UPDATED]){// FIXME Pass payload ?prepare(this);updateMethods.update.call(this,payload);this[OPTION_UPDATED]=false;}else{updateMethods[updateMethod].call(this,payload);}}// Follow the rule of action batchif(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);}functionflushPendingActions(silent){varpendingActions=this._pendingActions;while(pendingActions.length){varpayload=pendingActions.shift();doDispatchAction.call(this,payload,silent);}}functiontriggerUpdatedEvent(silent){!silent&&this.trigger('updated');}/** * Event `rendered` is triggered when zr * rendered. It is useful for realtime * snapshot (reflect animation). * * Event `finished` is triggered when: * (1) zrender rendering finished. * (2) initial animation finished. * (3) progressive rendering finished. * (4) no pending action. * (5) no delayed setOption needs to be processed. */functionbindRenderedEvent(zr,ecIns){zr.on('rendered',function(){ecIns.trigger('rendered');// The `finished` event should not be triggered repeatly,// so it should only be triggered when rendering indeed happend// in zrender. (Consider the case that dipatchAction is keep// triggering when mouse move).if(// Although zr is dirty if initial animation is not finished// and this checking is called on frame, we also check// animation finished for robustness.zr.animation.isFinished()&&!ecIns[OPTION_UPDATED]&&!ecIns._scheduler.unfinished&&!ecIns._pendingActions.length){ecIns.trigger('finished');}});}/** * @param {Object} params * @param {number} params.seriesIndex * @param {Array|TypedArray} params.data */echartsProto.appendData=function(params){varseriesIndex=params.seriesIndex;varecModel=this.getModel();varseriesModel=ecModel.getSeriesByIndex(seriesIndex);if(__DEV__){assert(params.data&&seriesModel);}seriesModel.appendData(params);// Note: `appendData` does not support that update extent of coordinate// system, util some scenario require that. In the expected usage of// `appendData`, the initial extent of coordinate system should better// be fixed by axis `min`/`max` setting or initial data, otherwise if// the extent changed while `appendData`, the location of the painted// graphic elements have to be changed, which make the usage of// `appendData` meaningless.this._scheduler.unfinished=true;};/** * Register event * @method */echartsProto.on=createRegisterEventWithLowercaseName('on');echartsProto.off=createRegisterEventWithLowercaseName('off');echartsProto.one=createRegisterEventWithLowercaseName('one');/** * Prepare view instances of charts and components * @param {module:echarts/model/Global}ecModel*@private*/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:idsameandtypechanged.varviewId='_ec_'+model.id+'_'+model.type;varview=viewMap[viewId];if(!view){varclassType=parseClassType(model.type);varClazz=isComponent?Component.getClass(classType.main,classType.sub):Chart.getClass(classType.sub);if(__DEV__){assert(Clazz,classType.sub+' does not exist.');}view=newClazz();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(vari=0;i<viewList.length;){varview=viewList[i];if(!view.__alive){!isComponent&&view.renderTask.dispose();zr.remove(view.group);view.dispose(ecModel,api);viewList.splice(i,1);deleteviewMap[view.__id];view.__id=view.group.__ecComponentInfo=null;}else{i++;}}}// /**// * Encode visual infomation from data after data processing// *// * @param {module:echarts/model/Global} ecModel// * @param {object} layout// * @param {boolean} [layoutFilter] `true`: only layout,// * `false`: only not layout,// * `null`/`undefined`: all.// * @param {string} taskBaseTag// * @private// */// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {// each(visualFuncs, function (visual, index) {// var isLayout = visual.isLayout;// if (layoutFilter == null// || (layoutFilter === false && !isLayout)// || (layoutFilter === true && isLayout)// ) {// visual.func(ecModel, api, payload);// }// });// }functionclearColorPalette(ecModel){ecModel.clearColorPalette();ecModel.eachSeries(function(seriesModel){seriesModel.clearColorPalette();});}functionrender(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 chartseach(ecIns._chartsViews,function(chart){if(!chart.__alive){chart.remove(ecModel,api);}});}functionrenderComponents(ecIns,ecModel,api,payload,dirtyList){each(dirtyList||ecIns._componentsViews,function(componentView){varcomponentModel=componentView.__model;componentView.render(componentModel,ecModel,api,payload);updateZ(componentModel,componentView);});}/** * Render each chart and component * @private */functionrenderSeries(ecIns,ecModel,api,payload,dirtyMap){// Render all chartsvarscheduler=ecIns._scheduler;varunfinished;ecModel.eachSeries(function(seriesModel){varchartView=ecIns._chartsMap[seriesModel.__viewId];chartView.__alive=true;varrenderTask=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 layerupdateHoverLayerStatus(ecIns._zr,ecModel);// Add ariaaria(ecIns._zr.dom,ecModel);}functionperformPostUpdateFuncs(ecModel,api){each(postUpdateFuncs,function(func){func(ecModel,api);});}varMOUSE_EVENT_NAMES=['click','dblclick','mouseover','mouseout','mousemove','mousedown','mouseup','globalout','contextmenu'];/** * @private */echartsProto._initEvents=function(){each(MOUSE_EVENT_NAMES,function(eveName){this._zr.on(eveName,function(e){varecModel=this.getModel();varel=e.target;varparams;varisGlobalOut=eveName==='globalout';// no e.target when 'globalout'.if(isGlobalOut){params={};}elseif(el&&el.dataIndex!=null){vardataModel=el.dataModel||ecModel.getSeriesByIndex(el.seriesIndex);params=dataModel&&dataModel.getDataParams(el.dataIndex,el.dataType,el)||{};}// If element has custom eventData of componentselseif(el&&el.eventData){params=extend({},el.eventData);}// Contract: if params prepared in mouse event,// these properties must be specified:// {// componentType: string (component main type)// componentIndex: number// }// Otherwise event query can not work.if(params){varcomponentType=params.componentType;varcomponentIndex=params.componentIndex;// Special handling for historic reason: when trigger by// markLine/markPoint/markArea, the componentType is// 'markLine'/'markPoint'/'markArea', but we should better// enable them to be queried by seriesIndex, since their// option is set in each series.if(componentType==='markLine'||componentType==='markPoint'||componentType==='markArea'){componentType='series';componentIndex=params.seriesIndex;}varmodel=componentType&&componentIndex!=null&&ecModel.getComponent(componentType,componentIndex);varview=model&&this[model.mainType==='series'?'_chartsMap':'_componentsMap'][model.__viewId];if(__DEV__){// `event.componentType` and `event[componentTpype + 'Index']` must not// be missed, otherwise there is no way to distinguish source component.// See `dataFormat.getDataParams`.if(!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);}},this);},this);each(eventActionMap,function(actionType,eventType){this._messageCenter.on(eventType,function(event){this.trigger(eventType,event);},this);},this);};/** * @return {boolean} */echartsProto.isDisposed=function(){returnthis._disposed;};/** * Clear */echartsProto.clear=function(){this.setOption({series:[]},true);};/** * Dispose instance */echartsProto.dispose=function(){if(this._disposed){if(__DEV__){console.warn('Instance '+this.id+' has been disposed');}return;}this._disposed=true;setAttribute(this.getDom(),DOM_ATTRIBUTE_KEY,'');varapi=this._api;varecModel=this._model;each(this._componentsViews,function(component){component.dispose(ecModel,api);});each(this._chartsViews,function(chart){chart.dispose(ecModel,api);});// Dispose after all views disposedthis._zr.dispose();deleteinstances[this.id];};mixin(ECharts,Eventful);functionupdateHoverLayerStatus(zr,ecModel){varstorage=zr.storage;varelCount=0;storage.traverse(function(el){if(!el.isGroup){elCount++;}});if(elCount>ecModel.get('hoverLayerThreshold')&&!env$1.node){storage.traverse(function(el){if(!el.isGroup){// Don't switch back.el.useHoverLayer=true;}});}}/** * Update chart progressive and blend. * @param {module:echarts/model/Series|module:echarts/model/Component}model*@param{module:echarts/view/Component|module:echarts/view/Chart}view*/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) { //FIXMEmarkerandothercomponentsif(!el.isGroup){// Only set if blendMode is changed. In case element is incremental and don't wan't to rerender.if(el.style.blend!==blendMode){el.setStyle('blend',blendMode);}}if(el.eachPendingDisplayable){el.eachPendingDisplayable(function(displayable){displayable.setStyle('blend',blendMode);});}});}/** * @param {module:echarts/model/Series|module:echarts/model/Component}model*@param{module:echarts/view/Component|module:echarts/view/Chart}view*/function updateZ(model, view) { var z = model.get('z'); var zlevel = model.get('zlevel'); //Setzandzlevelview.group.traverse(function(el){if(el.type!=='group'){z!=null&&(el.z=z);zlevel!=null&&(el.zlevel=zlevel);}});}functioncreateExtensionAPI(ecInstance){varcoordSysMgr=ecInstance._coordSysMgr;returnextend(newExtensionAPI(ecInstance),{// Inject methodsgetCoordinateSystems:bind(coordSysMgr.getCoordinateSystems,coordSysMgr),getComponentByElement:function(el){while(el){varmodelInfo=el.__ecComponentInfo;if(modelInfo!=null){returnecInstance._model.getComponent(modelInfo.mainType,modelInfo.index);}el=el.parent;}}});}/** * @class * Usage of query: * `chart.on('click', query, handler);` * The `query` can be: * + The component type query string, only `mainType` or `mainType.subType`, * like: 'xAxis', 'series', 'xAxis.category' or 'series.line'. * + The component query object, like: * `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`, * `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`. * + The data query object, like: * `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`. * + The other query object (cmponent customized query), like: * `{element: 'some'}` (only available in custom series). * * Caveat: If a prop in the `query` object is `null/undefined`,itisthe*sameasthereisnosuchpropinthe`query`object.*/function EventProcessor() { //Theseinforequired:targetEl,packedEvent,model,viewthis.eventInfo;}EventProcessor.prototype={constructor:EventProcessor,normalizeQuery:function(query){varcptQuery={};vardataQuery={};varotherQuery={};// `query` is `mainType` or `mainType.subType` of component.if(isString(query)){varcondCptType=parseClassType(query);// `.main` and `.sub` may be ''.cptQuery.mainType=condCptType.main||null;cptQuery.subType=condCptType.sub||null;}// `query` is an object, convert to {mainType, index, name, id}.else{// `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved,// can not be used in `compomentModel.filterForExposedEvent`.varsuffixes=['Index','Name','Id'];vardataKeys={name:1,dataIndex:1,dataType:1};each$1(query,function(val,key){varreserved=false;for(vari=0;i<suffixes.length;i++){varpropSuffix=suffixes[i];varsuffixPos=key.lastIndexOf(propSuffix);if(suffixPos>0&&suffixPos===key.length-propSuffix.length){varmainType=key.slice(0,suffixPos);// Consider `dataIndex`.if(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(eventType,query,args){// They should be assigned before each trigger call.vareventInfo=this.eventInfo;if(!eventInfo){returntrue;}vartargetEl=eventInfo.targetEl;varpackedEvent=eventInfo.packedEvent;varmodel=eventInfo.model;varview=eventInfo.view;// For event like 'globalout'.if(!model||!view){returntrue;}varcptQuery=query.cptQuery;vardataQuery=query.dataQuery;returncheck(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));functioncheck(query,host,prop,propOnHost){returnquery[prop]==null||host[propOnHost||prop]===query[prop];}},afterTrigger:function(){// Make sure the eventInfo wont be used in next trigger.this.eventInfo=null;}};/** * @type {Object} key: actionType. * @inner */varactions={};/** * Map eventType to actionType * @type {Object} */vareventActionMap={};/** * Data processor functions of each stage * @type {Array.<Object.<string, Function>>} * @inner */vardataProcessorFuncs=[];/** * @type {Array.<Function>} * @inner */varoptionPreprocessorFuncs=[];/** * @type {Array.<Function>} * @inner */varpostUpdateFuncs=[];/** * Visual encoding functions of each stage * @type {Array.<Object.<string, Function>>} */varvisualFuncs=[];/** * Theme storage * @type {Object.<key, Object>} */varthemeStorage={};/** * Loading effects */varloadingEffects={};varinstances={};varconnectedGroups={};varidBase=newDate()-0;vargroupIdBase=newDate()-0;varDOM_ATTRIBUTE_KEY='_echarts_instance_';functionenableConnect(chart){varSTATUS_PENDING=0;varSTATUS_UPDATING=1;varSTATUS_UPDATED=2;varSTATUS_KEY='__connectUpdateStatus';functionupdateConnectedChartsStatus(charts,status){for(vari=0;i<charts.length;i++){varotherChart=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;}varaction=chart.makeActionFromEvent(event);varotherCharts=[];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);}});});}/** * @param {HTMLElement} dom * @param {Object} [theme] * @param {Object} opts * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default * @param {string} [opts.renderer] Currently only 'canvas' is supported. * @param {number} [opts.width] Use clientWidth of the input `dom` by default. * Can be 'auto' (the same as null/undefined)*@param{number}[opts.height]UseclientHeightoftheinput`dom`bydefault.*Canbe'auto'(thesameasnull/undefined)*/function init(dom, theme$$1, opts) { if (__DEV__) { //Checkversionif((version$1.replace('.','')-0)<(dependencies.zrender.replace('.','')-0)){thrownewError('zrender/src '+version$1+' is too old for ECharts '+version+'. Current version need ZRender '+dependencies.zrender+'+');}if(!dom){thrownewError('Initialize failed: invalid dom.');}}varexistInstance=getInstanceByDom(dom);if(existInstance){if(__DEV__){console.warn('There is a chart instance already initialized on the dom.');}returnexistInstance;}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');}}varchart=newECharts(dom,theme$$1,opts);chart.id='ec_'+idBase++;instances[chart.id]=chart;setAttribute(dom,DOM_ATTRIBUTE_KEY,chart.id);enableConnect(chart);returnchart;}/** * @return {string|Array.<module:echarts~ECharts>} groupId */functionconnect(groupId){// Is array of chartsif(isArray(groupId)){varcharts=groupId;groupId=null;// If any chart has groupeach(charts,function(chart){if(chart.group!=null){groupId=chart.group;}});groupId=groupId||('g_'+groupIdBase++);each(charts,function(chart){chart.group=groupId;});}connectedGroups[groupId]=true;returngroupId;}/** * @DEPRECATED * @return {string} groupId */functiondisConnect(groupId){connectedGroups[groupId]=false;}/** * @return {string} groupId */vardisconnect=disConnect;/** * Dispose a chart instance * @param {module:echarts~ECharts|HTMLDomElement|string} chart */functiondispose(chart){if(typeofchart==='string'){chart=instances[chart];}elseif(!(chartinstanceofECharts)){// Try to treat as domchart=getInstanceByDom(chart);}if((chartinstanceofECharts)&&!chart.isDisposed()){chart.dispose();}}/** * @param {HTMLElement} dom * @return {echarts~ECharts} */functiongetInstanceByDom(dom){returninstances[getAttribute(dom,DOM_ATTRIBUTE_KEY)];}/** * @param {string} key * @return {echarts~ECharts} */functiongetInstanceById(key){returninstances[key];}/** * Register theme */functionregisterTheme(name,theme$$1){themeStorage[name]=theme$$1;}/** * Register option preprocessor * @param {Function} preprocessorFunc */functionregisterPreprocessor(preprocessorFunc){optionPreprocessorFuncs.push(preprocessorFunc);}/** * @param {number} [priority=1000] * @param {Object|Function} processor */functionregisterProcessor(priority,processor){normalizeRegister(dataProcessorFuncs,priority,processor,PRIORITY_PROCESSOR_FILTER);}/** * Register postUpdater * @param {Function} postUpdateFunc */functionregisterPostUpdate(postUpdateFunc){postUpdateFuncs.push(postUpdateFunc);}/** * Usage: * registerAction('someAction', 'someEvent', function () { ... }); * registerAction('someAction', function () { ... }); * registerAction( * {type: 'someAction', event: 'someEvent', update: 'updateView'}, * function () { ... } * ); * * @param {(string|Object)} actionInfo * @param {string} actionInfo.type * @param {string} [actionInfo.event] * @param {string} [actionInfo.update] * @param {string} [eventName] * @param {Function} action */functionregisterAction(actionInfo,eventName,action){if(typeofeventName==='function'){action=eventName;eventName='';}varactionType=isObject(actionInfo)?actionInfo.type:([actionInfo,actionInfo={event:eventName}][0]);// Event name is all lowercaseactionInfo.event=(actionInfo.event||actionType).toLowerCase();eventName=actionInfo.event;// Validate action type and event name.assert(ACTION_REG.test(actionType)&&ACTION_REG.test(eventName));if(!actions[actionType]){actions[actionType]={action:action,actionInfo:actionInfo};}eventActionMap[eventName]=actionType;}/** * @param {string} type * @param {*} CoordinateSystem */functionregisterCoordinateSystem(type,CoordinateSystem$$1){CoordinateSystemManager.register(type,CoordinateSystem$$1);}/** * Get dimensions of specified coordinate system. * @param {string} type * @return {Array.<string|Object>} */functiongetCoordinateSystemDimensions(type){varcoordSysCreator=CoordinateSystemManager.get(type);if(coordSysCreator){returncoordSysCreator.getDimensionsInfo?coordSysCreator.getDimensionsInfo():coordSysCreator.dimensions.slice();}}/** * Layout is a special stage of visual encoding * Most visual encoding like color are common for different chart * But each chart has it's own layout algorithm * * @param {number} [priority=1000] * @param {Function} layoutTask */functionregisterLayout(priority,layoutTask){normalizeRegister(visualFuncs,priority,layoutTask,PRIORITY_VISUAL_LAYOUT,'layout');}/** * @param {number} [priority=3000] * @param {module:echarts/stream/Task}visualTask*/function registerVisual(priority, visualTask) { normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');}/***@param{Object|Function}fn:{seriesType,createOnAllSeries,performRawSeries,reset}*/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'); } //Checkduplicateeach(targetList,function(wrap){assert(wrap.__raw!==fn);});}varstageHandler=Scheduler.wrapStageHandler(fn,visualType);stageHandler.__prio=priority;stageHandler.__raw=fn;targetList.push(stageHandler);returnstageHandler;}/** * @param {string} name */functionregisterLoading(name,loadingFx){loadingEffects[name]=loadingFx;}/** * @param {Object} opts * @param {string} [superClass] */functionextendComponentModel(opts/*, superClass*/){// var Clazz = ComponentModel;// if (superClass) {// var classType = parseClassType(superClass);// Clazz = ComponentModel.getClass(classType.main, classType.sub, true);// }returnComponentModel.extend(opts);}/** * @param {Object} opts * @param {string} [superClass] */functionextendComponentView(opts/*, superClass*/){// var Clazz = ComponentView;// if (superClass) {// var classType = parseClassType(superClass);// Clazz = ComponentView.getClass(classType.main, classType.sub, true);// }returnComponent.extend(opts);}/** * @param {Object} opts * @param {string} [superClass] */functionextendSeriesModel(opts/*, superClass*/){// var Clazz = SeriesModel;// if (superClass) {// superClass = 'series.' + superClass.replace('series.', '');// var classType = parseClassType(superClass);// Clazz = ComponentModel.getClass(classType.main, classType.sub, true);// }returnSeriesModel.extend(opts);}/** * @param {Object} opts * @param {string} [superClass] */functionextendChartView(opts/*, superClass*/){// var Clazz = ChartView;// if (superClass) {// superClass = superClass.replace('series.', '');// var classType = parseClassType(superClass);// Clazz = ChartView.getClass(classType.main, true);// }returnChart.extend(opts);}/** * ZRender need a canvas context to do measureText. * But in node environment canvas may be created by node-canvas. * So we need to specify how to create a canvas instead of using document.createElement('canvas') * * Be careful of using it in the browser. * * @param {Function} creator * @example * var Canvas = require('canvas'); * var echarts = require('echarts'); * echarts.setCanvasCreator(function () { * //Smallsizeisenough.*returnnewCanvas(32,32);*});*/function setCanvasCreator(creator) { $override('createCanvas', creator);}/***@param{string}mapName*@param{Array.<Object>|Object|string}geoJson*@param{Object}[specialAreas]**@exampleGeoJSON*$.get('USA.json',function(geoJson){*echarts.registerMap('USA',geoJson);*// Or*echarts.registerMap('USA',{*geoJson:geoJson,*specialAreas:{}*})*});**$.get('airport.svg',function(svg){*echarts.registerMap('airport',{*svg:svg*}*});**echarts.registerMap('eu',[*{svg:eu-topographic.svg},*{geoJSON:eu.json}*])*/function registerMap(mapName, geoJson, specialAreas) { mapDataStorage.registerMap(mapName, geoJson, specialAreas);}/***@param{string}mapName*@return{Object}*/function getMap(mapName) { //Forbackwardcompatibility,onlyreturnthefirstone.varrecords=mapDataStorage.retrieveMap(mapName);returnrecords&&records[0]&&{geoJson:records[0].geoJSON,specialAreas:records[0].specialAreas};}registerVisual(PRIORITY_VISUAL_GLOBAL,seriesColor);registerPreprocessor(backwardCompat);registerProcessor(PRIORITY_PROCESSOR_STATISTIC,dataStack);registerLoading('default',loadingDefault);// Default actionsregisterAction({type:'highlight',event:'highlight',update:'highlight'},noop);registerAction({type:'downplay',event:'downplay',update:'downplay'},noop);// Default themeregisterTheme('light',lightTheme);registerTheme('dark',theme);// For backward compatibility, where the namespace `dataTool` will// be mounted on `echarts` is the extension `dataTool` is imported.vardataTool={};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/function defaultKeyGetter(item) { return item;}/***@param{Array}oldArr*@param{Array}newArr*@param{Function}oldKeyGetter*@param{Function}newKeyGetter*@param{Object}[context]Canbevisitedbythis.contextincallback.*/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, /***Callbackfunctionwhenaddadata*/ add: function (func) { this._add = func; return this; }, /***Callbackfunctionwhenupdateadata*/ update: function (func) { this._update = func; return this; }, /***Callbackfunctionwhenremoveadata*/ remove: function (func) { this._remove = func; return this; }, execute: function () { 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); //Travelbyinvertedordertomakesureorderconsistency// when duplicate keys exists (consider newDataIndex.pop() below).// For performance consideration, these code below do not look neat.for(i=0;i<oldArr.length;i++){varkey=oldDataKeyArr[i];varidx=newDataIndexMap[key];// idx can never be empty array here. see 'set null' logic below.if(idx!=null){// Consider there is duplicate key (for example, use dataItem.name as key).// We should make sure every item in newArr and oldArr can be visited.varlen=idx.length;if(len){len===1&&(newDataIndexMap[key]=null);idx=idx.unshift();}else{newDataIndexMap[key]=null;}this._update&&this._update(idx,i);}else{this._remove&&this._remove(i);}}for(vari=0;i<newDataKeyArr.length;i++){varkey=newDataKeyArr[i];if(newDataIndexMap.hasOwnProperty(key)){varidx=newDataIndexMap[key];if(idx==null){continue;}// idx can never be empty array here. see 'set null' logic above.if(!idx.length){this._add&&this._add(idx);}else{for(varj=0,len=idx.length;j<len;j++){this._add&&this._add(idx[j]);}}}}}};functioninitIndexMap(arr,map,keyArr,keyGetterName,dataDiffer){for(vari=0;i<arr.length;i++){// Add prefix to avoid conflict with Object.prototype.varkey='_ec_'+dataDiffer[keyGetterName](arr[i],i);varexistence=map[key];if(existence==null){keyArr.push(key);map[key]=i;}else{if(!existence.length){map[key]=existence=[existence];}existence.push(i);}}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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 = []; 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 coordDimArr = encode[coordDim]; if (!encode.hasOwnProperty(coordDim)) { coordDimArr = encode[coordDim] = []; } coordDimArr[dimItem.coordDimIndex] = dimName; if (!dimItem.isExtraCoord) { notExtraCoordDimMap.set(coordDim, 1); //Usethelastcoorddim(andlabelfriendly)asdefaultlabel,// because when dataset is used, it is hard to guess which dimension// can be value dimension. If both show x, y on label is not look good,// and conventionally y axis is focused more.if(mayLabelDimType(dimItem.type)){defaultedLabel[0]=dimName;}}if(dimItem.defaultTooltip){defaultedTooltip.push(dimName);}}OTHER_DIMENSIONS.each(function(v,otherDim){varotherDimArr=encode[otherDim];if(!encode.hasOwnProperty(otherDim)){otherDimArr=encode[otherDim]=[];}vardimIndex=dimItem.otherDims[otherDim];if(dimIndex!=null&&dimIndex!==false){otherDimArr[dimIndex]=dimItem.name;}});});vardataDimsOnCoord=[];varencodeFirstDimNotExtra={};notExtraCoordDimMap.each(function(v,coordDim){vardimArr=encode[coordDim];// ??? FIXME extra coord should not be set in dataDimsOnCoord.// But should fix the case that radar axes: simplify the logic// of `completeDimension`, remove `extraPrefix`.encodeFirstDimNotExtra[coordDim]=dimArr[0];// Not necessary to remove duplicate, because a data// dim canot on more than one coordDim.dataDimsOnCoord=dataDimsOnCoord.concat(dimArr);});summary.dataDimsOnCoord=dataDimsOnCoord;summary.encodeFirstDimNotExtra=encodeFirstDimNotExtra;varencodeLabel=encode.label;// FIXME `encode.label` is not recommanded, because formatter can not be set// in this way. Use label.formatter instead. May be remove this approach someday.if(encodeLabel&&encodeLabel.length){defaultedLabel=encodeLabel.slice();}varencodeTooltip=encode.tooltip;if(encodeTooltip&&encodeTooltip.length){defaultedTooltip=encodeTooltip.slice();}elseif(!defaultedTooltip.length){defaultedTooltip=defaultedLabel.slice();}encode.defaultedLabel=defaultedLabel;encode.defaultedTooltip=defaultedTooltip;returnsummary;}functiongetDimensionTypeByAxis(axisType){returnaxisType==='category'?'ordinal':axisType==='time'?'time':'float';}functionmayLabelDimType(dimType){// In most cases, ordinal and time do not suitable for label.// Ordinal info can be displayed on axis. Time is too long.return!(dimType==='ordinal'||dimType==='time');}// function findTheLastDimMayLabel(data) {// // Get last value dim// var dimensions = data.dimensions.slice();// var valueType;// var valueDim;// while (dimensions.length && (// valueDim = dimensions.pop(),// valueType = data.getDimensionInfo(valueDim).type,// valueType === 'ordinal' || valueType === 'time'// )) {} // jshint ignore:line// return valueDim;// }/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//*globalFloat64Array,Int32Array,Uint32Array,Uint16Array*//***Listfordatastorage*@moduleecharts/data/List*/var isObject$4 = isObject$1;var UNDEFINED = 'undefined';//UseprefixtoavoidindextobethesameasotherIdList[idx],// which will cause weird udpate animation.varID_PREFIX='e\0\0';vardataCtors={'float':typeofFloat64Array===UNDEFINED?Array:Float64Array,'int':typeofInt32Array===UNDEFINED?Array:Int32Array,// Ordinal data type can be string or int'ordinal':Array,'number':Array,'time':Array};// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is// different from the Ctor of typed array.varCtorUint32Array=typeofUint32Array===UNDEFINED?Array:Uint32Array;varCtorUint16Array=typeofUint16Array===UNDEFINED?Array:Uint16Array;functiongetIndicesCtor(list){// The possible max value in this._indicies is always this._rawCount despite of filtering.returnlist._rawCount>65535?CtorUint32Array:CtorUint16Array;}functioncloneChunk(originalChunk){varCtor=originalChunk.constructor;// Only shallow clone is enough when Array.returnCtor===Array?originalChunk.slice():newCtor(originalChunk);}varTRANSFERABLE_PROPERTIES=['hasItemOption','_nameList','_idList','_invertedIndicesMap','_rawData','_chunkSize','_chunkCount','_dimValueGetter','_count','_rawCount','_nameDimIdx','_idDimIdx'];varCLONE_PROPERTIES=['_extent','_approximateExtent','_rawExtent'];functiontransferProperties(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);}/** * @constructor * @alias module:echarts/data/List**@param{Array.<string|Object>}dimensions*Forexample,['someDimName',{name:'someDimName',type:'someDimType'},...].*Dimensionsshouldbeconcretenameslikex,y,z,lng,lat,angle,radius*Spetialfields:{*ordinalMeta:<module:echarts/data/OrdinalMeta>*createInvertedIndices:<boolean>*}*@param{module:echarts/model/Model}hostModel*/var List = function (dimensions, hostModel) { dimensions = dimensions || ['x', 'y']; var dimensionInfos = {}; var dimensionNames = []; var invertedIndicesMap = {}; for (var i = 0; i < dimensions.length; i++) { //Usetheoriginaldimensions[i],whereotherflagpropsmayexists.vardimensionInfo=dimensions[i];if(isString(dimensionInfo)){dimensionInfo={name:dimensionInfo};}vardimensionName=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]=[];}}/** * @readOnly * @type {Array.<string>} */this.dimensions=dimensionNames;/** * Infomation of each data dimension, like data type. * @type {Object} */this._dimensionInfos=dimensionInfos;/** * @type {module:echarts/model/Model}*/ this.hostModel = hostModel; /***@type{module:echarts/model/Model}*/ this.dataType; /***Indicesstorestheindicesofdatasubsetafterfiltered.*Thisdatasubsetwillbeusedinchart.*@type{Array.<number>}*@readOnly*/ this._indices = null; this._count = 0; this._rawCount = 0; /***Datastorage*@type{Object.<key,Array.<TypedArray|Array>>}*@private*/ this._storage = {}; /***@type{Array.<string>}*/ this._nameList = []; /***@type{Array.<string>}*/ this._idList = []; /***Modelsofdataoptionisstoredsparseforoptimizingmemorycost*@type{Array.<module:echarts/model/Model>}*@private*/ this._optionModels = []; /***Globalvisualpropertiesaftervisualcoding*@type{Object}*@private*/ this._visual = {}; /***Globellayoutproperties.*@type{Object}*@private*/ this._layout = {}; /***Itemvisualpropertiesaftervisualcoding*@type{Array.<Object>}*@private*/ this._itemVisuals = []; /***Key:visualtype,Value:boolean*@type{Object}*@readOnly*/ this.hasItemVisual = {}; /***Itemlayoutpropertiesafterlayout*@type{Array.<Object>}*@private*/ this._itemLayouts = []; /***Graphicelemnents*@type{Array.<module:zrender/Element>}*@private*/ this._graphicEls = []; /***Maxsizeofeachchunk.*@type{number}*@private*/ this._chunkSize = 1e5; /***@type{number}*@private*/ this._chunkCount = 0; /***@type{Array.<Array|Object>}*@private*/ this._rawData; /***Rawextentwillnotbecloned,butonlytransfered.*Itwillnotbecalculatedutilneeded.*key:dim,*value:{end:number,extent:Array.<number>}*@type{Object}*@private*/ this._rawExtent = {}; /***@type{Object}*@private*/ this._extent = {}; /***key:dim*value:extent*@type{Object}*@private*/ this._approximateExtent = {}; /***Cachesummaryinfoforfastvisit.See"dimensionHelper".*@type{Object}*@private*/ this._dimensionsSummary = summarizeDimensions(this); /***@type{Object.<Array|TypedArray>}*@private*/ this._invertedIndicesMap = invertedIndicesMap; /***@type{Object}*@private*/ this._calculationInfo = {};};var listProto = List.prototype;listProto.type = 'list';/***Ifeachdataitemhasit'sownoption*@type{boolean}*/listProto.hasItemOption = true;/***Getdimensionname*@param{string|number}dim*Dimensioncanbeconcretenameslikex,y,z,lng,lat,angle,radius*Oraordinalnumber.ForexamplegetDimensionInfo(0)willreturn'x'or'lng'or'radius'*@return{string}Concretedimname.*/listProto.getDimension = function (dim) { if (!isNaN(dim)) { dim = this.dimensions[dim] || dim; } return dim;};/***Gettypeandcalculationinfoofparticulardimension*@param{string|number}dim*Dimensioncanbeconcretenameslikex,y,z,lng,lat,angle,radius*Oraordinalnumber.ForexamplegetDimensionInfo(0)willreturn'x'or'lng'or'radius'*/listProto.getDimensionInfo = function (dim) { //Donotclone,becausetheremaybecategoriesindimInfo.returnthis._dimensionInfos[this.getDimension(dim)];};/** * @return {Array.<string>} concrete dimension name list on coord. */listProto.getDimensionsOnCoord=function(){returnthis._dimensionsSummary.dataDimsOnCoord.slice();};/** * @param {string} coordDim * @param {number} [idx] A coordDim may map to more than one data dim. * If idx is `true`, return a array of all mapped dims. * If idx is not specified, return the first dim not extra. * @return {string|Array.<string>} concrete data dim. * If idx is number, and not found, return null/undefined.*Ifidxis`true`,andnotfound,returnemptyarray(alwaysreturnarray).*/listProto.mapDimension = function (coordDim, idx) { var dimensionsSummary = this._dimensionsSummary; if (idx == null) { return dimensionsSummary.encodeFirstDimNotExtra[coordDim]; } var dims = dimensionsSummary.encode[coordDim]; return idx === true //alwaysreturnarrayifidxis`true`?(dims||[]).slice():(dims&&dims[idx]);};/** * Initialize from data * @param {Array.<Object|number|Array>} data source or data or data provider. * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and * defualt label/tooltip.*Anamecanbespecifiedinencode.itemName,*ordataItem.name(onlyforseriesoptiondata),*orprovidedinnameListfromoutside.*@param{Function}[dimValueGetter](dataItem,dimName,dataIndex,dimIndex)=>number*/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; //Clearthis._storage={};this._indices=null;this._nameList=nameList||[];this._idList=[];this._nameRepeatCount={};if(!dimValueGetter){this.hasItemOption=false;}/** * @readOnly */this.defaultDimValueGetter=defaultDimValueGetters[this._rawData.getSource().sourceFormat];// Default dim value getterthis._dimValueGetter=dimValueGetter=dimValueGetter||this.defaultDimValueGetter;// Reset raw extent.this._rawExtent={};this._initDataFromProvider(0,data.count());// If data has no item option.if(data.pure){this.hasItemOption=false;}};listProto.getProvider=function(){returnthis._rawData;};listProto.appendData=function(data){if(__DEV__){assert$1(!this._indices,'appendData can only be called on raw data.');}varrawData=this._rawData;varstart=this.count();rawData.appendData(data);varend=rawData.count();if(!rawData.persistent){end+=start;}this._initDataFromProvider(start,end);};listProto._initDataFromProvider=function(start,end){// Optimize.if(start>=end){return;}varchunkSize=this._chunkSize;varrawData=this._rawData;varstorage=this._storage;vardimensions=this.dimensions;vardimLen=dimensions.length;vardimensionInfoMap=this._dimensionInfos;varnameList=this._nameList;varidList=this._idList;varrawExtent=this._rawExtent;varnameRepeatCount=this._nameRepeatCount={};varnameDimIdx;varchunkCount=this._chunkCount;varlastChunkIndex=chunkCount-1;for(vari=0;i<dimLen;i++){vardim=dimensions[i];if(!rawExtent[dim]){rawExtent[dim]=getInitialExtent();}vardimInfo=dimensionInfoMap[dim];if(dimInfo.otherDims.itemName===0){nameDimIdx=this._nameDimIdx=i;}if(dimInfo.otherDims.itemId===0){this._idDimIdx=i;}varDataCtor=dataCtors[dimInfo.type];if(!storage[dim]){storage[dim]=[];}varresizeChunkArray=storage[dim][lastChunkIndex];if(resizeChunkArray&&resizeChunkArray.length<chunkSize){varnewStore=newDataCtor(Math.min(end-lastChunkIndex*chunkSize,chunkSize));// The cost of the copy is probably inconsiderable// within the initial chunkSize.for(varj=0;j<resizeChunkArray.length;j++){newStore[j]=resizeChunkArray[j];}storage[dim][lastChunkIndex]=newStore;}// Create new chunks.for(vark=chunkCount*chunkSize;k<end;k+=chunkSize){storage[dim].push(newDataCtor(Math.min(end-k,chunkSize)));}this._chunkCount=storage[dim].length;}vardataItem=newArray(dimLen);for(varidx=start;idx<end;idx++){// NOTICE: Try not to write things into dataItemdataItem=rawData.getItem(idx,dataItem);// Each data item is value// [1, 2]// 2// Bar chart, line chart which uses category axis// only gives the 'y' value. 'x' value is the indices of category// Use a tempValue to normalize the value to be a (x, y) valuevarchunkIndex=Math.floor(idx/chunkSize);varchunkOffset=idx%chunkSize;// Store the data by dimensionsfor(vark=0;k<dimLen;k++){vardim=dimensions[k];vardimStorage=storage[dim][chunkIndex];// PENDING NULL is empty or zerovarval=this._dimValueGetter(dataItem,dim,idx,k);dimStorage[chunkOffset]=val;vardimRawExtent=rawExtent[dim];if(val<dimRawExtent[0]){dimRawExtent[0]=val;}if(val>dimRawExtent[1]){dimRawExtent[1]=val;}}// ??? FIXME not check by pure but sourceFormat?// TODO refactor these logic.if(!rawData.pure){varname=nameList[idx];if(dataItem&&name==null){// If dataItem is {name: ...}, it has highest priority.// That is appropriate for many common cases.if(dataItem.name!=null){// There is no other place to persistent dataItem.name,// so save it to nameList.nameList[idx]=name=dataItem.name;}elseif(nameDimIdx!=null){varnameDim=dimensions[nameDimIdx];varnameDimChunk=storage[nameDim][chunkIndex];if(nameDimChunk){name=nameDimChunk[chunkOffset];varordinalMeta=dimensionInfoMap[nameDim].ordinalMeta;if(ordinalMeta&&ordinalMeta.categories.length){name=ordinalMeta.categories[name];}}}}// Try using the id in option// id or name is used on dynamical data, mapping old and new items.varid=dataItem==null?null:dataItem.id;if(id==null&&name!=null){// Use name as id and add counter to avoid same namenameRepeatCount[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.rawData.clean();}this._rawCount=this._count=end;// Reset data extentthis._extent={};prepareInvertedIndex(this);};functionprepareInvertedIndex(list){varinvertedIndicesMap=list._invertedIndicesMap;each$1(invertedIndicesMap,function(invertedIndices,dim){vardimInfo=list._dimensionInfos[dim];// Currently, only dimensions that has ordinalMeta can create inverted indices.varordinalMeta=dimInfo.ordinalMeta;if(ordinalMeta){invertedIndices=invertedIndicesMap[dim]=newCtorUint32Array(ordinalMeta.categories.length);// The default value of TypedArray is 0. To avoid miss// mapping to 0, we should set it as NaN.for(vari=0;i<invertedIndices.length;i++){invertedIndices[i]=NaN;}for(vari=0;i<list._count;i++){// Only support the case that all values are distinct.invertedIndices[list.get(dim,i)]=i;}}});}functiongetRawValueFromStore(list,dimIndex,rawIndex){varval;if(dimIndex!=null){varchunkSize=list._chunkSize;varchunkIndex=Math.floor(rawIndex/chunkSize);varchunkOffset=rawIndex%chunkSize;vardim=list.dimensions[dimIndex];varchunk=list._storage[dim][chunkIndex];if(chunk){val=chunk[chunkOffset];varordinalMeta=list._dimensionInfos[dim].ordinalMeta;if(ordinalMeta&&ordinalMeta.categories.length){val=ordinalMeta.categories[val];}}}returnval;}/** * @return {number} */listProto.count=function(){returnthis._count;};listProto.getIndices=function(){varnewIndices;varindices=this._indices;if(indices){varCtor=indices.constructor;varthisCount=this._count;// `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.if(Ctor===Array){newIndices=newCtor(thisCount);for(vari=0;i<thisCount;i++){newIndices[i]=indices[i];}}else{newIndices=newCtor(indices.buffer,0,thisCount);}}else{varCtor=getIndicesCtor(this);varnewIndices=newCtor(this.count());for(vari=0;i<newIndices.length;i++){newIndices[i]=i;}}returnnewIndices;};/** * Get value. Return NaN if idx is out of range. * @param {string} dim Dim must be concrete name. * @param {number} idx * @param {boolean} stack * @return {number} */listProto.get=function(dim,idx/*, stack */){if(!(idx>=0&&idx<this._count)){returnNaN;}varstorage=this._storage;if(!storage[dim]){// TODO Warn ?returnNaN;}idx=this.getRawIndex(idx);varchunkIndex=Math.floor(idx/this._chunkSize);varchunkOffset=idx%this._chunkSize;varchunkStore=storage[dim][chunkIndex];varvalue=chunkStore[chunkOffset];// FIXME ordinal data type is not stackable// if (stack) {// var dimensionInfo = this._dimensionInfos[dim];// if (dimensionInfo && dimensionInfo.stackable) {// var stackedOn = this.stackedOn;// while (stackedOn) {// // Get no stacked data of stacked on// var stackedValue = stackedOn.get(dim, idx);// // Considering positive stack, negative stack and empty data// if ((value >= 0 && stackedValue > 0) // Positive stack// || (value <= 0 && stackedValue < 0) // Negative stack// ) {// value += stackedValue;// }// stackedOn = stackedOn.stackedOn;// }// }// }returnvalue;};/** * @param {string} dim concrete dim * @param {number} rawIndex * @return {number|string} */listProto.getByRawIndex=function(dim,rawIdx){if(!(rawIdx>=0&&rawIdx<this._rawCount)){returnNaN;}vardimStore=this._storage[dim];if(!dimStore){// TODO Warn ?returnNaN;}varchunkIndex=Math.floor(rawIdx/this._chunkSize);varchunkOffset=rawIdx%this._chunkSize;varchunkStore=dimStore[chunkIndex];returnchunkStore[chunkOffset];};/** * FIXME Use `get` on chrome maybe slow(in filterSelf and selectRange). * Hack a much simpler _getFast * @private */listProto._getFast=function(dim,rawIdx){varchunkIndex=Math.floor(rawIdx/this._chunkSize);varchunkOffset=rawIdx%this._chunkSize;varchunkStore=this._storage[dim][chunkIndex];returnchunkStore[chunkOffset];};/** * Get value for multi dimensions. * @param {Array.<string>} [dimensions] If ignored, using all dimensions. * @param {number} idx * @return {number} */listProto.getValues=function(dimensions,idx/*, stack */){varvalues=[];if(!isArray(dimensions)){// stack = idx;idx=dimensions;dimensions=this.dimensions;}for(vari=0,len=dimensions.length;i<len;i++){values.push(this.get(dimensions[i],idx/*, stack */));}returnvalues;};/** * If value is NaN. Inlcuding '-' * Only check the coord dimensions. * @param {string} dim * @param {number} idx * @return {number} */listProto.hasValue=function(idx){vardataDimsOnCoord=this._dimensionsSummary.dataDimsOnCoord;vardimensionInfos=this._dimensionInfos;for(vari=0,len=dataDimsOnCoord.length;i<len;i++){if(// Ordinal type can be string or numberdimensionInfos[dataDimsOnCoord[i]].type!=='ordinal'// FIXME check ordinal when using index?&&isNaN(this.get(dataDimsOnCoord[i],idx))){returnfalse;}}returntrue;};/** * Get extent of data in one dimension * @param {string} dim * @param {boolean} stack */listProto.getDataExtent=function(dim/*, stack */){// Make sure use concrete dim as cache name.dim=this.getDimension(dim);vardimData=this._storage[dim];varinitialExtent=getInitialExtent();// stack = !!((stack || false) && this.getCalculationInfo(dim));if(!dimData){returninitialExtent;}// Make more strict checkings to ensure hitting cache.varcurrEnd=this.count();// var cacheName = [dim, !!stack].join('_');// var cacheName = dim;// Consider the most cases when using data zoom, `getDataExtent`// happened before filtering. We cache raw extent, which is not// necessary to be cleared and recalculated when restore data.varuseRaw=!this._indices;// && !stack;vardimExtent;if(useRaw){returnthis._rawExtent[dim].slice();}dimExtent=this._extent[dim];if(dimExtent){returndimExtent.slice();}dimExtent=initialExtent;varmin=dimExtent[0];varmax=dimExtent[1];for(vari=0;i<currEnd;i++){// var value = stack ? this.get(dim, i, true) : this._getFast(dim, this.getRawIndex(i));varvalue=this._getFast(dim,this.getRawIndex(i));value<min&&(min=value);value>max&&(max=value);}dimExtent=[min,max];this._extent[dim]=dimExtent;returndimExtent;};/** * Optimize for the scenario that data is filtered by a given extent. * Consider that if data amount is more than hundreds of thousand, * extent calculation will cost more than 10ms and the cache will * be erased because of the filtering. */listProto.getApproximateExtent=function(dim/*, stack */){dim=this.getDimension(dim);returnthis._approximateExtent[dim]||this.getDataExtent(dim/*, stack */);};listProto.setApproximateExtent=function(extent,dim/*, stack */){dim=this.getDimension(dim);this._approximateExtent[dim]=extent.slice();};/** * @param {string} key * @return {*} */listProto.getCalculationInfo=function(key){returnthis._calculationInfo[key];};/** * @param {string|Object} key or k-v object * @param {*} [value] */listProto.setCalculationInfo=function(key,value){isObject$4(key)?extend(this._calculationInfo,key):(this._calculationInfo[key]=value);};/** * Get sum of data in one dimension * @param {string} dim */listProto.getSum=function(dim/*, stack */){vardimData=this._storage[dim];varsum=0;if(dimData){for(vari=0,len=this.count();i<len;i++){varvalue=this.get(dim,i/*, stack */);if(!isNaN(value)){sum+=value;}}}returnsum;};/** * Get median of data in one dimension * @param {string} dim */listProto.getMedian=function(dim/*, stack */){vardimDataArray=[];// map all data of one dimensionthis.each(dim,function(val,idx){if(!isNaN(val)){dimDataArray.push(val);}});// TODO// Use quick select?// immutability & sortvarsortedDimDataArray=[].concat(dimDataArray).sort(function(a,b){returna-b;});varlen=this.count();// calculate medianreturnlen===0?0:len%2===1?sortedDimDataArray[(len-1)/2]:(sortedDimDataArray[len/2]+sortedDimDataArray[len/2-1])/2;};// /**// * Retreive the index with given value// * @param {string} dim Concrete dimension.// * @param {number} value// * @return {number}// */// Currently incorrect: should return dataIndex but not rawIndex.// Do not fix it until this method is to be used somewhere.// FIXME Precision of float value// listProto.indexOf = function (dim, value) {// var storage = this._storage;// var dimData = storage[dim];// var chunkSize = this._chunkSize;// if (dimData) {// for (var i = 0, len = this.count(); i < len; i++) {// var chunkIndex = Math.floor(i / chunkSize);// var chunkOffset = i % chunkSize;// if (dimData[chunkIndex][chunkOffset] === value) {// return i;// }// }// }// return -1;// };/** * Only support the dimension which inverted index created. * Do not support other cases until required. * @param {string} concrete dim * @param {number|string} value * @return {number} rawIndex */listProto.rawIndexOf=function(dim,value){varinvertedIndices=dim&&this._invertedIndicesMap[dim];if(__DEV__){if(!invertedIndices){thrownewError('Do not supported yet');}}varrawIndex=invertedIndices[value];if(rawIndex==null||isNaN(rawIndex)){return-1;}returnrawIndex;};/** * Retreive the index with given name * @param {number} idx * @param {number} name * @return {number} */listProto.indexOfName=function(name){for(vari=0,len=this.count();i<len;i++){if(this.getName(i)===name){returni;}}return-1;};/** * Retreive the index with given raw data index * @param {number} idx * @param {number} name * @return {number} */listProto.indexOfRawIndex=function(rawIndex){if(!this._indices){returnrawIndex;}if(rawIndex>=this._rawCount||rawIndex<0){return-1;}// Indices are ascendingvarindices=this._indices;// If rawIndex === dataIndexvarrawDataIndex=indices[rawIndex];if(rawDataIndex!=null&&rawDataIndex<this._count&&rawDataIndex===rawIndex){returnrawIndex;}varleft=0;varright=this._count-1;while(left<=right){varmid=(left+right)/2|0;if(indices[mid]<rawIndex){left=mid+1;}elseif(indices[mid]>rawIndex){right=mid-1;}else{returnmid;}}return-1;};/** * Retreive the index of nearest value * @param {string} dim * @param {number} value * @param {number} [maxDistance=Infinity] * @return {Array.<number>} Considere multiple points has the same value. */listProto.indicesOfNearest=function(dim,value,maxDistance){varstorage=this._storage;vardimData=storage[dim];varnearestIndices=[];if(!dimData){returnnearestIndices;}if(maxDistance==null){maxDistance=Infinity;}varminDist=Number.MAX_VALUE;varminDiff=-1;for(vari=0,len=this.count();i<len;i++){vardiff=value-this.get(dim,i/*, stack */);vardist=Math.abs(diff);if(diff<=maxDistance&&dist<=minDist){// For the case of two data are same on xAxis, which has sequence data.// Show the nearest index// https://github.com/ecomfe/echarts/issues/2869if(dist<minDist||(diff>=0&&minDiff<0)){minDist=dist;minDiff=diff;nearestIndices.length=0;}nearestIndices.push(i);}}returnnearestIndices;};/** * Get raw data index * @param {number} idx * @return {number} */listProto.getRawIndex=getRawIndexWithoutIndices;functiongetRawIndexWithoutIndices(idx){returnidx;}functiongetRawIndexWithIndices(idx){if(idx<this._count&&idx>=0){returnthis._indices[idx];}return-1;}/** * Get raw data item * @param {number} idx * @return {number} */listProto.getRawDataItem=function(idx){if(!this._rawData.persistent){varval=[];for(vari=0;i<this.dimensions.length;i++){vardim=this.dimensions[i];val.push(this.get(dim,idx));}returnval;}else{returnthis._rawData.getItem(this.getRawIndex(idx));}};/** * @param {number} idx * @param {boolean} [notDefaultIdx=false] * @return {string} */listProto.getName=function(idx){varrawIndex=this.getRawIndex(idx);returnthis._nameList[rawIndex]||getRawValueFromStore(this,this._nameDimIdx,rawIndex)||'';};/** * @param {number} idx * @param {boolean} [notDefaultIdx=false] * @return {string} */listProto.getId=function(idx){returngetId(this,this.getRawIndex(idx));};functiongetId(list,rawIndex){varid=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.id=ID_PREFIX+rawIndex;}returnid;}functionnormalizeDimensions(dimensions){if(!isArray(dimensions)){dimensions=[dimensions];}returndimensions;}functionvalidateDimensions(list,dims){for(vari=0;i<dims.length;i++){// stroage may be empty when no data, so use// dimensionInfos to check.if(!list._dimensionInfos[dims[i]]){console.error('Unkown dimension '+dims[i]);}}}/** * Data iteration * @param {string|Array.<string>} * @param {Function} cb * @param {*} [context=this] * * @example * list.each('x', function (x, idx) {}); * list.each(['x', 'y'], function (x, y, idx) {}); * list.each(function (idx) {}) */listProto.each=function(dims,cb,context,contextCompat){'use strict';if(!this._count){return;}if(typeofdims==='function'){contextCompat=context;context=cb;cb=dims;dims=[];}// contextCompat just for compat echarts3context=context||contextCompat||this;dims=map(normalizeDimensions(dims),this.getDimension,this);if(__DEV__){validateDimensions(this,dims);}vardimSize=dims.length;for(vari=0;i<this.count();i++){// Simple optimizationswitch(dimSize){case0:cb.call(context,i);break;case1:cb.call(context,this.get(dims[0],i),i);break;case2:cb.call(context,this.get(dims[0],i),this.get(dims[1],i),i);break;default:vark=0;varvalue=[];for(;k<dimSize;k++){value[k]=this.get(dims[k],i);}// Indexvalue[k]=i;cb.apply(context,value);}}};/** * Data filter * @param {string|Array.<string>} * @param {Function} cb * @param {*} [context=this] */listProto.filterSelf=function(dimensions,cb,context,contextCompat){'use strict';if(!this._count){return;}if(typeofdimensions==='function'){contextCompat=context;context=cb;cb=dimensions;dimensions=[];}// contextCompat just for compat echarts3context=context||contextCompat||this;dimensions=map(normalizeDimensions(dimensions),this.getDimension,this);if(__DEV__){validateDimensions(this,dimensions);}varcount=this.count();varCtor=getIndicesCtor(this);varnewIndices=newCtor(count);varvalue=[];vardimSize=dimensions.length;varoffset=0;vardim0=dimensions[0];for(vari=0;i<count;i++){varkeep;varrawIdx=this.getRawIndex(i);// Simple optimizationif(dimSize===0){keep=cb.call(context,i);}elseif(dimSize===1){varval=this._getFast(dim0,rawIdx);keep=cb.call(context,val,i);}else{for(vark=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.if(offset<count){this._indices=newIndices;}this._count=offset;// Reset data extentthis._extent={};this.getRawIndex=this._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;returnthis;};/** * Select data in range. (For optimization of filter) * (Manually inline code, support 5 million data filtering in data zoom.) */listProto.selectRange=function(range){'use strict';if(!this._count){return;}vardimensions=[];for(vardiminrange){if(range.hasOwnProperty(dim)){dimensions.push(dim);}}if(__DEV__){validateDimensions(this,dimensions);}vardimSize=dimensions.length;if(!dimSize){return;}varoriginalCount=this.count();varCtor=getIndicesCtor(this);varnewIndices=newCtor(originalCount);varoffset=0;vardim0=dimensions[0];varmin=range[dim0][0];varmax=range[dim0][1];varquickFinished=false;if(!this._indices){// Extreme optimization for common case. About 2x faster in chrome.varidx=0;if(dimSize===1){vardimStorage=this._storage[dimensions[0]];for(vark=0;k<this._chunkCount;k++){varchunkStorage=dimStorage[k];varlen=Math.min(this._count-k*this._chunkSize,this._chunkSize);for(vari=0;i<len;i++){varval=chunkStorage[i];// NaN will not be filtered. Consider the case, in line chart, empty// value indicates the line should be broken. But for the case like// scatter plot, a data item with empty value will not be rendered,// but the axis extent may be effected if some other dim of the data// item has value. Fortunately it is not a significant negative effect.if((val>=min&&val<=max)||isNaN(val)){newIndices[offset++]=idx;}idx++;}}quickFinished=true;}elseif(dimSize===2){vardimStorage=this._storage[dim0];vardimStorage2=this._storage[dimensions[1]];varmin2=range[dimensions[1]][0];varmax2=range[dimensions[1]][1];for(vark=0;k<this._chunkCount;k++){varchunkStorage=dimStorage[k];varchunkStorage2=dimStorage2[k];varlen=Math.min(this._count-k*this._chunkSize,this._chunkSize);for(vari=0;i<len;i++){varval=chunkStorage[i];varval2=chunkStorage2[i];// Do not filter NaN, see comment above.if(((val>=min&&val<=max)||isNaN(val))&&((val2>=min2&&val2<=max2)||isNaN(val2))){newIndices[offset++]=idx;}idx++;}}quickFinished=true;}}if(!quickFinished){if(dimSize===1){for(vari=0;i<originalCount;i++){varrawIndex=this.getRawIndex(i);varval=this._getFast(dim0,rawIndex);// Do not filter NaN, see comment above.if((val>=min&&val<=max)||isNaN(val)){newIndices[offset++]=rawIndex;}}}else{for(vari=0;i<originalCount;i++){varkeep=true;varrawIndex=this.getRawIndex(i);for(vark=0;k<dimSize;k++){vardimk=dimensions[k];varval=this._getFast(dim,rawIndex);// Do not filter NaN, see comment above.if(val<range[dimk][0]||val>range[dimk][1]){keep=false;}}if(keep){newIndices[offset++]=this.getRawIndex(i);}}}}// Set indices after filtered.if(offset<originalCount){this._indices=newIndices;}this._count=offset;// Reset data extentthis._extent={};this.getRawIndex=this._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;returnthis;};/** * Data mapping to a plain array * @param {string|Array.<string>} [dimensions] * @param {Function} cb * @param {*} [context=this] * @return {Array} */listProto.mapArray=function(dimensions,cb,context,contextCompat){'use strict';if(typeofdimensions==='function'){contextCompat=context;context=cb;cb=dimensions;dimensions=[];}// contextCompat just for compat echarts3context=context||contextCompat||this;varresult=[];this.each(dimensions,function(){result.push(cb&&cb.apply(this,arguments));},context);returnresult;};// Data in excludeDimensions is copied, otherwise transfered.functioncloneListForMapAndSample(original,excludeDimensions){varallDimensions=original.dimensions;varlist=newList(map(allDimensions,original.getDimensionInfo,original),original.hostModel);// FIXME If needs stackedOn, value may already been stackedtransferProperties(list,original);varstorage=list._storage={};varoriginalStorage=original._storage;// Init storagefor(vari=0;i<allDimensions.length;i++){vardim=allDimensions[i];if(originalStorage[dim]){// Notice that we do not reset invertedIndicesMap here, becuase// there is no scenario of mapping or sampling ordinal dimension.if(indexOf(excludeDimensions,dim)>=0){storage[dim]=cloneDimStore(originalStorage[dim]);list._rawExtent[dim]=getInitialExtent();list._extent[dim]=null;}else{// Direct reference for other dimensionsstorage[dim]=originalStorage[dim];}}}returnlist;}functioncloneDimStore(originalDimStore){varnewDimStore=newArray(originalDimStore.length);for(varj=0;j<originalDimStore.length;j++){newDimStore[j]=cloneChunk(originalDimStore[j]);}returnnewDimStore;}functiongetInitialExtent(){return[Infinity,-Infinity];}/** * Data mapping to a new List with given dimensions * @param {string|Array.<string>} dimensions * @param {Function} cb * @param {*} [context=this] * @return {Array} */listProto.map=function(dimensions,cb,context,contextCompat){'use strict';// contextCompat just for compat echarts3context=context||contextCompat||this;dimensions=map(normalizeDimensions(dimensions),this.getDimension,this);if(__DEV__){validateDimensions(this,dimensions);}varlist=cloneListForMapAndSample(this,dimensions);// Following properties are all immutable.// So we can reference to the same valuelist._indices=this._indices;list.getRawIndex=list._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;varstorage=list._storage;vartmpRetValue=[];varchunkSize=this._chunkSize;vardimSize=dimensions.length;vardataCount=this.count();varvalues=[];varrawExtent=list._rawExtent;for(vardataIndex=0;dataIndex<dataCount;dataIndex++){for(vardimIndex=0;dimIndex<dimSize;dimIndex++){values[dimIndex]=this.get(dimensions[dimIndex],dataIndex/*, stack */);}values[dimSize]=dataIndex;varretValue=cb&&cb.apply(context,values);if(retValue!=null){// a number or string (in oridinal dimension)?if(typeofretValue!=='object'){tmpRetValue[0]=retValue;retValue=tmpRetValue;}varrawIndex=this.getRawIndex(dataIndex);varchunkIndex=Math.floor(rawIndex/chunkSize);varchunkOffset=rawIndex%chunkSize;for(vari=0;i<retValue.length;i++){vardim=dimensions[i];varval=retValue[i];varrawExtentOnDim=rawExtent[dim];vardimStore=storage[dim];if(dimStore){dimStore[chunkIndex][chunkOffset]=val;}if(val<rawExtentOnDim[0]){rawExtentOnDim[0]=val;}if(val>rawExtentOnDim[1]){rawExtentOnDim[1]=val;}}}}returnlist;};/** * Large data down sampling on given dimension * @param {string} dimension * @param {number} rate * @param {Function} sampleValue * @param {Function} sampleIndex Sample index for name and id */listProto.downSample=function(dimension,rate,sampleValue,sampleIndex){varlist=cloneListForMapAndSample(this,[dimension]);vartargetStorage=list._storage;varframeValues=[];varframeSize=Math.floor(1/rate);vardimStore=targetStorage[dimension];varlen=this.count();varchunkSize=this._chunkSize;varrawExtentOnDim=list._rawExtent[dimension];varnewIndices=new(getIndicesCtor(this))(len);varoffset=0;for(vari=0;i<len;i+=frameSize){// Last frameif(frameSize>len-i){frameSize=len-i;frameValues.length=frameSize;}for(vark=0;k<frameSize;k++){vardataIdx=this.getRawIndex(i+k);varoriginalChunkIndex=Math.floor(dataIdx/chunkSize);varoriginalChunkOffset=dataIdx%chunkSize;frameValues[k]=dimStore[originalChunkIndex][originalChunkOffset];}varvalue=sampleValue(frameValues);varsampleFrameIdx=this.getRawIndex(Math.min(i+sampleIndex(frameValues,value)||0,len-1));varsampleChunkIndex=Math.floor(sampleFrameIdx/chunkSize);varsampleChunkOffset=sampleFrameIdx%chunkSize;// Only write value on the filtered datadimStore[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;returnlist;};/** * Get model of one data item. * * @param {number} idx */// FIXME Model proxy ?listProto.getItemModel=function(idx){varhostModel=this.hostModel;returnnewModel(this.getRawDataItem(idx),hostModel,hostModel&&hostModel.ecModel);};/** * Create a data differ * @param {module:echarts/data/List}otherList*@return{module:echarts/data/DataDiffer}*/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); });};/***Getvisualproperty.*@param{string}key*/listProto.getVisual = function (key) { var visual = this._visual; return visual && visual[key];};/***Setvisualproperty*@param{string|Object}key*@param{*}[value]**@example*setVisual('color',color);*setVisual({*'color':color*});*/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;};/***Setlayoutproperty.*@param{string|Object}key*@param{*}[val]*/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;};/***Getlayoutproperty.*@param{string}key.*@return{*}*/listProto.getLayout = function (key) { return this._layout[key];};/***Getlayoutofsingledataitem*@param{number}idx*/listProto.getItemLayout = function (idx) { return this._itemLayouts[idx];};/***Setlayoutofsingledataitem*@param{number}idx*@param{Object}layout*@param{boolean=}[merge=false]*/listProto.setItemLayout = function (idx, layout, merge$$1) { this._itemLayouts[idx] = merge$$1? extend(this._itemLayouts[idx] || {}, layout) : layout;};/***Clearalllayoutofsingledataitem*/listProto.clearItemLayouts = function () { this._itemLayouts.length = 0;};/***Getvisualpropertyofsingledataitem*@param{number}idx*@param{string}key*@param{boolean}[ignoreParent=false]*/listProto.getItemVisual = function (idx, key, ignoreParent) { var itemVisual = this._itemVisuals[idx]; var val = itemVisual && itemVisual[key]; if (val == null && !ignoreParent) { //Useglobalvisualpropertyreturnthis.getVisual(key);}returnval;};/** * Set visual property of single data item * * @param {number} idx * @param {string|Object} key * @param {*} [value] * * @example * setItemVisual(0, 'color', color); * setItemVisual(0, { * 'color': color * }); */listProto.setItemVisual=function(idx,key,value){varitemVisual=this._itemVisuals[idx]||{};varhasItemVisual=this.hasItemVisual;this._itemVisuals[idx]=itemVisual;if(isObject$4(key)){for(varnameinkey){if(key.hasOwnProperty(name)){itemVisual[name]=key[name];hasItemVisual[name]=true;}}return;}itemVisual[key]=value;hasItemVisual[key]=true;};/** * Clear itemVisuals and list visual. */listProto.clearAllVisual=function(){this._visual={};this._itemVisuals=[];this.hasItemVisual={};};varsetItemDataAndSeriesIndex=function(child){child.seriesIndex=this.seriesIndex;child.dataIndex=this.dataIndex;child.dataType=this.dataType;};/** * Set graphic element relative to data. It can be set as null * @param {number} idx * @param {module:zrender/Element}[el]*/listProto.setItemGraphicEl = function (idx, el) { var hostModel = this.hostModel; if (el) { //Adddataindexandseriesindexforindexingthedatabyelement// Useful in tooltipel.dataIndex=idx;el.dataType=this.dataType;el.seriesIndex=hostModel&&hostModel.seriesIndex;if(el.type==='group'){el.traverse(setItemDataAndSeriesIndex,el);}}this._graphicEls[idx]=el;};/** * @param {number} idx * @return {module:zrender/Element}*/listProto.getItemGraphicEl = function (idx) { return this._graphicEls[idx];};/***@param{Function}cb*@param{*}context*/listProto.eachItemGraphicEl = function (cb, context) { each$1(this._graphicEls, function (el, idx) { if (el) { cb && cb.call(context, el, idx); } });};/***Shallowcloneanewlistexceptvisualandlayoutproperties,andgraphelements.*Newlistonlychangetheindices.*/listProto.cloneShallow = function (list) { if (!list) { var dimensionInfoList = map(this.dimensions, this.getDimensionInfo, this); list = new List(dimensionInfoList, this.hostModel); } //FIXMElist._storage=this._storage;transferProperties(list,this);// Clone will not change the data extent and indicesif(this._indices){varCtor=this._indices.constructor;list._indices=newCtor(this._indices);}else{list._indices=null;}list.getRawIndex=list._indices?getRawIndexWithIndices:getRawIndexWithoutIndices;returnlist;};/** * Wrap some method to add more feature * @param {string} methodName * @param {Function} injectFunction */listProto.wrapMethod=function(methodName,injectFunction){varoriginalMethod=this[methodName];if(typeoforiginalMethod!=='function'){return;}this.__wrappedMethods=this.__wrappedMethods||[];this.__wrappedMethods.push(methodName);this[methodName]=function(){varres=originalMethod.apply(this,arguments);returninjectFunction.apply(this,[res].concat(slice(arguments)));};};// Methods that create a new list based on this list should be listed here.// Notice that those method should `RETURN` the new list.listProto.TRANSFERABLE_METHODS=['cloneShallow','downSample','map'];// Methods that change indices of this list should be listed here.listProto.CHANGABLE_METHODS=['filterSelf','selectRange'];/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@deprecated*Use`echarts/data/helper/createDimensions`instead.*//***@see{module:echarts/test/ut/spec/data/completeDimensions}**Completethedimensionsarray,byuserdefined`dimension`and`encode`,*andguessingfromthedatastructure.*Ifno'value'dimensionspecified,thefirstno-nameddimensionwillbe*namedas'value'.**@param{Array.<string>}sysDimsNecessarydimensions,like['x','y'],which*providesnotonlydimtemplate,butalsodefaultorder.*properties:'name','type','displayName'.*`name`ofeachitemprovidesdefaultcoordname.*[{dimsDef:[string|Object,...]},...]dimsDefofsysDimitemprovidesdefaultdimname,and*providedimscountthatthesysDimrequired.*[{ordinalMeta}]canbespecified.*@param{module:echarts/data/Source|Array|Object}sourceordata(forcompatibalwithpervious)*@param{Object}[opt]*@param{Array.<Object|string>}[opt.dimsDef]option.series.dimensionsUserdefineddimensions*Forexample:['asdf',{name,type},...].*@param{Object|HashMap}[opt.encodeDef]option.series.encode{x:2,y:[3,1],tooltip:[1,2],label:3}*@param{string}[opt.generateCoord]Generatecoorddimwiththegivenname.*Ifnotspecified,extradimnameswillbe:*'value','value0','value1',...*@param{number}[opt.generateCoordCount]Bydefault,thegenerateddimnameis`generateCoord`.*If`generateCoordCount`specified,thegenerateddimnameswillbe:*`generateCoord`+0,`generateCoord`+1,...*canbeInfinity,indicatethatusealloftheremaincolumns.*@param{number}[opt.dimCount]Ifnotspecified,guessbythefirstdataitem.*@param{number}[opt.encodeDefaulter]Ifnotspecified,autofindthenextavailabledatadim.*@return{Array.<Object>}[{*name:stringmandatory,*displayName:string,theoriginnameindimsDef,seesourcehelper.*IfdisplayNamegiven,thetooltipwilldisplayedvertically.*coordDim:stringmandatory,*coordDimIndex:numbermandatory,*type:stringoptional,*otherDims:{nevernull/undefined*tooltip:numberoptional,*label:numberoptional,*itemName:numberoptional,*seriesName:numberoptional,*},*isExtraCoord:booleantrueifcoordisgenerated*(notspecifiedinencodeandnotseriesspecified)*otherprops...*}]*/function completeDimensions(sysDims, source, opt) { if (!Source.isInstance(source)) { source = Source.seriesDataToSource(source); } opt = opt || {}; sysDims = (sysDims || []).slice(); var dimsDef = (opt.dimsDef || []).slice(); var encodeDef = createHashMap(opt.encodeDef); var dataDimNameMap = createHashMap(); var coordDimNameMap = createHashMap(); //varvalueCandidate;varresult=[];vardimCount=getDimCount(source,sysDims,dimsDef,opt.dimCount);// Apply user defined dims (`name` and `type`) and init result.for(vari=0;i<dimCount;i++){vardimDefItem=dimsDef[i]=extend({},isObject$1(dimsDef[i])?dimsDef[i]:{name:dimsDef[i]});varuserDimName=dimDefItem.name;varresultItem=result[i]={otherDims:{}};// Name will be applied later for avoiding duplication.if(userDimName!=null&&dataDimNameMap.get(userDimName)==null){// Only if `series.dimensions` is defined in option// displayName, will be set, and dimension will be diplayed vertically in// tooltip by default.resultItem.name=resultItem.displayName=userDimName;dataDimNameMap.set(userDimName,i);}dimDefItem.type!=null&&(resultItem.type=dimDefItem.type);dimDefItem.displayName!=null&&(resultItem.displayName=dimDefItem.displayName);}// Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.encodeDef.each(function(dataDims,coordDim){dataDims=normalizeToArray(dataDims).slice();// Note: It is allowed that `dataDims.length` is `0`, e.g., options is// `{encode: {x: -1, y: 1}}`. Should not filter anything in// this case.if(dataDims.length===1&&dataDims[0]<0){encodeDef.set(coordDim,false);return;}varvalidDataDims=encodeDef.set(coordDim,[]);each$1(dataDims,function(resultDimIdx,idx){// The input resultDimIdx can be dim name or index.isString(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`.varavailDimIdx=0;each$1(sysDims,function(sysDimItem,sysDimIndex){varcoordDim;varsysDimItem;varsysDimItemDimsDef;varsysDimItemOtherDims;if(isString(sysDimItem)){coordDim=sysDimItem;sysDimItem={};}else{coordDim=sysDimItem.name;varordinalMeta=sysDimItem.ordinalMeta;sysDimItem.ordinalMeta=null;sysDimItem=clone(sysDimItem);sysDimItem.ordinalMeta=ordinalMeta;// `coordDimIndex` should not be set directly.sysDimItemDimsDef=sysDimItem.dimsDef;sysDimItemOtherDims=sysDimItem.otherDims;sysDimItem.name=sysDimItem.coordDim=sysDimItem.coordDimIndex=sysDimItem.dimsDef=sysDimItem.otherDims=null;}vardataDims=encodeDef.get(coordDim);// negative resultDimIdx means no need to mapping.if(dataDims===false){return;}vardataDims=normalizeToArray(dataDims);// dimensions provides default dim sequences.if(!dataDims.length){for(vari=0;i<(sysDimItemDimsDef&&sysDimItemDimsDef.length||1);i++){while(availDimIdx<result.length&&result[availDimIdx].coordDim!=null){availDimIdx++;}availDimIdx<result.length&&dataDims.push(availDimIdx++);}}// Apply templates.each$1(dataDims,function(resultDimIdx,coordDimIndex){varresultItem=result[resultDimIdx];applyDim(defaults(resultItem,sysDimItem),coordDim,coordDimIndex);if(resultItem.name==null&&sysDimItemDimsDef){varsysDimItemDimsDefItem=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}}sysDimItemOtherDims&&defaults(resultItem.otherDims,sysDimItemOtherDims);});});functionapplyDim(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'.vargenerateCoord=opt.generateCoord;vargenerateCoordCount=opt.generateCoordCount;varfromZero=generateCoordCount!=null;generateCoordCount=generateCoord?(generateCoordCount||1):0;varextra=generateCoord||'value';// Set dim `name` and other `coordDim` and other props.for(varresultDimIdx=0;resultDimIdx<dimCount;resultDimIdx++){varresultItem=result[resultDimIdx]=result[resultDimIdx]||{};varcoordDim=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)){resultItem.type='ordinal';}}returnresult;}// ??? TODO// Originally detect dimCount by data[0]. Should we// optimize it to only by sysDims and dimensions and encode.// So only necessary dims will be initialized.// But// (1) custom series should be considered. where other dims// may be visited.// (2) sometimes user need to calcualte bubble size or use visualMap// on other dimensions besides coordSys needed.// So, dims that is not used by system, should be shared in storage?functiongetDimCount(source,sysDims,dimsDef,optDimCount){// Note that the result dimCount should not small than columns count// of data, otherwise `dataDimNameMap` checking will be incorrect.vardimCount=Math.max(source.dimensionsDetectCount||1,sysDims.length,dimsDef.length,optDimCount||0);each$1(sysDims,function(sysDimItem){varsysDimItemDimsDef=sysDimItem.dimsDef;sysDimItemDimsDef&&(dimCount=Math.max(dimCount,sysDimItemDimsDef.length));});returndimCount;}functiongenName(name,map$$1,fromZero){if(fromZero||map$$1.get(name)!=null){vari=0;while(map$$1.get(name+i)!=null){i++;}name+=i;}map$$1.set(name,true);returnname;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Substitute`completeDimensions`.*`completeDimensions`istobedeprecated.*//***@param{module:echarts/data/Source|module:echarts/data/List}sourceordata.*@param{Object|Array}[opt]*@param{Array.<string|Object>}[opt.coordDimensions=[]]*@param{number}[opt.dimensionsCount]*@param{string}[opt.generateCoord]*@param{string}[opt.generateCoordCount]*@param{Array.<string|Object>}[opt.dimensionsDefine=source.dimensionsDefine]Overwritesourcedefine.*@param{Object|HashMap}[opt.encodeDefine=source.encodeDefine]Overwritesourcedefine.*@return{Array.<Object>}dimensionsInfo*/var createDimensions = function (source, opt) { opt = opt || {}; return completeDimensions(opt.coordDimensions || [], source, { dimsDef: opt.dimensionsDefine || source.dimensionsDefine, encodeDef: opt.encodeDefine || source.encodeDefine, dimCount: opt.dimensionsCount, generateCoord: opt.generateCoord, generateCoordCount: opt.generateCoordCount });};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Notethatitistoocomplicatedtosupport3dstackbyvalue*(havetocreatetwo-dimensioninvertedindex),soin3dcase*wejustsupportthatstackedbyindex.**@param{module:echarts/model/Series}seriesModel*@param{Array.<string|Object>}dimensionInfoListThesameastheinputof<module:echarts/data/List>.*TheinputdimensionInfoListwillbemodified.*@param{Object}[opt]*@param{boolean}[opt.stackedCoordDimension='']Specifyacoorddimensionifneeded.*@param{boolean}[opt.byIndex=false]*@return{Object}calculationInfo*{*stackedDimension:string*stackedByDimension:string*isStackedByIndex:boolean*stackedOverDimension:string*stackResultDimension:string*}*/function enableDataStack(seriesModel, dimensionInfoList, opt) { opt = opt || {}; var byIndex = opt.byIndex; var stackedCoordDimension = opt.stackedCoordDimension; //Compatibal:when`stack`issetas'',donotstack.varmayStack=!!(seriesModel&&seriesModel.get('stack'));varstackedByDimInfo;varstackedDimInfo;varstackResultDimension;varstackedOverDimension;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.if(!byIndex&&!stackedByDimInfo&&dimensionInfo.ordinalMeta){stackedByDimInfo=dimensionInfo;}// Find the first stackable dimension as the stackedDimInfo.if(!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.// It may make sense if the user provides elaborately constructed data.byIndex=true;}// Add stack dimension, they can be both calculated by coordinate system in `unionExtent`.// That put stack logic in List is for using conveniently in echarts extensions, but it// might not be a good way.if(stackedDimInfo){// Use a weird name that not duplicated with other names.stackResultDimension='__\0ecstackresult';stackedOverDimension='__\0ecstackedover';// Create inverted index to fast query index by value.if(stackedByDimInfo){stackedByDimInfo.createInvertedIndices=true;}varstackedDimCoordDim=stackedDimInfo.coordDim;varstackedDimType=stackedDimInfo.type;varstackedDimCoordIndex=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// `stackedDimCoordDim` to avoid extent calculation, consider log scale.coordDim:stackedOverDimension,coordDimIndex:stackedDimCoordIndex,type:stackedDimType,isExtraCoord:true,isCalculationCoord:true});}return{stackedDimension:stackedDimInfo&&stackedDimInfo.name,stackedByDimension:stackedByDimInfo&&stackedByDimInfo.name,isStackedByIndex:byIndex,stackedOverDimension:stackedOverDimension,stackResultDimension:stackResultDimension};}/** * @param {module:echarts/data/List}data*@param{string}stackedDim*/function isDimensionStacked(data, stackedDim /*,stackedByDim*/) { //Eachsingleseriesonlymapstoonepairofaxis.Sowedonotneedto// check stackByDim, whatever stacked by a dimension or stacked by index.return!!stackedDim&&stackedDim===data.getCalculationInfo('stackedDimension');// && (// stackedByDim != null// ? stackedByDim === data.getCalculationInfo('stackedByDimension')// : data.getCalculationInfo('isStackedByIndex')// );}/** * @param {module:echarts/data/List}data*@param{string}targetDim*@param{string}[stackedByDim]Ifnotinputthisparameter,checkwhether*stackedbyindex.*@return{string}dimension*/function getStackedDimension(data, targetDim) { return isDimensionStacked(data, targetDim)? data.getCalculationInfo('stackResultDimension') : targetDim;}/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@param{module:echarts/data/Source|Array}sourceOrrawdata.*@param{module:echarts/model/Series}seriesModel*@param{Object}[opt]*@param{string}[opt.generateCoord]*/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 coordSysDefine = getCoordSysDefineBySeries(seriesModel); var coordSysDimDefs; if (coordSysDefine) { coordSysDimDefs = map(coordSysDefine.coordSysDims, function (dim) { var dimInfo = {name: dim}; var axisModel = coordSysDefine.axisMap.get(dim); if (axisModel) { var axisType = axisModel.get('type'); dimInfo.type = getDimensionTypeByAxis(axisType); //dimInfo.stackable=isStackable(axisType);}returndimInfo;});}if(!coordSysDimDefs){// Get dimensions from registered coordinate systemcoordSysDimDefs=(registeredCoordSys&&(registeredCoordSys.getDimensionsInfo?registeredCoordSys.getDimensionsInfo():registeredCoordSys.dimensions.slice()))||['x','y'];}vardimInfoList=createDimensions(source,{coordDimensions:coordSysDimDefs,generateCoord:opt.generateCoord});varfirstCategoryDimIndex;varhasNameEncode;coordSysDefine&&each$1(dimInfoList,function(dimInfo,dimIndex){varcoordDim=dimInfo.coordDim;varcategoryAxisModel=coordSysDefine.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;}varstackCalculationInfo=enableDataStack(seriesModel,dimInfoList);varlist=newList(dimInfoList,seriesModel);list.setCalculationInfo(stackCalculationInfo);vardimValueGetter=(firstCategoryDimIndex!=null&&isNeedCompleteOrdinalData(source))?function(itemOpt,dimName,dataIndex,dimIndex){// Use dataIndex as ordinal value in categoryAxisreturndimIndex===firstCategoryDimIndex?dataIndex:this.defaultDimValueGetter(itemOpt,dimName,dataIndex,dimIndex);}:null;list.hasItemOption=false;list.initData(source,null,dimValueGetter);returnlist;}functionisNeedCompleteOrdinalData(source){if(source.sourceFormat===SOURCE_FORMAT_ORIGINAL){varsampleItem=firstDataNotNull(source.data||[]);returnsampleItem!=null&&!isArray(getDataItemValue(sampleItem));}}functionfirstDataNotNull(data){vari=0;while(i<data.length&&data[i]==null){i++;}returndata[i];}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/SeriesModel.extend({ type: 'series.line', dependencies: ['grid', 'polar'], getInitialData: function (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); }, defaultOption: { zlevel: 0, z: 2, coordinateSystem: 'cartesian2d', legendHoverLink: true, hoverAnimation: true, //stack:null// xAxisIndex: 0,// yAxisIndex: 0,// polarIndex: 0,// If clip the overflow valueclipOverflow:true,// cursor: null,label:{position:'top'},// itemStyle: {// },lineStyle:{width:2,type:'solid'},// areaStyle: {// origin of areaStyle. Valid values:// `'auto'/null/undefined`: from axisLine to data// `'start'`: from min to data// `'end'`: from data to max// origin: 'auto'// },// false, 'start', 'end', 'middle'step:false,// Disabled if step is truesmooth:false,smoothMonotone:null,symbol:'emptyCircle',symbolSize:4,symbolRotate:null,showSymbol:true,// `false`: follow the label interval strategy.// `true`: show all symbols.// `'auto'`: If possible, show all symbols, otherwise// follow the label interval strategy.showAllSymbol:'auto',// Whether to connect break point.connectNulls:false,// Sampling for large data. Can be: 'average', 'max', 'min', 'sum'.sampling:'none',animationEasing:'linear',// Disable progressiveprogressive:0,hoverLayerThreshold:Infinity}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Symbolbase_factory/***Triangleshape*@inner*/var Triangle = extendShape({ type: 'triangle', shape: { cx: 0, cy: 0, width: 0, height: 0 }, buildPath: function (path, shape) { var cx = shape.cx; var cy = shape.cy; var width = shape.width /2;varheight=shape.height/2;path.moveTo(cx,cy-height);path.lineTo(cx+width,cy+height);path.lineTo(cx-width,cy+height);path.closePath();}});/** * Diamond shape * @inner */varDiamond=extendShape({type:'diamond',shape:{cx:0,cy:0,width:0,height:0},buildPath:function(path,shape){varcx=shape.cx;varcy=shape.cy;varwidth=shape.width/2;varheight=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();}});/** * Pin shape * @inner */varPin=extendShape({type:'pin',shape:{// x, y on the cuspx:0,y:0,width:0,height:0},buildPath:function(path,shape){varx=shape.x;vary=shape.y;varw=shape.width/5*3;// Height must be larger than widthvarh=Math.max(w,shape.height);varr=w/2;// Dist on y with tangent point and circle centervardy=r*r/(h-r);varcy=y-h+r+dy;varangle=Math.asin(dy/r);// Dist on x with tangent point and circle centervardx=Math.cos(angle)*r;vartanX=Math.sin(angle);vartanY=Math.cos(angle);varcpLen=r*0.6;varcpLen2=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();}});/** * Arrow shape * @inner */varArrow=extendShape({type:'arrow',shape:{x:0,y:0,width:0,height:0},buildPath:function(ctx,shape){varheight=shape.height;varwidth=shape.width;varx=shape.x;vary=shape.y;vardx=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();}});/** * Map of path contructors * @type {Object.<string, module:zrender/graphic/Path>}*/var symbolCtors = { line: Line, rect: Rect, roundRect: Rect, square: Rect, circle: Circle, diamond: Diamond, pin: Pin, arrow: Arrow, triangle: Triangle};var symbolShapeMakers = { line: function (x, y, w, h, shape) { //FIXMEshape.x1=x;shape.y1=y+h/2;shape.x2=x+w;shape.y2=y+h/2;},rect:function(x,y,w,h,shape){shape.x=x;shape.y=y;shape.width=w;shape.height=h;},roundRect:function(x,y,w,h,shape){shape.x=x;shape.y=y;shape.width=w;shape.height=h;shape.r=Math.min(w,h)/4;},square:function(x,y,w,h,shape){varsize=Math.min(w,h);shape.x=x;shape.y=y;shape.width=size;shape.height=size;},circle:function(x,y,w,h,shape){// Put circle in the center of squareshape.cx=x+w/2;shape.cy=y+h/2;shape.r=Math.min(w,h)/2;},diamond:function(x,y,w,h,shape){shape.cx=x+w/2;shape.cy=y+h/2;shape.width=w;shape.height=h;},pin:function(x,y,w,h,shape){shape.x=x+w/2;shape.y=y+h/2;shape.width=w;shape.height=h;},arrow:function(x,y,w,h,shape){shape.x=x+w/2;shape.y=y+h/2;shape.width=w;shape.height=h;},triangle:function(x,y,w,h,shape){shape.cx=x+w/2;shape.cy=y+h/2;shape.width=w;shape.height=h;}};varsymbolBuildProxies={};each$1(symbolCtors,function(Ctor,name){symbolBuildProxies[name]=newCtor();});varSymbolClz$2=extendShape({type:'symbol',shape:{symbolType:'',x:0,y:0,width:0,height:0},beforeBrush:function(){varstyle=this.style;varshape=this.shape;// FIXMEif(shape.symbolType==='pin'&&style.textPosition==='inside'){style.textPosition=['50%','40%'];style.textAlign='center';style.textVerticalAlign='middle';}},buildPath:function(ctx,shape,inBundle){varsymbolType=shape.symbolType;varproxySymbol=symbolBuildProxies[symbolType];if(shape.symbolType!=='none'){if(!proxySymbol){// Default rectsymbolType='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 outsidefunctionsymbolPathSetColor(color,innerColor){if(this.type!=='image'){varsymbolStyle=this.style;varsymbolShape=this.shape;if(symbolShape&&symbolShape.symbolType==='line'){symbolStyle.stroke=color;}elseif(this.__isEmptyBrush){symbolStyle.stroke=color;symbolStyle.fill=innerColor||'#fff';}else{// FIXME 判断图形默认是填充还是描边,使用 onlyStroke ?symbolStyle.fill&&(symbolStyle.fill=color);symbolStyle.stroke&&(symbolStyle.stroke=color);}this.dirty(false);}}/** * Create a symbol element with given symbol configuration: shape, x, y, width, height, color * @param {string} symbolType * @param {number} x * @param {number} y * @param {number} w * @param {number} h * @param {string} color * @param {boolean} [keepAspect=false] whether to keep the ratio of w/h,*forpathandimageonly.*/function createSymbol(symbolType, x, y, w, h, color, keepAspect) { //TODOSupportimageobject,DynamicImage.varisEmpty=symbolType.indexOf('empty')===0;if(isEmpty){symbolType=symbolType.substr(5,1).toLowerCase()+symbolType.substr(6);}varsymbolPath;if(symbolType.indexOf('image://')===0){symbolPath=makeImage(symbolType.slice(8),newBoundingRect(x,y,w,h),keepAspect?'center':'cover');}elseif(symbolType.indexOf('path://')===0){symbolPath=makePath(symbolType.slice(7),{},newBoundingRect(x,y,w,h),keepAspect?'center':'cover');}else{symbolPath=newSymbolClz$2({shape:{symbolType:symbolType,x:x,y:y,width:w,height:h}});}symbolPath.__isEmptyBrush=isEmpty;symbolPath.setColor=symbolPathSetColor;symbolPath.setColor(color);returnsymbolPath;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@param{module:echarts/data/List}data*@param{number}dataIndex*@return{string}labelstring.Notnull/undefined*/function getDefaultLabel(data, dataIndex) { var labelDims = data.mapDimension('defaultedLabel', true); var len = labelDims.length; //Simpleoptimization(inlotsofcases,labeldimslengthis1)if(len===1){returnretrieveRawValue(data,dataIndex,labelDims[0]);}elseif(len){varvals=[];for(vari=0;i<labelDims.length;i++){varval=retrieveRawValue(data,dataIndex,labelDims[i]);vals.push(val);}returnvals.join(' ');}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@moduleecharts/chart/helper/Symbol*//***@constructor*@alias{module:echarts/chart/helper/Symbol}*@param{module:echarts/data/List}data*@param{number}idx*@extends{module:zrender/graphic/Group}*/function SymbolClz(data, idx, seriesScope) { Group.call(this); this.updateData(data, idx, seriesScope);}var symbolProto = SymbolClz.prototype;/***@public*@static*@param{module:echarts/data/List}data*@param{number}dataIndex*@return{Array.<number>}[width,height]*/var getSymbolSize = SymbolClz.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];}functiondriftSymbol(dx,dy){this.parent.drift(dx,dy);}symbolProto._createSymbol=function(symbolType,data,idx,symbolSize,keepAspect){// Remove paths created beforethis.removeAll();varcolor=data.getItemVisual(idx,'color');// var symbolPath = createSymbol(// symbolType, -0.5, -0.5, 1, 1, color// );// If width/height are set too small (e.g., set to 1) on ios10// and macOS Sierra, a circle stroke become a rect, no matter what// the scale is set. So we set width/height as 2. See #4150.varsymbolPath=createSymbol(symbolType,-1,-1,2,2,color,keepAspect);symbolPath.attr({z2:100,culling:true,scale:getScale(symbolSize)});// Rewrite drift methodsymbolPath.drift=driftSymbol;this._symbolType=symbolType;this.add(symbolPath);};/** * Stop animation * @param {boolean} toLastFrame */symbolProto.stopSymbolAnimation=function(toLastFrame){this.childAt(0).stopAnimation(toLastFrame);};/** * FIXME: * Caution: This method breaks the encapsulation of this module, * but it indeed brings convenience. So do not use the method * unless you detailedly know all the implements of `Symbol`, * especially animation. * * Get symbol path element. */symbolProto.getSymbolPath=function(){returnthis.childAt(0);};/** * Get scale(aka, current symbol size). * Including the change caused by animation */symbolProto.getScale=function(){returnthis.childAt(0).scale;};/** * Highlight symbol */symbolProto.highlight=function(){this.childAt(0).trigger('emphasis');};/** * Downplay symbol */symbolProto.downplay=function(){this.childAt(0).trigger('normal');};/** * @param {number} zlevel * @param {number} z */symbolProto.setZ=function(zlevel,z){varsymbolPath=this.childAt(0);symbolPath.zlevel=zlevel;symbolPath.z=z;};symbolProto.setDraggable=function(draggable){varsymbolPath=this.childAt(0);symbolPath.draggable=draggable;symbolPath.cursor=draggable?'move':'pointer';};/** * Update symbol properties * @param {module:echarts/data/List}data*@param{number}idx*@param{Object}[seriesScope]*@param{Object}[seriesScope.itemStyle]*@param{Object}[seriesScope.hoverItemStyle]*@param{Object}[seriesScope.symbolRotate]*@param{Object}[seriesScope.symbolOffset]*@param{module:echarts/model/Model}[seriesScope.labelModel]*@param{module:echarts/model/Model}[seriesScope.hoverLabelModel]*@param{boolean}[seriesScope.hoverAnimation]*@param{Object}[seriesScope.cursorStyle]*@param{module:echarts/model/Model}[seriesScope.itemModel]*@param{string}[seriesScope.symbolInnerColor]*@param{Object}[seriesScope.fadeIn=false]*/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;};//UpdatecommonpropertiesvarnormalStyleAccessPath=['itemStyle'];varemphasisStyleAccessPath=['emphasis','itemStyle'];varnormalLabelAccessPath=['label'];varemphasisLabelAccessPath=['emphasis','label'];/** * @param {module:echarts/data/List}data*@param{number}idx*@param{Array.<number>}symbolSize*@param{Object}[seriesScope]*/symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) { var symbolPath = this.childAt(0); var seriesModel = data.hostModel; var color = data.getItemVisual(idx, 'color'); //Resetstyleif(symbolPath.type!=='image'){symbolPath.useStyle({strokeNoScale:true});}varitemStyle=seriesScope&&seriesScope.itemStyle;varhoverItemStyle=seriesScope&&seriesScope.hoverItemStyle;varsymbolRotate=seriesScope&&seriesScope.symbolRotate;varsymbolOffset=seriesScope&&seriesScope.symbolOffset;varlabelModel=seriesScope&&seriesScope.labelModel;varhoverLabelModel=seriesScope&&seriesScope.hoverLabelModel;varhoverAnimation=seriesScope&&seriesScope.hoverAnimation;varcursorStyle=seriesScope&&seriesScope.cursorStyle;if(!seriesScope||data.hasItemOption){varitemModel=(seriesScope&&seriesScope.itemModel)?seriesScope.itemModel:data.getItemModel(idx);// Color must be excluded.// Because symbol provide setColor individually to set fill and strokeitemStyle=itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']);hoverItemStyle=itemModel.getModel(emphasisStyleAccessPath).getItemStyle();symbolRotate=itemModel.getShallow('symbolRotate');symbolOffset=itemModel.getShallow('symbolOffset');labelModel=itemModel.getModel(normalLabelAccessPath);hoverLabelModel=itemModel.getModel(emphasisLabelAccessPath);hoverAnimation=itemModel.getShallow('hoverAnimation');cursorStyle=itemModel.getShallow('cursor');}else{hoverItemStyle=extend({},hoverItemStyle);}varelStyle=symbolPath.style;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!!!symbolPath.setColor(color,seriesScope&&seriesScope.symbolInnerColor);symbolPath.setStyle(itemStyle);varopacity=data.getItemVisual(idx,'opacity');if(opacity!=null){elStyle.opacity=opacity;}varliftZ=data.getItemVisual(idx,'liftZ');varz2Origin=symbolPath.__z2Origin;if(liftZ!=null){if(z2Origin==null){symbolPath.__z2Origin=symbolPath.z2;symbolPath.z2+=liftZ;}}elseif(z2Origin!=null){symbolPath.z2=z2Origin;symbolPath.__z2Origin=null;}varuseNameLabel=seriesScope&&seriesScope.useNameLabel;setLabelStyle(elStyle,hoverItemStyle,labelModel,hoverLabelModel,{labelFetcher:seriesModel,labelDataIndex:idx,defaultText:getLabelDefaultText,isRectText:true,autoColor:color});// Do not execute util needed.functiongetLabelDefaultText(idx,opt){returnuseNameLabel?data.getName(idx):getDefaultLabel(data,idx);}symbolPath.off('mouseover').off('mouseout').off('emphasis').off('normal');symbolPath.hoverStyle=hoverItemStyle;// FIXME// Do not use symbol.trigger('emphasis'), but use symbol.highlight() instead.setHoverStyle(symbolPath);symbolPath.__symbolOriginalScale=getScale(symbolSize);if(hoverAnimation&&seriesModel.isAnimationEnabled()){// Note: consider `off`, should use static function here.symbolPath.on('mouseover',onMouseOver).on('mouseout',onMouseOut).on('emphasis',onEmphasis).on('normal',onNormal);}};functiononMouseOver(){// see comment in `graphic.isInEmphasis`!isInEmphasis(this)&&onEmphasis.call(this);}functiononMouseOut(){// see comment in `graphic.isInEmphasis`!isInEmphasis(this)&&onNormal.call(this);}functiononEmphasis(){// Do not support this hover animation util some scenario required.// Animation can only be supported in hover layer when using `el.incremetal`.if(this.incremental||this.useHoverLayer){return;}varscale=this.__symbolOriginalScale;varratio=scale[1]/scale[0];this.animateTo({scale:[Math.max(scale[0]*1.1,scale[0]+3),Math.max(scale[1]*1.1,scale[1]+3*ratio)]},400,'elasticOut');}functiononNormal(){if(this.incremental||this.useHoverLayer){return;}this.animateTo({scale:this.__symbolOriginalScale},400,'elasticOut');}/** * @param {Function} cb * @param {Object} [opt] * @param {Object} [opt.keepLabel=true] */symbolProto.fadeOut=function(cb,opt){varsymbolPath=this.childAt(0);// Avoid mistaken hover when fading outthis.silent=symbolPath.silent=true;// Not show text when animating!(opt&&opt.keepLabel)&&(symbolPath.style.text=null);updateProps(symbolPath,{style:{opacity:0},scale:[0,0]},this._seriesModel,this.dataIndex,cb);};inherits(SymbolClz,Group);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@moduleecharts/chart/helper/SymbolDraw*//***@constructor*@aliasmodule:echarts/chart/helper/SymbolDraw*@param{module:zrender/graphic/Group}[symbolCtor]*/function SymbolDraw(symbolCtor) { this.group = new Group(); this._symbolCtor = symbolCtor || SymbolClz;}var symbolDrawProto = SymbolDraw.prototype;function symbolNeedsDraw(data, point, idx, opt) { return point && !isNaN(point[0]) && !isNaN(point[1]) && !(opt.isIgnore && opt.isIgnore(idx)) //WedonotsetclipShapeongroup,becauseitwillcutpartof// the symbol element shape. We use the same clip shape here as// the line clip.&&!(opt.clipShape&&!opt.clipShape.contain(point[0],point[1]))&&data.getItemVisual(idx,'symbol')!=='none';}/** * Update symbols draw by new data * @param {module:echarts/data/List}data*@param{Object}[opt]OrisIgnore*@param{Function}[opt.isIgnore]*@param{Object}[opt.clipShape]*/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); //ThereisnooldLineDataonlywhenfirstrenderingorswitchingfrom// stream mode to normal mode, where previous elements should be removed.if(!oldData){group.removeAll();}data.diff(oldData).add(function(newIdx){varpoint=data.getItemLayout(newIdx);if(symbolNeedsDraw(data,point,newIdx,opt)){varsymbolEl=newSymbolCtor(data,newIdx,seriesScope);symbolEl.attr('position',point);data.setItemGraphicEl(newIdx,symbolEl);group.add(symbolEl);}}).update(function(newIdx,oldIdx){varsymbolEl=oldData.getItemGraphicEl(oldIdx);varpoint=data.getItemLayout(newIdx);if(!symbolNeedsDraw(data,point,newIdx,opt)){group.remove(symbolEl);return;}if(!symbolEl){symbolEl=newSymbolCtor(data,newIdx);symbolEl.attr('position',point);}else{symbolEl.updateData(data,newIdx,seriesScope);updateProps(symbolEl,{position:point},seriesModel);}// Add backgroup.add(symbolEl);data.setItemGraphicEl(newIdx,symbolEl);}).remove(function(oldIdx){varel=oldData.getItemGraphicEl(oldIdx);el&&el.fadeOut(function(){group.remove(el);});}).execute();this._data=data;};symbolDrawProto.isPersistent=function(){returntrue;};symbolDrawProto.updateLayout=function(){vardata=this._data;if(data){// Not use animationdata.eachItemGraphicEl(function(el,idx){varpoint=data.getItemLayout(idx);el.attr('position',point);});}};symbolDrawProto.incrementalPrepareUpdate=function(data){this._seriesScope=makeSeriesScope(data);this._data=null;this.group.removeAll();};/** * Update symbols draw by new data * @param {module:echarts/data/List}data*@param{Object}[opt]OrisIgnore*@param{Function}[opt.isIgnore]*@param{Object}[opt.clipShape]*/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; //Incrementalmodeldonothavethis._data.if(data&&enableAnimation){data.eachItemGraphicEl(function(el){el.fadeOut(function(){group.remove(el);});});}else{group.removeAll();}};functionmakeSeriesScope(data){varseriesModel=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')};}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@param{Object}coordSys*@param{module:echarts/data/List}data*@param{string}valueOriginlineSeries.option.areaStyle.origin*/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]*/)) { //jshintignore:linedims[0]=stackResultDim;}if(stacked|=isDimensionStacked(data,dims[1]/*, dims[0]*/)){// jshint ignore:linedims[1]=stackResultDim;}return{dataDimsForPoint:dims,valueStart:valueStart,valueAxisDim:valueAxisDim,baseAxisDim:baseAxisDim,stacked:!!stacked,valueDim:valueDim,baseDim:baseDim,baseDataOffset:baseDataOffset,stackedOverDimension:data.getCalculationInfo('stackedOverDimension')};}functiongetValueStart(valueAxis,valueOrigin){varvalueStart=0;varextent=valueAxis.scale.getExtent();if(valueOrigin==='start'){valueStart=extent[0];}elseif(valueOrigin==='end'){valueStart=extent[1];}// autoelse{// Both positiveif(extent[0]>0){valueStart=extent[0];}// Both negativeelseif(extent[1]<0){valueStart=extent[1];}// If is one positive, and one negative, onZero shall be true}returnvalueStart;}functiongetStackedOnPoint(dataCoordInfo,coordSys,data,idx){varvalue=NaN;if(dataCoordInfo.stacked){value=data.get(data.getCalculationInfo('stackedOverDimension'),idx);}if(isNaN(value)){value=dataCoordInfo.valueStart;}varbaseDataOffset=dataCoordInfo.baseDataOffset;varstackedData=[];stackedData[baseDataOffset]=data.get(dataCoordInfo.baseDim,idx);stackedData[1-baseDataOffset]=value;returncoordSys.dataToPoint(stackedData);}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///vararrayDiff=require('zrender/src/core/arrayDiff');// 'zrender/src/core/arrayDiff' has been used before, but it did// not do well in performance when roam with fixed dataZoom window.// function convertToIntId(newIdList, oldIdList) {// // Generate int id instead of string id.// // Compare string maybe slow in score function of arrDiff// // Assume id in idList are all unique// var idIndicesMap = {};// var idx = 0;// for (var i = 0; i < newIdList.length; i++) {// idIndicesMap[newIdList[i]] = idx;// newIdList[i] = idx++;// }// for (var i = 0; i < oldIdList.length; i++) {// var oldId = oldIdList[i];// // Same with newIdList// if (idIndicesMap[oldId]) {// oldIdList[i] = idIndicesMap[oldId];// }// else {// oldIdList[i] = idx++;// }// }// }functiondiffData(oldData,newData){vardiffResult=[];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();returndiffResult;}varlineAnimationDiff=function(oldData,newData,oldStackedOnPoints,newStackedOnPoints,oldCoordSys,newCoordSys,oldValueOrigin,newValueOrigin){vardiff=diffData(oldData,newData);// var newIdList = newData.mapArray(newData.getId);// var oldIdList = oldData.mapArray(oldData.getId);// convertToIntId(newIdList, oldIdList);// // FIXME One data ?// diff = arrayDiff(oldIdList, newIdList);varcurrPoints=[];varnextPoints=[];// Points for stacking base linevarcurrStackedPoints=[];varnextStackedPoints=[];varstatus=[];varsortedIndices=[];varrawIndices=[];varnewDataOldCoordInfo=prepareDataCoordInfo(oldCoordSys,newData,oldValueOrigin);varoldDataNewCoordInfo=prepareDataCoordInfo(newCoordSys,oldData,newValueOrigin);for(vari=0;i<diff.length;i++){vardiffItem=diff[i];varpointAdded=true;// FIXME, animation is not so perfect when dataZoom window moves fast// Which is in case remvoing or add more than one data in the tail or headswitch(diffItem.cmd){case'=':varcurrentPt=oldData.getItemLayout(diffItem.idx);varnextPt=newData.getItemLayout(diffItem.idx1);// If previous data is NaN, use next point directlyif(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'+':varidx=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'-':varidx=diffItem.idx;varrawIndex=oldData.getRawIndex(idx);// Data is replaced. In the case of dynamic data queue// FIXME FIXME FIXMEif(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 indicesif(pointAdded){status.push(diffItem);sortedIndices.push(sortedIndices.length);}}// Diff result may be crossed if all items are changed// Sort by data indexsortedIndices.sort(function(a,b){returnrawIndices[a]-rawIndices[b];});varsortedCurrPoints=[];varsortedNextPoints=[];varsortedCurrStackedPoints=[];varsortedNextStackedPoints=[];varsortedStatus=[];for(vari=0;i<sortedIndices.length;i++){varidx=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};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///PolypathsupportNaNpointvarvec2Min=min;varvec2Max=max;varscaleAndAdd$1=scaleAndAdd;varv2Copy=copy;// Temporary variablevarv=[];varcp0=[];varcp1=[];functionisPointNull(p){returnisNaN(p[0])||isNaN(p[1]);}functiondrawSegment(ctx,points,start,segLen,allLen,dir,smoothMin,smoothMax,smooth,smoothMonotone,connectNulls){// if (smoothMonotone == null) {// if (isMono(points, 'x')) {// return drawMono(ctx, points, start, segLen, allLen,// dir, smoothMin, smoothMax, smooth, 'x', connectNulls);// }// else if (isMono(points, 'y')) {// return drawMono(ctx, points, start, segLen, allLen,// dir, smoothMin, smoothMax, smooth, 'y', connectNulls);// }// else {// return drawNonMono.apply(this, arguments);// }// }// else if (smoothMonotone !== 'none' && isMono(points, smoothMonotone)) {// return drawMono.apply(this, arguments);// }// else {// return drawNonMono.apply(this, arguments);// }if(smoothMonotone==='none'||!smoothMonotone){returndrawNonMono.apply(this,arguments);}else{returndrawMono.apply(this,arguments);}}/** * Check if points is in monotone. * * @param {number[][]} points Array of points which is in [x, y] form * @param {string} smoothMonotone 'x', 'y', or 'none', stating for which * dimension that is checking. * If is 'none', `drawNonMono` should be * called. * If is undefined, either being monotone * in 'x' or 'y' will call `drawMono`. */// function isMono(points, smoothMonotone) {// if (points.length <= 1) {// return true;// }// var dim = smoothMonotone === 'x' ? 0 : 1;// var last = points[0][dim];// var lastDiff = 0;// for (var i = 1; i < points.length; ++i) {// var diff = points[i][dim] - last;// if (!isNaN(diff) && !isNaN(lastDiff)// && diff !== 0 && lastDiff !== 0// && ((diff >= 0) !== (lastDiff >= 0))// ) {// return false;// }// if (!isNaN(diff) && diff !== 0) {// lastDiff = diff;// last = points[i][dim];// }// }// return true;// }/***Drawsmoothedlineinmonotone,inwhichonlyverticalorhorizontalbezier*controlpointswillbeused.Thisshouldbeusedwhenpointsaremonotone*eitherinxorydimension.*/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; //Lengthofcontrolpointtop,eitherinxory,butnotbothvarctrlLen=(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;}returnk;}/** * Draw smoothed line in non-monotone, in may cause undesired curve in extreme * situations. This should be used when points are non-monotone neither in x or * y dimension. */functiondrawNonMono(ctx,points,start,segLen,allLen,dir,smoothMin,smoothMax,smooth,smoothMonotone,connectNulls){varprevIdx=0;varidx=start;for(vark=0;k<segLen;k++){varp=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){varnextIdx=idx+dir;varnextP=points[nextIdx];if(connectNulls){// Find next point not nullwhile(nextP&&isPointNull(points[nextIdx])){nextIdx+=dir;nextP=points[nextIdx];}}varratioNextSeg=0.5;varprevP=points[prevIdx];varnextP=points[nextIdx];// Last pointif(!nextP||isPointNull(nextP)){v2Copy(cp1,p);}else{// If next data is null in not connect caseif(isPointNull(nextP)&&!connectNulls){nextP=p;}sub(v,nextP,prevP);varlenPrevSeg;varlenNextSeg;if(smoothMonotone==='x'||smoothMonotone==='y'){vardim=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 lengthratioNextSeg=lenNextSeg/(lenNextSeg+lenPrevSeg);scaleAndAdd$1(cp1,p,v,-smooth*(1-ratioNextSeg));}// Smooth constraintvec2Min(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 segmentscaleAndAdd$1(cp0,p,v,smooth*ratioNextSeg);}else{ctx.lineTo(p[0],p[1]);}}prevIdx=idx;idx+=dir;}returnk;}functiongetBoundingBox(points,smoothConstraint){varptMin=[Infinity,Infinity];varptMax=[-Infinity,-Infinity];if(smoothConstraint){for(vari=0;i<points.length;i++){varpt=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};}varPolyline$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(ctx,shape){varpoints=shape.points;vari=0;varlen$$1=points.length;varresult=getBoundingBox(points,shape.smoothConstraint);if(shape.connectNulls){// Must remove first and last null values avoid draw error in polygonfor(;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;}}});varPolygon$1=Path.extend({type:'ec-polygon',shape:{points:[],// Offset between stacked base points and pointsstackedOnPoints:[],smooth:0,stackedOnSmooth:0,smoothConstraint:true,smoothMonotone:null,connectNulls:false},brush:fixClipWithShadow(Path.prototype.brush),buildPath:function(ctx,shape){varpoints=shape.points;varstackedOnPoints=shape.stackedOnPoints;vari=0;varlen$$1=points.length;varsmoothMonotone=shape.smoothMonotone;varbbox=getBoundingBox(points,shape.smoothConstraint);varstackedOnBBox=getBoundingBox(stackedOnPoints,shape.smoothConstraint);if(shape.connectNulls){// Must remove first and last null values avoid draw error in polygonfor(;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){vark=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();}}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///FIXMEstepnotsupportpolarfunctionisPointsSame(points1,points2){if(points1.length!==points2.length){return;}for(vari=0;i<points1.length;i++){varp1=points1[i];varp2=points2[i];if(p1[0]!==p2[0]||p1[1]!==p2[1]){return;}}returntrue;}functiongetSmooth(smooth){returntypeof(smooth)==='number'?smooth:(smooth?0.5:0);}functiongetAxisExtentWithGap(axis){varextent=axis.getGlobalExtent();if(axis.onBand){// Remove extra 1px to avoid line miter in clipped edgevarhalfBandWidth=axis.getBandWidth()/2-1;vardir=extent[1]>extent[0]?1:-1;extent[0]+=dir*halfBandWidth;extent[1]-=dir*halfBandWidth;}returnextent;}/** * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar}coordSys*@param{module:echarts/data/List}data*@param{Object}dataCoordInfo*@param{Array.<Array.<number>>}points*/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 createGridClipShape(cartesian, hasAnimation, forSymbol, seriesModel) { var xExtent = getAxisExtentWithGap(cartesian.getAxis('x')); var yExtent = getAxisExtentWithGap(cartesian.getAxis('y')); var isHorizontal = cartesian.getBaseAxis().isHorizontal(); 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; //Avoidfloatnumberroundingerrorforsymbolontheedgeofaxisextent.// See #7913 and `test/dataZoom-clip.html`.if(forSymbol){x-=0.5;width+=0.5;y-=0.5;height+=0.5;}else{varlineWidth=seriesModel.get('lineStyle.width')||2;// Expand clip shape to avoid clipping when line value exceeds axisvarexpandSize=seriesModel.get('clipOverflow')?lineWidth/2:Math.max(width,height);if(isHorizontal){y-=expandSize;height+=expandSize*2;}else{x-=expandSize;width+=expandSize*2;}}varclipPath=newRect({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);}returnclipPath;}functioncreatePolarClipShape(polar,hasAnimation,forSymbol,seriesModel){varangleAxis=polar.getAngleAxis();varradiusAxis=polar.getRadiusAxis();varradiusExtent=radiusAxis.getExtent().slice();radiusExtent[0]>radiusExtent[1]&&radiusExtent.reverse();varangleExtent=angleAxis.getExtent();varRADIAN=Math.PI/180;// Avoid float number rounding error for symbol on the edge of axis extent.if(forSymbol){radiusExtent[0]-=0.5;radiusExtent[1]+=0.5;}varclipPath=newSector({shape:{cx:round$1(polar.cx,1),cy:round$1(polar.cy,1),r0:round$1(radiusExtent[0],1),r:round$1(radiusExtent[1],1),startAngle:-angleExtent[0]*RADIAN,endAngle:-angleExtent[1]*RADIAN,clockwise:angleAxis.inverse}});if(hasAnimation){clipPath.shape.endAngle=-angleExtent[0]*RADIAN;initProps(clipPath,{shape:{endAngle:-angleExtent[1]*RADIAN}},seriesModel);}returnclipPath;}functioncreateClipShape(coordSys,hasAnimation,forSymbol,seriesModel){returncoordSys.type==='polar'?createPolarClipShape(coordSys,hasAnimation,forSymbol,seriesModel):createGridClipShape(coordSys,hasAnimation,forSymbol,seriesModel);}functionturnPointsIntoStep(points,coordSys,stepTurnAt){varbaseAxis=coordSys.getBaseAxis();varbaseIndex=baseAxis.dim==='x'||baseAxis.dim==='radius'?0:1;varstepPoints=[];for(vari=0;i<points.length-1;i++){varnextPt=points[i+1];varpt=points[i];stepPoints.push(pt);varstepPt=[];switch(stepTurnAt){case'end':stepPt[baseIndex]=nextPt[baseIndex];stepPt[1-baseIndex]=pt[1-baseIndex];// default is startstepPoints.push(stepPt);break;case'middle':// default is startvarmiddle=(pt[baseIndex]+nextPt[baseIndex])/2;varstepPt2=[];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 startstepPoints.push(stepPt);}}// Last pointspoints[i]&&stepPoints.push(points[i]);returnstepPoints;}functiongetVisualGradient(data,coordSys){varvisualMetaList=data.getVisual('visualMeta');if(!visualMetaList||!visualMetaList.length||!data.count()){// When data.count() is 0, gradient range can not be calculated.return;}if(coordSys.type!=='cartesian2d'){if(__DEV__){console.warn('Visual map on line style is only supported on cartesian2d.');}return;}varcoordDim;varvisualMeta;for(vari=visualMetaList.length-1;i>=0;i--){vardimIndex=visualMetaList[i].dimension;vardimName=data.dimensions[dimIndex];vardimInfo=data.getDimensionInfo(dimName);coordDim=dimInfo&&dimInfo.coordDim;// Can only be x or yif(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,// the canvas spec prescribes that the color of the first stop and the last// stop should be used. But if two stops are added at offset 0, in effect// browsers use the color of the second stop to render area outside// LinearGradient. So we can only infinitesimally extend area defined in// LinearGradient to render `outerColors`.varaxis=coordSys.getAxis(coordDim);// dataToCoor mapping may not be linear, but must be monotonic.varcolorStops=map(visualMeta.stops,function(stop){return{coord:axis.toGlobalCoord(axis.dataToCoord(stop.value)),color:stop.color};});varstopLen=colorStops.length;varouterColors=visualMeta.outerColors.slice();if(stopLen&&colorStops[0].coord>colorStops[stopLen-1].coord){colorStops.reverse();outerColors.reverse();}vartinyExtent=10;// Arbitrary value: 10pxvarminCoord=colorStops[0].coord-tinyExtent;varmaxCoord=colorStops[stopLen-1].coord+tinyExtent;varcoordSpan=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.offset:stopLen?colorStops[0].offset:0.5,color:outerColors[0]||'transparent'});// zrUtil.each(colorStops, function (colorStop) {// // Make sure each offset has rounded px to avoid not sharp edge// colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);// });vargradient=newLinearGradient(0,0,0,0,colorStops,true);gradient[coordDim]=minCoord;gradient[coordDim+'2']=maxCoord;returngradient;}functiongetIsIgnoreFunc(seriesModel,data,coordSys){varshowAllSymbol=seriesModel.get('showAllSymbol');varisAuto=showAllSymbol==='auto';if(showAllSymbol&&!isAuto){return;}varcategoryAxis=coordSys.getAxesByScale('ordinal')[0];if(!categoryAxis){return;}// Note that category label interval strategy might bring some weird effect// in some scenario: users may wonder why some of the symbols are not// displayed. So we show all symbols as possible as we can.if(isAuto// Simplify the logic, do not determine label overlap here.&&canShowAllSymbolForCategory(categoryAxis,data)){return;}// Otherwise follow the label interval strategy on category axis.varcategoryDataDim=data.mapDimension(categoryAxis.dim);varlabelMap={};each$1(categoryAxis.getViewLabels(),function(labelItem){labelMap[labelItem.tickValue]=1;});returnfunction(dataIndex){return!labelMap.hasOwnProperty(data.get(categoryDataDim,dataIndex));};}functioncanShowAllSymbolForCategory(categoryAxis,data){// In mose cases, line is monotonous on category axis, and the label size// is close with each other. So we check the symbol size and some of the// label size alone with the category axis to estimate whether all symbol// can be shown without overlap.varaxisExtent=categoryAxis.getExtent();varavailSize=Math.abs(axisExtent[1]-axisExtent[0])/categoryAxis.scale.count();isNaN(availSize)&&(availSize=0);// 0/0 is NaN.// Sampling some points, max 5.vardataLen=data.count();varstep=Math.max(1,Math.round(dataLen/5));for(vardataIndex=0;dataIndex<dataLen;dataIndex+=step){if(SymbolClz.getSymbolSize(data,dataIndex// Only for cartesian, where `isHorizontal` exists.)[categoryAxis.isHorizontal()?1:0]// Empirical number*1.5>availSize){returnfalse;}}returntrue;}Chart.extend({type:'line',init:function(){varlineGroup=newGroup();varsymbolDraw=newSymbolDraw();this.group.add(symbolDraw.group);this._symbolDraw=symbolDraw;this._lineGroup=lineGroup;},render:function(seriesModel,ecModel,api){varcoordSys=seriesModel.coordinateSystem;vargroup=this.group;vardata=seriesModel.getData();varlineStyleModel=seriesModel.getModel('lineStyle');varareaStyleModel=seriesModel.getModel('areaStyle');varpoints=data.mapArray(data.getItemLayout);varisCoordSysPolar=coordSys.type==='polar';varprevCoordSys=this._coordSys;varsymbolDraw=this._symbolDraw;varpolyline=this._polyline;varpolygon=this._polygon;varlineGroup=this._lineGroup;varhasAnimation=seriesModel.get('animation');varisAreaChart=!areaStyleModel.isEmpty();varvalueOrigin=areaStyleModel.get('origin');vardataCoordInfo=prepareDataCoordInfo(coordSys,data,valueOrigin);varstackedOnPoints=getStackedOnPoints(coordSys,data,dataCoordInfo);varshowSymbol=seriesModel.get('showSymbol');varisIgnoreFunc=showSymbol&&!isCoordSysPolar&&getIsIgnoreFunc(seriesModel,data,coordSys);// Remove temporary symbolsvaroldData=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 falseif(!showSymbol){symbolDraw.remove();}group.add(lineGroup);// FIXME step not support polarvarstep=!isCoordSysPolar&&seriesModel.get('step');// Initialization animation or coordinate system changedif(!(polyline&&prevCoordSys.type===coordSys.type&&step===this._step)){showSymbol&&symbolDraw.updateData(data,{isIgnore:isIgnoreFunc,clipShape:createClipShape(coordSys,false,true,seriesModel)});if(step){// TODO If stacked series is not steppoints=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(createClipShape(coordSys,true,false,seriesModel));}else{if(isAreaChart&&!polygon){// If areaStyle is addedpolygon=this._newPolygon(points,stackedOnPoints,coordSys,hasAnimation);}elseif(polygon&&!isAreaChart){// If areaStyle is removedlineGroup.remove(polygon);polygon=this._polygon=null;}// Update clipPathlineGroup.setClipPath(createClipShape(coordSys,false,false,seriesModel));// Always update, or it is wrong in the case turning on legend// because points are not changedshowSymbol&&symbolDraw.updateData(data,{isIgnore:isIgnoreFunc,clipShape:createClipShape(coordSys,false,true,seriesModel)});// Stop symbol animation and sync with line points// FIXME performance?data.eachItemGraphicEl(function(el){el.stopAnimation(true);});// In the case data zoom triggerred refreshing frequently// Data may not change if line has a category axis. So it should animate nothingif(!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 animationif(step){// TODO If stacked series is not steppoints=turnPointsIntoStep(points,coordSys,step);stackedOnPoints=turnPointsIntoStep(stackedOnPoints,coordSys,step);}polyline.setShape({points:points});polygon&&polygon.setShape({points:points,stackedOnPoints:stackedOnPoints});}}}varvisualColor=getVisualGradient(data,coordSys)||data.getVisual('color');polyline.useStyle(defaults(// Use color in lineStyle firstlineStyleModel.getLineStyle(),{fill:'none',stroke:visualColor,lineJoin:'bevel'}));varsmooth=seriesModel.get('smooth');smooth=getSmooth(seriesModel.get('smooth'));polyline.setShape({smooth:smooth,smoothMonotone:seriesModel.get('smoothMonotone'),connectNulls:seriesModel.get('connectNulls')});if(polygon){varstackedOnSeries=data.getCalculationInfo('stackedOnSeries');varstackedOnSmooth=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 changedthis._coordSys=coordSys;this._stackedOnPoints=stackedOnPoints;this._points=points;this._step=step;this._valueOrigin=valueOrigin;},dispose:function(){},highlight:function(seriesModel,ecModel,api,payload){vardata=seriesModel.getData();vardataIndex=queryDataIndex(data,payload);if(!(dataIndexinstanceofArray)&&dataIndex!=null&&dataIndex>=0){varsymbol=data.getItemGraphicEl(dataIndex);if(!symbol){// Create a temporary symbol if it is not existsvarpt=data.getItemLayout(dataIndex);if(!pt){// Null datareturn;}symbol=newSymbolClz(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 animationsymbol.stopSymbolAnimation(true);this.group.add(symbol);}symbol.highlight();}else{// Highlight whole seriesChart.prototype.highlight.call(this,seriesModel,ecModel,api,payload);}},downplay:function(seriesModel,ecModel,api,payload){vardata=seriesModel.getData();vardataIndex=queryDataIndex(data,payload);if(dataIndex!=null&&dataIndex>=0){varsymbol=data.getItemGraphicEl(dataIndex);if(symbol){if(symbol.__temp){data.setItemGraphicEl(dataIndex,null);this.group.remove(symbol);}else{symbol.downplay();}}}else{// FIXME// can not downplay completely.// Downplay whole seriesChart.prototype.downplay.call(this,seriesModel,ecModel,api,payload);}},/** * @param {module:zrender/container/Group}group*@param{Array.<Array.<number>>}points*@private*/ _newPolyline: function (points) { var polyline = this._polyline; //Removepreviouscreatedpolylineif(polyline){this._lineGroup.remove(polyline);}polyline=newPolyline$1({shape:{points:points},silent:true,z2:10});this._lineGroup.add(polyline);this._polyline=polyline;returnpolyline;},/** * @param {module:zrender/container/Group}group*@param{Array.<Array.<number>>}stackedOnPoints*@param{Array.<Array.<number>>}points*@private*/ _newPolygon: function (points, stackedOnPoints) { var polygon = this._polygon; //Removepreviouscreatedpolygonif(polygon){this._lineGroup.remove(polygon);}polygon=newPolygon$1({shape:{points:points,stackedOnPoints:stackedOnPoints},silent:true});this._lineGroup.add(polygon);this._polygon=polygon;returnpolygon;},/** * @private */// FIXME Two value axis_updateAnimation:function(data,stackedOnPoints,coordSys,api,step,valueOrigin){varpolyline=this._polyline;varpolygon=this._polygon;varseriesModel=data.hostModel;vardiff=lineAnimationDiff(this._data,data,this._stackedOnPoints,stackedOnPoints,this._coordSys,coordSys,this._valueOrigin,valueOrigin);varcurrent=diff.current;varstackedOnCurrent=diff.stackedOnCurrent;varnext=diff.next;varstackedOnNext=diff.stackedOnNext;if(step){// TODO If stacked series is not stepcurrent=turnPointsIntoStep(diff.current,coordSys,step);stackedOnCurrent=turnPointsIntoStep(diff.stackedOnCurrent,coordSys,step);next=turnPointsIntoStep(diff.next,coordSys,step);stackedOnNext=turnPointsIntoStep(diff.stackedOnNext,coordSys,step);}// `diff.current` is subset of `current` (which should be ensured by// turnPointsIntoStep), so points in `__points` can be updated when// points in `current` are update during animation.polyline.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);}varupdatedDataInfo=[];vardiffStatus=diff.status;for(vari=0;i<diffStatus.length;i++){varcmd=diffStatus[i].cmd;if(cmd==='='){varel=data.getItemGraphicEl(diffStatus[i].idx1);if(el){updatedDataInfo.push({el:el,ptIdx:i// Index of points});}}}if(polyline.animators&&polyline.animators.length){polyline.animators[0].during(function(){for(vari=0;i<updatedDataInfo.length;i++){varel=updatedDataInfo[i].el;el.attr('position',polyline.shape.__points[updatedDataInfo[i].ptIdx]);}});}},remove:function(ecModel){vargroup=this.group;varoldData=this._data;this._lineGroup.removeAll();this._symbolDraw.remove(true);// Remove temporary created elements when highlightingoldData&&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;}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var visualSymbol = function (seriesType, defaultSymbolType, legendSymbol) { //Encodingvisualforallseriesincludewhichisfilteredforlegenddrawingreturn{seriesType:seriesType,// For legend.performRawSeries:true,reset:function(seriesModel,ecModel,api){vardata=seriesModel.getData();varsymbolType=seriesModel.get('symbol')||defaultSymbolType;varsymbolSize=seriesModel.get('symbolSize');varkeepAspect=seriesModel.get('symbolKeepAspect');data.setVisual({legendSymbol:legendSymbol||symbolType,symbol:symbolType,symbolSize:symbolSize,symbolKeepAspect:keepAspect});// Only visible series has each data be visual encodedif(ecModel.isSeriesFiltered(seriesModel)){return;}varhasCallback=typeofsymbolSize==='function';functiondataEach(data,idx){if(typeofsymbolSize==='function'){varrawValue=seriesModel.getRawValue(idx);// FIXMEvarparams=seriesModel.getDataParams(idx);data.setItemVisual(idx,'symbolSize',symbolSize(rawValue,params));}if(data.hasItemOption){varitemModel=data.getItemModel(idx);varitemSymbolType=itemModel.getShallow('symbol',true);varitemSymbolSize=itemModel.getShallow('symbolSize',true);varitemSymbolKeepAspect=itemModel.getShallow('symbolKeepAspect',true);// If has item symbolif(itemSymbolType!=null){data.setItemVisual(idx,'symbol',itemSymbolType);}if(itemSymbolSize!=null){// PENDING Transform symbolSize ?data.setItemVisual(idx,'symbolSize',itemSymbolSize);}if(itemSymbolKeepAspect!=null){data.setItemVisual(idx,'symbolKeepAspect',itemSymbolKeepAspect);}}}return{dataEach:(data.hasItemOption||hasCallback)?dataEach:null};}};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//*globalFloat32Array*/var layoutPoints = function (seriesType) { return { seriesType: seriesType, plan: createRenderPlanner(), reset: function (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>},notundefinedtoavoidif...else...statementpoint=!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);}returndimLen&&{progress:progress};}};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var samplers = { average: function (frame) { var sum = 0; var count = 0; for (var i = 0; i < frame.length; i++) { if (!isNaN(frame[i])) { sum += frame[i]; count++; } } //ReturnNaNifcountis0returncount===0?NaN:sum/count;},sum:function(frame){varsum=0;for(vari=0;i<frame.length;i++){// Ignore NaNsum+=frame[i]||0;}returnsum;},max:function(frame){varmax=-Infinity;for(vari=0;i<frame.length;i++){frame[i]>max&&(max=frame[i]);}// NaN will cause illegal axis extent.returnisFinite(max)?max:NaN;},min:function(frame){varmin=Infinity;for(vari=0;i<frame.length;i++){frame[i]<min&&(min=frame[i]);}// NaN will cause illegal axis extent.returnisFinite(min)?min:NaN;},// TODO// Mediannearest:function(frame){returnframe[0];}};varindexSampler=function(frame,value){returnMath.round(frame.length/2);};vardataSample=function(seriesType){return{seriesType:seriesType,modifyOutputEnd:true,reset:function(seriesModel,ecModel,api){vardata=seriesModel.getData();varsampling=seriesModel.get('sampling');varcoordSys=seriesModel.coordinateSystem;// Only cartesian2d support down samplingif(coordSys.type==='cartesian2d'&&sampling){varbaseAxis=coordSys.getBaseAxis();varvalueAxis=coordSys.getOtherAxis(baseAxis);varextent=baseAxis.getExtent();// Coordinste system has been resizedvarsize=extent[1]-extent[0];varrate=Math.round(data.count()/size);if(rate>1){varsampler;if(typeofsampling==='string'){sampler=samplers[sampling];}elseif(typeofsampling==='function'){sampler=sampling;}if(sampler){// Only support sample the first dim mapped from value axis.seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim),1/rate,sampler,indexSampler));}}}}};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***// Scale class management*@moduleecharts/scale/Scale*//***@param{Object}[setting]*/function Scale(setting) { this._setting = setting || {}; /***Extent*@type{Array.<number>}*@protected*/ this._extent = [Infinity, -Infinity]; /***StepiscalculatedinadjustExtent*@type{Array.<number>}*@protected*/ this._interval = 0; this.init && this.init.apply(this, arguments);}/***Parseinputvaltovalidinnernumber.*@param{*}val*@return{number}*/Scale.prototype.parse = function (val) { //Notice:Thiswouldbeatraphere,Iftheimplementation// of this method depends on extent, and this method is used// before extent set (like in dataZoom), it would be wrong.// Nevertheless, parse does not depend on extent generally.returnval;};Scale.prototype.getSetting=function(name){returnthis._setting[name];};Scale.prototype.contain=function(val){varextent=this._extent;returnval>=extent[0]&&val<=extent[1];};/** * Normalize value to linear [0, 1], return 0.5 if extent span is 0 * @param {number} val * @return {number} */Scale.prototype.normalize=function(val){varextent=this._extent;if(extent[1]===extent[0]){return0.5;}return(val-extent[0])/(extent[1]-extent[0]);};/** * Scale normalized value * @param {number} val * @return {number} */Scale.prototype.scale=function(val){varextent=this._extent;returnval*(extent[1]-extent[0])+extent[0];};/** * Set extent from data * @param {Array.<number>} other */Scale.prototype.unionExtent=function(other){varextent=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// this.setExtent(extent[0], extent[1]);};/** * Set extent from data * @param {module:echarts/data/List}data*@param{string}dim*/Scale.prototype.unionExtentFromData = function (data, dim) { this.unionExtent(data.getApproximateExtent(dim));};/***Getextent*@return{Array.<number>}*/Scale.prototype.getExtent = function () { return this._extent.slice();};/***Setextent*@param{number}start*@param{number}end*/Scale.prototype.setExtent = function (start, end) { var thisExtent = this._extent; if (!isNaN(start)) { thisExtent[0] = start; } if (!isNaN(end)) { thisExtent[1] = end; }};/***Whenaxisextentdependsondataandnodataexists,*axisticksshouldnotbedrawn,whichisnamed'blank'.*/Scale.prototype.isBlank = function () { return this._isBlank;},/***Whenaxisextentdependsondataandnodataexists,*axisticksshouldnotbedrawn,whichisnamed'blank'.*/Scale.prototype.setBlank = function (isBlank) { this._isBlank = isBlank;};/***@abstract*@param{*}tick*@return{string}labelofthetick.*/Scale.prototype.getLabel = null;enableClassExtend(Scale);enableClassManagement(Scale, { registerWhenExtend: true});/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@constructor*@param{Object}[opt]*@param{Object}[opt.categories=[]]*@param{Object}[opt.needCollect=false]*@param{Object}[opt.deduplication=false]*/function OrdinalMeta(opt) { /***@readOnly*@type{Array.<string>}*/ this.categories = opt.categories || []; /***@private*@type{boolean}*/ this._needCollect = opt.needCollect; /***@private*@type{boolean}*/ this._deduplication = opt.deduplication; /***@private*@type{boolean}*/ this._map;}/***@param{module:echarts/model/Model}axisModel*@return{module:echarts/data/OrdinalMeta}*/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, //deduplicationisdefaultinaxis.deduplication:option.dedplication!==false});};varproto$1=OrdinalMeta.prototype;/** * @param {string} category * @return {number} ordinal */proto$1.getOrdinal=function(category){returngetOrCreateMap(this).get(category);};/** * @param {*} category * @return {number} The ordinal. If not found, return NaN. */proto$1.parseAndCollect=function(category){varindex;varneedCollect=this._needCollect;// The value of category dim can be the index of the given category set.// This feature is only supported when !needCollect, because we should// consider a common case: a value is 2017, which is a number but is// expected to be tread as a category. This case usually happen in dataset,// where it happent to be no need of the index feature.if(typeofcategory!=='string'&&!needCollect){returncategory;}// Optimize for the scenario:// category is ['2012-01-01', '2012-01-02', ...], where the input// data has been ensured not duplicate and is large data.// Notice, if a dataset dimension provide categroies, usually echarts// should remove duplication except user tell echarts dont do that// (set axis.deduplication = false), because echarts do not know whether// the values in the category dimension has duplication (consider the// parallel-aqi example)if(needCollect&&!this._deduplication){index=this.categories.length;this.categories[index]=category;returnindex;}varmap$$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;}}returnindex;};// Consider big data, do not create map until needed.functiongetOrCreateMap(ordinalMeta){returnordinalMeta._map||(ordinalMeta._map=createHashMap(ordinalMeta.categories));}functiongetName(obj){if(isObject$1(obj)&&obj.value!=null){returnobj.value;}else{returnobj+'';}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Linearcontinuousscale*@moduleecharts/coord/scale/Ordinal**http://en.wikipedia.org/wiki/Level_of_measurement*///FIXMEonlyonedatavarscaleProto=Scale.prototype;varOrdinalScale=Scale.extend({type:'ordinal',/** * @param {module:echarts/data/OrdianlMeta|Array.<string>}ordinalMeta*/ init: function (ordinalMeta, extent) { //Caution:Shouldnotuseinstanceof,considerec-extensionsusing// import approach to get OrdinalMeta class.if(!ordinalMeta||isArray(ordinalMeta)){ordinalMeta=newOrdinalMeta({categories:ordinalMeta});}this._ordinalMeta=ordinalMeta;this._extent=extent||[0,ordinalMeta.categories.length-1];},parse:function(val){returntypeofval==='string'?this._ordinalMeta.getOrdinal(val)// val might be float.:Math.round(val);},contain:function(rank){rank=this.parse(rank);returnscaleProto.contain.call(this,rank)&&this._ordinalMeta.categories[rank]!=null;},/** * Normalize given rank or name to linear [0, 1] * @param {number|string} [val] * @return {number} */normalize:function(val){returnscaleProto.normalize.call(this,this.parse(val));},scale:function(val){returnMath.round(scaleProto.scale.call(this,val));},/** * @return {Array} */getTicks:function(){varticks=[];varextent=this._extent;varrank=extent[0];while(rank<=extent[1]){ticks.push(rank);rank++;}returnticks;},/** * Get item on rank n * @param {number} n * @return {string} */getLabel:function(n){if(!this.isBlank()){// Note that if no data, ordinalMeta.categories is an empty array.returnthis._ordinalMeta.categories[n];}},/** * @return {number} */count:function(){returnthis._extent[1]-this._extent[0]+1;},/** * @override */unionExtentFromData:function(data,dim){this.unionExtent(data.getApproximateExtent(dim));},getOrdinalMeta:function(){returnthis._ordinalMeta;},niceTicks:noop,niceExtent:noop});/** * @return {module:echarts/scale/Time}*/OrdinalScale.create = function () { return new OrdinalScale();};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Fortestable.*/var roundNumber$1 = round$1;/***@param{Array.<number>}extentBothextent[0]andextent[1]shouldbevalidnumber.*Shouldbeextent[0]<extent[1].*@param{number}splitNumbersplitNumbershouldbe>=1.*@param{number}[minInterval]*@param{number}[maxInterval]*@return{Object}{interval,intervalPrecision,niceTickExtent}*/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.varprecision=result.intervalPrecision=getIntervalPrecision(interval);// Niced extent inside original extentvarniceTickExtent=result.niceTickExtent=[roundNumber$1(Math.ceil(extent[0]/interval)*interval,precision),roundNumber$1(Math.floor(extent[1]/interval)*interval,precision)];fixExtent(niceTickExtent,extent);returnresult;}/** * @param {number} interval * @return {number} interval precision */functiongetIntervalPrecision(interval){// Tow more digital for tick.returngetPrecisionSafe(interval)+2;}functionclamp(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.functionfixExtent(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];}}functionintervalScaleGetTicks(interval,extent,niceTickExtent,intervalPrecision){varticks=[];// If interval is 0, return [];if(!interval){returnticks;}// Consider this case: using dataZoom toolbox, zoom and zoom.varsafeLimit=10000;if(extent[0]<niceTickExtent[0]){ticks.push(extent[0]);}vartick=niceTickExtent[0];while(tick<=niceTickExtent[1]){ticks.push(tick);// Avoid rounding errortick=roundNumber$1(tick+interval,intervalPrecision);if(tick===ticks[ticks.length-1]){// Consider out of safe float point, e.g.,// -3711126.9907707 + 2e-10 === -3711126.9907707break;}if(ticks.length>safeLimit){return[];}}// Consider this case: the last item of ticks is smaller// than niceTickExtent[1] and niceTickExtent[1] === extent[1].if(extent[1]>(ticks.length?ticks[ticks.length-1]:niceTickExtent[1])){ticks.push(extent[1]);}returnticks;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Intervalscale*@moduleecharts/scale/Interval*/var roundNumber = round$1;/***@aliasmodule:echarts/coord/scale/Interval*@constructor*/var IntervalScale = Scale.extend({ type: 'interval', _interval: 0, _intervalPrecision: 2, setExtent: function (start, end) { var thisExtent = this._extent; //start,endmaybeaNumberlike'25',so...if(!isNaN(start)){thisExtent[0]=parseFloat(start);}if(!isNaN(end)){thisExtent[1]=parseFloat(end);}},unionExtent:function(other){varextent=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 classesIntervalScale.prototype.setExtent.call(this,extent[0],extent[1]);},/** * Get interval */getInterval:function(){returnthis._interval;},/** * Set interval */setInterval:function(interval){this._interval=interval;// Dropped auto calculated niceExtent and use user setted extent// We assume user wan't to set both interval, min, max to get a better resultthis._niceExtent=this._extent.slice();this._intervalPrecision=getIntervalPrecision(interval);},/** * @return {Array.<number>} */getTicks:function(){returnintervalScaleGetTicks(this._interval,this._extent,this._niceExtent,this._intervalPrecision);},/** * @param {number} data * @param {Object} [opt] * @param {number|string} [opt.precision] If 'auto', use nice presision. * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2. * @return {string} */getLabel:function(data,opt){if(data==null){return'';}varprecision=opt&&opt.precision;if(precision==null){precision=getPrecisionSafe(data)||0;}elseif(precision==='auto'){// Should be more precise then tick.precision=this._intervalPrecision;}// (1) If `precision` is set, 12.005 should be display as '12.00500'.// (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'.data=roundNumber(data,precision,true);returnaddCommas(data);},/** * Update interval and extent of intervals for nice ticks * * @param {number} [splitNumber = 5] Desired number of ticks * @param {number} [minInterval] * @param {number} [maxInterval] */niceTicks:function(splitNumber,minInterval,maxInterval){splitNumber=splitNumber||5;varextent=this._extent;varspan=extent[1]-extent[0];if(!isFinite(span)){return;}// User may set axis min 0 and data are all negative// FIXME If it needs to reverse ?if(span<0){span=-span;extent.reverse();}varresult=intervalScaleNiceTicks(extent,splitNumber,minInterval,maxInterval);this._intervalPrecision=result.intervalPrecision;this._interval=result.interval;this._niceExtent=result.niceTickExtent;},/** * Nice extent. * @param {Object} opt * @param {number} [opt.splitNumber = 5] Given approx tick number * @param {boolean} [opt.fixMin=false] * @param {boolean} [opt.fixMax=false] * @param {boolean} [opt.minInterval] * @param {boolean} [opt.maxInterval] */niceExtent:function(opt){varextent=this._extent;// If extent start and end are same, expand themif(extent[0]===extent[1]){if(extent[0]!==0){// Expand extentvarexpandSize=extent[0];// In the fowllowing case// Axis has been fixed max 100// Plus data are all 100 and axis extent are [100, 100].// Extend to the both side will cause expanded max is larger than fixed max.// So only expand to the smaller side.if(!opt.fixMax){extent[1]+=expandSize/2;extent[0]-=expandSize/2;}else{extent[0]-=expandSize/2;}}else{extent[1]=1;}}varspan=extent[1]-extent[0];// If there are no data and extent are [Infinity, -Infinity]if(!isFinite(span)){extent[0]=0;extent[1]=1;}this.niceTicks(opt.splitNumber,opt.minInterval,opt.maxInterval);// var extent = this._extent;varinterval=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);}}});/** * @return {module:echarts/scale/Time}*/IntervalScale.create = function () { return new IntervalScale();};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//*globalFloat32Array*/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;}/***@param{Object}opt*@param{module:echarts/coord/Axis}opt.axisOnlysupportcategoryaxiscurrently.*@param{number}opt.countPositiveinterger.*@param{number}[opt.barWidth]*@param{number}[opt.barMaxWidth]*@param{number}[opt.barGap]*@param{number}[opt.barCategoryGap]*@return{Object}{width,offset,offsetCenter}Ifaxis.typeisnot'category',returnundefined.*/function prepareLayoutBarSeries(seriesType, ecModel) { var seriesModels = []; ecModel.eachSeriesByType(seriesType, function (seriesModel) { //Checkseriescoordinate,dolayoutforcartesian2donlyif(isOnCartesian(seriesModel)&&!isInLargeMode(seriesModel)){seriesModels.push(seriesModel);}});returnseriesModels;}functionmakeColumnLayout(barSeries){varseriesInfoList=[];each$1(barSeries,function(seriesModel){vardata=seriesModel.getData();varcartesian=seriesModel.coordinateSystem;varbaseAxis=cartesian.getBaseAxis();varaxisExtent=baseAxis.getExtent();varbandWidth=baseAxis.type==='category'?baseAxis.getBandWidth():(Math.abs(axisExtent[1]-axisExtent[0])/data.count());varbarWidth=parsePercent$1(seriesModel.get('barWidth'),bandWidth);varbarMaxWidth=parsePercent$1(seriesModel.get('barMaxWidth'),bandWidth);varbarGap=seriesModel.get('barGap');varbarCategoryGap=seriesModel.get('barCategoryGap');seriesInfoList.push({bandWidth:bandWidth,barWidth:barWidth,barMaxWidth:barMaxWidth,barGap:barGap,barCategoryGap:barCategoryGap,axisKey:getAxisKey(baseAxis),stackId:getSeriesStackId(seriesModel)});});returndoCalBarWidthAndOffset(seriesInfoList);}functiondoCalBarWidthAndOffset(seriesInfoList){// Columns info on each category axis. Key is cartesian namevarcolumnsMap={};each$1(seriesInfoList,function(seriesInfo,idx){varaxisKey=seriesInfo.axisKey;varbandWidth=seriesInfo.bandWidth;varcolumnsOnAxis=columnsMap[axisKey]||{bandWidth:bandWidth,remainedWidth:bandWidth,autoWidthCount:0,categoryGap:'20%',gap:'30%',stacks:{}};varstacks=columnsOnAxis.stacks;columnsMap[axisKey]=columnsOnAxis;varstackId=seriesInfo.stackId;if(!stacks[stackId]){columnsOnAxis.autoWidthCount++;}stacks[stackId]=stacks[stackId]||{width:0,maxWidth:0};// Caution: In a single coordinate system, these barGrid attributes// will be shared by series. Consider that they have default values,// only the attributes set on the last series will work.// Do not change this fact unless there will be a break change.// TODOvarbarWidth=seriesInfo.barWidth;if(barWidth&&!stacks[stackId].width){// See #6312, do not restrict width.stacks[stackId].width=barWidth;barWidth=Math.min(columnsOnAxis.remainedWidth,barWidth);columnsOnAxis.remainedWidth-=barWidth;}varbarMaxWidth=seriesInfo.barMaxWidth;barMaxWidth&&(stacks[stackId].maxWidth=barMaxWidth);varbarGap=seriesInfo.barGap;(barGap!=null)&&(columnsOnAxis.gap=barGap);varbarCategoryGap=seriesInfo.barCategoryGap;(barCategoryGap!=null)&&(columnsOnAxis.categoryGap=barCategoryGap);});varresult={};each$1(columnsMap,function(columnsOnAxis,coordSysName){result[coordSysName]={};varstacks=columnsOnAxis.stacks;varbandWidth=columnsOnAxis.bandWidth;varcategoryGap=parsePercent$1(columnsOnAxis.categoryGap,bandWidth);varbarGapPercent=parsePercent$1(columnsOnAxis.gap,1);varremainedWidth=columnsOnAxis.remainedWidth;varautoWidthCount=columnsOnAxis.autoWidthCount;varautoWidth=(remainedWidth-categoryGap)/(autoWidthCount+(autoWidthCount-1)*barGapPercent);autoWidth=Math.max(autoWidth,0);// Find if any auto calculated bar exceeded maxBarWidtheach$1(stacks,function(column,stack){varmaxWidth=column.maxWidth;if(maxWidth&&maxWidth<autoWidth){maxWidth=Math.min(maxWidth,remainedWidth);if(column.width){maxWidth=Math.min(maxWidth,column.width);}remainedWidth-=maxWidth;column.width=maxWidth;autoWidthCount--;}});// Recalculate width againautoWidth=(remainedWidth-categoryGap)/(autoWidthCount+(autoWidthCount-1)*barGapPercent);autoWidth=Math.max(autoWidth,0);varwidthSum=0;varlastColumn;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;}varoffset=-widthSum/2;each$1(stacks,function(column,stackId){result[coordSysName][stackId]=result[coordSysName][stackId]||{offset:offset,width:column.width};offset+=column.width*(1+barGapPercent);});});returnresult;}/** * @param {Object} barWidthAndOffset The result of makeColumnLayout * @param {module:echarts/coord/Axis}axis*@param{module:echarts/model/Series}[seriesModel]Ifnotprovided,returnall.*@return{Object}{stackId:{offset,width}}or{offset,width}ifseriesModelprovided.*/function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) { if (barWidthAndOffset && axis) { var result = barWidthAndOffset[getAxisKey(axis)]; if (result != null && seriesModel != null) { result = result[getSeriesStackId(seriesModel)]; } return result; }}/***@param{string}seriesType*@param{module:echarts/model/Global}ecModel*/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({ 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); if (isNaN(value)) { continue; } var sign = value >= 0 ? 'p' : 'n'; var baseCoord = valueAxisStart; //BecauseofthebarMinHeight,wecannotusethevaluein// stackResultDimension directly.if(stacked){// Only ordinal axis can be stacked.if(!lastStackCoords[stackId][baseValue]){lastStackCoords[stackId][baseValue]={p:valueAxisStart,// Positive stackn:valueAxisStart// Negative stack};}// Should also consider #4243baseCoord=lastStackCoords[stackId][baseValue][sign];}varx;vary;varwidth;varheight;if(isValueAxisH){varcoord=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;}stacked&&(lastStackCoords[stackId][baseValue][sign]+=width);}else{varcoord=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 barheight=(height<=0?-1:1)*barMinHeight;}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.varlargeLayout={seriesType:'bar',plan:createRenderPlanner(),reset:function(seriesModel){if(!isOnCartesian(seriesModel)||!isInLargeMode(seriesModel)){return;}vardata=seriesModel.getData();varcartesian=seriesModel.coordinateSystem;varbaseAxis=cartesian.getBaseAxis();varvalueAxis=cartesian.getOtherAxis(baseAxis);varvalueDim=data.mapDimension(valueAxis.dim);varbaseDim=data.mapDimension(baseAxis.dim);varvalueAxisHorizontal=valueAxis.isHorizontal();varvalueDimIdx=valueAxisHorizontal?0:1;varbarWidth=retrieveColumnLayout(makeColumnLayout([seriesModel]),baseAxis,seriesModel).width;if(!(barWidth>LARGE_BAR_MIN_WIDTH)){// jshint ignore:linebarWidth=LARGE_BAR_MIN_WIDTH;}return{progress:progress};functionprogress(params,data){varlargePoints=newLargeArr(params.count*2);vardataIndex;varcoord=[];varvaluePair=[];varoffset=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);largePoints[offset++]=coord[0];largePoints[offset++]=coord[1];}data.setLayout({largePoints:largePoints,barWidth:barWidth,valueAxisStart:getValueAxisStart(baseAxis,valueAxis,false),valueAxisHorizontal:valueAxisHorizontal});}}};functionisOnCartesian(seriesModel){returnseriesModel.coordinateSystem&&seriesModel.coordinateSystem.type==='cartesian2d';}functionisInLargeMode(seriesModel){returnseriesModel.pipelineContext&&seriesModel.pipelineContext.large;}// See cases in `test/bar-start.html` and `#7412`, `#8747`.functiongetValueAxisStart(baseAxis,valueAxis,stacked){varextent=valueAxis.getGlobalExtent();varmin;varmax;if(extent[0]>extent[1]){min=extent[1];max=extent[0];}else{min=extent[0];max=extent[1];}varvalueStart=valueAxis.toGlobalCoord(valueAxis.dataToCoord(0));valueStart<min&&(valueStart=min);valueStart>max&&(valueStart=max);returnvalueStart;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//**The`scaleLevels`referencestod3.js.Theuseofthesource*codeofthisfileisalsosubjecttothetermsandconsitions*ofitslicense(BSD-3Clause,see<echarts/src/licenses/LICENSE-d3>).*///[AboutUTCandlocaltimezone]:// In most cases, `number.parseDate` will treat input data string as local time// (except time zone is specified in time string). And `format.formateTime` returns// local time by default. option.useUTC is false by default. This design have// concidered these common case:// (1) Time that is persistent in server is in UTC, but it is needed to be diplayed// in local time by default.// (2) By default, the input data string (e.g., '2011-01-02') should be displayed// as its original time, without any time difference.varintervalScaleProto=IntervalScale.prototype;varmathCeil=Math.ceil;varmathFloor=Math.floor;varONE_SECOND=1000;varONE_MINUTE=ONE_SECOND*60;varONE_HOUR=ONE_MINUTE*60;varONE_DAY=ONE_HOUR*24;// FIXME 公用?varbisect=function(a,x,lo,hi){while(lo<hi){varmid=lo+hi>>>1;if(a[mid][1]<x){lo=mid+1;}else{hi=mid;}}returnlo;};/** * @alias module:echarts/coord/scale/Time*@constructor*/var TimeScale = IntervalScale.extend({ type: 'time', /***@override*/ getLabel: function (val) { var stepLvl = this._stepLvl; var date = new Date(val); return formatTime(stepLvl[0], date, this.getSetting('useUTC')); }, /***@override*/ niceExtent: function (opt) { var extent = this._extent; //Ifextentstartandendaresame,expandthemif(extent[0]===extent[1]){// Expand extentextent[0]-=ONE_DAY;extent[1]+=ONE_DAY;}// If there are no data and extent are [Infinity, -Infinity]if(extent[1]===-Infinity&&extent[0]===Infinity){vard=newDate();extent[1]=+newDate(d.getFullYear(),d.getMonth(),d.getDate());extent[0]=extent[1]-ONE_DAY;}this.niceTicks(opt.splitNumber,opt.minInterval,opt.maxInterval);// var extent = this._extent;varinterval=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);}},/** * @override */niceTicks:function(approxTickNum,minInterval,maxInterval){approxTickNum=approxTickNum||10;varextent=this._extent;varspan=extent[1]-extent[0];varapproxInterval=span/approxTickNum;if(minInterval!=null&&approxInterval<minInterval){approxInterval=minInterval;}if(maxInterval!=null&&approxInterval>maxInterval){approxInterval=maxInterval;}varscaleLevelsLen=scaleLevels.length;varidx=bisect(scaleLevels,approxInterval,0,scaleLevelsLen);varlevel=scaleLevels[Math.min(idx,scaleLevelsLen-1)];varinterval=level[1];// Same with interval scale if span is much larger than 1 yearif(level[0]==='year'){varyearSpan=span/interval;// From "Nice Numbers for Graph Labels" of Graphic Gems// var niceYearSpan = numberUtil.nice(yearSpan, false);varyearStep=nice(yearSpan/approxTickNum,true);interval*=yearStep;}vartimezoneOffset=this.getSetting('useUTC')?0:(newDate(+extent[0]||+extent[1])).getTimezoneOffset()*60*1000;varniceExtent=[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 getTicksthis._interval=interval;this._niceExtent=niceExtent;},parse:function(val){// val might be float.return+parseDate(val);}});each$1(['contain','normalize'],function(methodName){TimeScale.prototype[methodName]=function(val){returnintervalScaleProto[methodName].call(this,this.parse(val));};});// Steps from d3, see the license statement at the top of this file.varscaleLevels=[// Format interval['hh:mm:ss',ONE_SECOND],// 1s['hh:mm:ss',ONE_SECOND*5],// 5s['hh:mm:ss',ONE_SECOND*10],// 10s['hh:mm:ss',ONE_SECOND*15],// 15s['hh:mm:ss',ONE_SECOND*30],// 30s['hh:mm\nMM-dd',ONE_MINUTE],// 1m['hh:mm\nMM-dd',ONE_MINUTE*5],// 5m['hh:mm\nMM-dd',ONE_MINUTE*10],// 10m['hh:mm\nMM-dd',ONE_MINUTE*15],// 15m['hh:mm\nMM-dd',ONE_MINUTE*30],// 30m['hh:mm\nMM-dd',ONE_HOUR],// 1h['hh:mm\nMM-dd',ONE_HOUR*2],// 2h['hh:mm\nMM-dd',ONE_HOUR*6],// 6h['hh:mm\nMM-dd',ONE_HOUR*12],// 12h['MM-dd\nyyyy',ONE_DAY],// 1d['MM-dd\nyyyy',ONE_DAY*2],// 2d['MM-dd\nyyyy',ONE_DAY*3],// 3d['MM-dd\nyyyy',ONE_DAY*4],// 4d['MM-dd\nyyyy',ONE_DAY*5],// 5d['MM-dd\nyyyy',ONE_DAY*6],// 6d['week',ONE_DAY*7],// 7d['MM-dd\nyyyy',ONE_DAY*10],// 10d['week',ONE_DAY*14],// 2w['week',ONE_DAY*21],// 3w['month',ONE_DAY*31],// 1M['week',ONE_DAY*42],// 6w['month',ONE_DAY*62],// 2M['week',ONE_DAY*70],// 10w['quarter',ONE_DAY*95],// 3M['month',ONE_DAY*31*4],// 4M['month',ONE_DAY*31*5],// 5M['half-year',ONE_DAY*380/2],// 6M['month',ONE_DAY*31*8],// 8M['month',ONE_DAY*31*10],// 10M['year',ONE_DAY*380]// 1Y];/** * @param {module:echarts/model/Model}*@return{module:echarts/scale/Time}*/TimeScale.create = function (model) { return new TimeScale({useUTC: model.ecModel.get('useUTC')});};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Logscale*@moduleecharts/scale/Log*///UsesomemethodofIntervalScalevarscaleProto$1=Scale.prototype;varintervalScaleProto$1=IntervalScale.prototype;vargetPrecisionSafe$1=getPrecisionSafe;varroundingErrorFix=round$1;varmathFloor$1=Math.floor;varmathCeil$1=Math.ceil;varmathPow$1=Math.pow;varmathLog=Math.log;varLogScale=Scale.extend({type:'log',base:10,$constructor:function(){Scale.apply(this,arguments);this._originalScale=newIntervalScale();},/** * @return {Array.<number>} */getTicks:function(){varoriginalScale=this._originalScale;varextent=this._extent;varoriginalExtent=originalScale.getExtent();returnmap(intervalScaleProto$1.getTicks.call(this),function(val){varpowVal=round$1(mathPow$1(this.base,val));// Fix #4158powVal=(val===extent[0]&&originalScale.__fixMin)?fixRoundingError(powVal,originalExtent[0]):powVal;powVal=(val===extent[1]&&originalScale.__fixMax)?fixRoundingError(powVal,originalExtent[1]):powVal;returnpowVal;},this);},/** * @param {number} val * @return {string} */getLabel:intervalScaleProto$1.getLabel,/** * @param {number} val * @return {number} */scale:function(val){val=scaleProto$1.scale.call(this,val);returnmathPow$1(this.base,val);},/** * @param {number} start * @param {number} end */setExtent:function(start,end){varbase=this.base;start=mathLog(start)/mathLog(base);end=mathLog(end)/mathLog(base);intervalScaleProto$1.setExtent.call(this,start,end);},/** * @return {number} end */getExtent:function(){varbase=this.base;varextent=scaleProto$1.getExtent.call(this);extent[0]=mathPow$1(base,extent[0]);extent[1]=mathPow$1(base,extent[1]);// Fix #4158varoriginalScale=this._originalScale;varoriginalExtent=originalScale.getExtent();originalScale.__fixMin&&(extent[0]=fixRoundingError(extent[0],originalExtent[0]));originalScale.__fixMax&&(extent[1]=fixRoundingError(extent[1],originalExtent[1]));returnextent;},/** * @param {Array.<number>} extent */unionExtent:function(extent){this._originalScale.unionExtent(extent);varbase=this.base;extent[0]=mathLog(extent[0])/mathLog(base);extent[1]=mathLog(extent[1])/mathLog(base);scaleProto$1.unionExtent.call(this,extent);},/** * @override */unionExtentFromData:function(data,dim){// TODO// filter value that <= 0this.unionExtent(data.getApproximateExtent(dim));},/** * Update interval and extent of intervals for nice ticks * @param {number} [approxTickNum = 10] Given approx tick number */niceTicks:function(approxTickNum){approxTickNum=approxTickNum||10;varextent=this._extent;varspan=extent[1]-extent[0];if(span===Infinity||span<=0){return;}varinterval=quantity(span);varerr=approxTickNum/span*interval;// Filter ticks to get closer to the desired count.if(err<=0.5){interval*=10;}// Interval should be integerwhile(!isNaN(interval)&&Math.abs(interval)<1&&Math.abs(interval)>0){interval*=10;}varniceExtent=[round$1(mathCeil$1(extent[0]/interval)*interval),round$1(mathFloor$1(extent[1]/interval)*interval)];this._interval=interval;this._niceExtent=niceExtent;},/** * Nice extent. * @override */niceExtent:function(opt){intervalScaleProto$1.niceExtent.call(this,opt);varoriginalScale=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);returnscaleProto$1[methodName].call(this,val);};});LogScale.create=function(){returnnewLogScale();};functionfixRoundingError(val,originalVal){returnroundingErrorFix(val,getPrecisionSafe$1(originalVal));}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Getaxisscaleextentbeforeniced.*Itemofreturnedarraycanonlybenumber(includingInfinityandNaN).*/function getScaleExtent(scale, model) { var scaleType = scale.type; var min = model.getMin(); var max = model.getMax(); var fixMin = min != null; var fixMax = max != null; 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:Whenmin/maxisnotset(thatis,whentherearenull/undefined,// which is the most common case), these cases should be ensured:// (1) For 'ordinal', show all axis.data.// (2) For others:// + `boundaryGap` is applied (if min/max set, boundaryGap is// disabled).// + If `needCrossZero`, min/max should be zero, otherwise, min/max should// be the result that originalExtent enlarged by boundaryGap.// (3) If no data, it should be ensured that `scale.setBlank` is set.// FIXME// (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used?// (2) When `needCrossZero` and all data is positive/negative, should it be ensured// that the results processed by boundaryGap are positive/negative?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;}if(min==='dataMin'){min=originalExtent[0];}elseif(typeofmin==='function'){min=min({min:originalExtent[0],max:originalExtent[1]});}if(max==='dataMax'){max=originalExtent[1];}elseif(typeofmax==='function'){max=max({min:originalExtent[0],max:originalExtent[1]});}(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 zeroif(model.getNeedCrossZero()){// Axis is over zero and min is not setif(min>0&&max>0&&!fixMin){min=0;}// Axis is under zero and max is not setif(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// is base axis// FIXME// (1) Consider support value axis, where below zero and axis `onZero` should be handled properly.// (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent?// Should not depend on series type `bar`?// (3) Fix that might overlap when using dataZoom.// (4) Consider other chart types using `barGrid`?// See #6728, #4862, `test/bar-overflow-time-plot.html`varecModel=model.ecModel;if(ecModel&&(scaleType==='time'/*|| scaleType === 'interval' */)){varbarSeriesModels=prepareLayoutBarSeries('bar',ecModel);varisBaseAxisAndHasBarSeries;each$1(barSeriesModels,function(seriesModel){isBaseAxisAndHasBarSeries|=seriesModel.getBaseAxis()===model.axis;});if(isBaseAxisAndHasBarSeries){// Calculate placement of bars on axisvarbarWidthAndOffset=makeColumnLayout(barSeriesModels);// Adjust axis min and max to account for overflowvaradjustedScale=adjustScaleForOverflow(min,max,model,barWidthAndOffset);min=adjustedScale.min;max=adjustedScale.max;}}return[min,max];}functionadjustScaleForOverflow(min,max,model,barWidthAndOffset){// Get Axis LengthvaraxisExtent=model.axis.getExtent();varaxisLength=axisExtent[1]-axisExtent[0];// Get bars on current base axis and calculate min and max overflowvarbarsOnCurrentAxis=retrieveColumnLayout(barWidthAndOffset,model.axis);if(barsOnCurrentAxis===undefined){return{min:min,max:max};}varminOverflow=Infinity;each$1(barsOnCurrentAxis,function(item){minOverflow=Math.min(item.offset,minOverflow);});varmaxOverflow=-Infinity;each$1(barsOnCurrentAxis,function(item){maxOverflow=Math.max(item.offset+item.width,maxOverflow);});minOverflow=Math.abs(minOverflow);maxOverflow=Math.abs(maxOverflow);vartotalOverFlow=minOverflow+maxOverflow;// Calulate required buffer based on old range and overflowvaroldRange=max-min;varoldRangePercentOfNew=(1-(minOverflow+maxOverflow)/axisLength);varoverflowBuffer=((oldRange/oldRangePercentOfNew)-oldRange);max+=overflowBuffer*(maxOverflow/totalOverFlow);min-=overflowBuffer*(minOverflow/totalOverFlow);return{min:min,max:max};}functionniceScaleExtent(scale,model){varextent=getScaleExtent(scale,model);varfixMin=model.getMin()!=null;varfixMax=model.getMax()!=null;varsplitNumber=model.get('splitNumber');if(scale.type==='log'){scale.base=model.get('logBase');}varscaleType=scale.type;scale.setExtent(extent[0],extent[1]);scale.niceExtent({splitNumber:splitNumber,fixMin:fixMin,fixMax: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// is not good enough. He can specify the interval. It is often appeared// in angle axis with angle 0 - 360. Interval calculated in interval scale is hard// to be 60.// FIXMEvarinterval=model.get('interval');if(interval!=null){scale.setInterval&&scale.setInterval(interval);}}/** * @param {module:echarts/model/Model}model*@param{string}[axisType]Defaultretrievefrommodel.type*@return{module:echarts/scale/*}*/function createScaleByModel(model, axisType) { axisType = axisType || model.get('type'); if (axisType) { switch (axisType) { //Buildinscalecase'category':returnnewOrdinalScale(model.getOrdinalMeta?model.getOrdinalMeta():model.getCategories(),[Infinity,-Infinity]);case'value':returnnewIntervalScale();// Extended scale, like time and logdefault:return(Scale.getClass(axisType)||IntervalScale).create(model);}}}/** * Check if the axis corss 0 */functionifAxisCrossZero(axis){vardataExtent=axis.scale.getExtent();varmin=dataExtent[0];varmax=dataExtent[1];return!((min>0&&max>0)||(min<0&&max<0));}/** * @param {module:echarts/coord/Axis}axis*@return{Function}Labelformatterfunction.*param:{number}tickValue,*param:{number}idx,theindexinallticks.*Ifcategoryaxis,thisparamisnotrequied.*return:{string}labelstring.*/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) { //Forcategoryaxis,getrawvalue;fornumericaxis,// get foramtted label like '1,333,444'.val=axis.scale.getLabel(val);returntpl.replace('{value}',val!=null?val:'');};})(labelFormatter);// Consider empty arrayreturnlabelFormatter;}elseif(typeoflabelFormatter==='function'){returnfunction(tickValue,idx){// The original intention of `idx` is "the index of the tick in all ticks".// But the previous implementation of category axis do not consider the// `axisLabel.interval`, which cause that, for example, the `interval` is// `1`, then the ticks "name5", "name7", "name9" are displayed, where the// corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep// the definition here for back compatibility.if(categoryTickStart!=null){idx=tickValue-categoryTickStart;}returnlabelFormatter(getAxisRawValue(axis,tickValue),idx);};}else{returnfunction(tick){returnaxis.scale.getLabel(tick);};}}functiongetAxisRawValue(axis,value){// In category axis with data zoom, tick is not the original// index of axis.data. So tick should not be exposed to user// in category axis.returnaxis.type==='category'?axis.scale.getLabel(value):value;}/** * @param {module:echarts/coord/Axis}axis*@return{module:zrender/core/BoundingRect}Benull/undefinedifnolabels.*/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(); //Optimizeforlargecategorydata,avoidcall`getTicks()`.if(isCategory){tickCount=scale.count();}else{realNumberScaleTicks=scale.getTicks();tickCount=realNumberScaleTicks.length;}varaxisLabelModel=axis.getLabelModel();varlabelFormatter=makeLabelFormatter(axis);varrect;varstep=1;// Simple optimization for large amount of labelsif(tickCount>40){step=Math.ceil(tickCount/40);}for(vari=0;i<tickCount;i+=step){vartickValue=realNumberScaleTicks?realNumberScaleTicks[i]:categoryScaleExtent[0]+i;varlabel=labelFormatter(tickValue);varunrotatedSingleRect=axisLabelModel.getTextRect(label);varsingleRect=rotateTextRect(unrotatedSingleRect,axisLabelModel.get('rotate')||0);rect?rect.union(singleRect):(rect=singleRect);}returnrect;}functionrotateTextRect(textRect,rotate){varrotateRadians=rotate*Math.PI/180;varboundingBox=textRect.plain();varbeforeWidth=boundingBox.width;varbeforeHeight=boundingBox.height;varafterWidth=beforeWidth*Math.cos(rotateRadians)+beforeHeight*Math.sin(rotateRadians);varafterHeight=beforeWidth*Math.sin(rotateRadians)+beforeHeight*Math.cos(rotateRadians);varrotatedRect=newBoundingRect(boundingBox.x,boundingBox.y,afterWidth,afterHeight);returnrotatedRect;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Cartesiancoordinatesystem*@moduleecharts/coord/Cartesian**/function dimAxisMapper(dim) { return this._axes[dim];}/***@aliasmodule:echarts/coord/Cartesian*@constructor*/var Cartesian = function (name) { this._axes = {}; this._dimList = []; /***@type{string}*/ this.name = name || '';};Cartesian.prototype = { constructor: Cartesian, type: 'cartesian', /***Getaxis*@param{number|string}dim*@return{module:echarts/coord/Cartesian~Axis}*/ getAxis: function (dim) { return this._axes[dim]; }, /***Getaxeslist*@return{Array.<module:echarts/coord/Cartesian~Axis>}*/ getAxes: function () { return map(this._dimList, dimAxisMapper, this); }, /***Getaxeslistbygivenscaletype*/ getAxesByScale: function (scaleType) { scaleType = scaleType.toLowerCase(); return filter( this.getAxes(), function (axis) { return axis.scale.type === scaleType; }); }, /***Addaxis*@param{module:echarts/coord/Cartesian.Axis}*/ addAxis: function (axis) { var dim = axis.dim; this._axes[dim] = axis; this._dimList.push(dim); }, /***Convertdatatocoordinndspace*@param{Array.<number>|Object.<string,number>}val*@return{Array.<number>|Object.<string,number>}*/ dataToCoord: function (val) { return this._dataCoordConvert(val, 'dataToCoord'); }, /***Convertcoordinndspacetodata*@param{Array.<number>|Object.<string,number>}val*@return{Array.<number>|Object.<string,number>}*/ coordToData: function (val) { return this._dataCoordConvert(val, 'coordToData'); }, _dataCoordConvert: function (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; }};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/function Cartesian2D(name) { Cartesian.call(this, name);}Cartesian2D.prototype = { constructor: Cartesian2D, type: 'cartesian2d', /***@type{Array.<string>}*@readOnly*/ dimensions: ['x', 'y'], /***Baseaxiswillbeusedonstacking.**@return{module:echarts/coord/cartesian/Axis2D}*/ getBaseAxis: function () { return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x'); }, /***Ifcontainpoint*@param{Array.<number>}point*@return{boolean}*/ containPoint: function (point) { var axisX = this.getAxis('x'); var axisY = this.getAxis('y'); return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1])); }, /***Ifcontaindata*@param{Array.<number>}data*@return{boolean}*/ containData: function (data) { return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]); }, /***@param{Array.<number>}data*@param{Array.<number>}out*@return{Array.<number>}*/ dataToPoint: function (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; }, /***@param{Array.<number>}data*@param{Array.<number>}out*@return{Array.<number>}*/ clampData: function (data, out) { var xScale = this.getAxis('x').scale; var yScale = this.getAxis('y').scale; var xAxisExtent = xScale.getExtent(); var yAxisExtent = yScale.getExtent(); var x = xScale.parse(data[0]); var y = yScale.parse(data[1]); out = out || []; out[0] = Math.min( Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1])); out[1] = Math.min( Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1])); return out; }, /***@param{Array.<number>}point*@param{Array.<number>}out*@return{Array.<number>}*/ pointToData: function (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; }, /***Getotheraxis*@param{module:echarts/coord/cartesian/Axis2D}axis*/ getOtherAxis: function (axis) { return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); }};inherits(Cartesian2D, Cartesian);/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var inner$6 = makeInner();/***@param{module:echats/coord/Axis}axis*@return{Object}{*labels:[{*formattedLabel:string,*rawLabel:string,*tickValue:number*},...],*labelCategoryInterval:number*}*/function createAxisLabels(axis) { //Onlyordinalscalesupporttickintervalreturnaxis.type==='category'?makeCategoryLabels(axis):makeRealNumberLabels(axis);}/** * @param {module:echats/coord/Axis}axis*@param{module:echarts/model/Model}tickModelForexample,canbeaxisTick,splitLine,splitArea.*@return{Object}{*ticks:Array.<number>*tickCategoryInterval:number*}*/function createAxisTicks(axis, tickModel) { //Onlyordinalscalesupporttickintervalreturnaxis.type==='category'?makeCategoryTicks(axis,tickModel):{ticks:axis.scale.getTicks()};}functionmakeCategoryLabels(axis){varlabelModel=axis.getLabelModel();varresult=makeCategoryLabelsActually(axis,labelModel);return(!labelModel.get('show')||axis.scale.isBlank())?{labels:[],labelCategoryInterval:result.labelCategoryInterval}:result;}functionmakeCategoryLabelsActually(axis,labelModel){varlabelsCache=getListCache(axis,'labels');varoptionLabelInterval=getOptionCategoryInterval(labelModel);varresult=listCacheGet(labelsCache,optionLabelInterval);if(result){returnresult;}varlabels;varnumericLabelInterval;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.returnlistCacheSet(labelsCache,optionLabelInterval,{labels:labels,labelCategoryInterval:numericLabelInterval});}functionmakeCategoryTicks(axis,tickModel){varticksCache=getListCache(axis,'ticks');varoptionTickInterval=getOptionCategoryInterval(tickModel);varresult=listCacheGet(ticksCache,optionTickInterval);if(result){returnresult;}varticks;vartickCategoryInterval;// Optimize for the case that large category data and no label displayed,// we should not return all ticks.if(!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// scenario, Use multiple grid with the xAxis sync, and only one xAxis shows// labels. `splitLine` and `axisTick` should be consistent in this case.elseif(optionTickInterval==='auto'){varlabelsResult=makeCategoryLabelsActually(axis,axis.getLabelModel());tickCategoryInterval=labelsResult.labelCategoryInterval;ticks=map(labelsResult.labels,function(labelItem){returnlabelItem.tickValue;});}else{tickCategoryInterval=optionTickInterval;ticks=makeLabelsByNumericCategoryInterval(axis,tickCategoryInterval,true);}// Cache to avoid calling interval function repeatly.returnlistCacheSet(ticksCache,optionTickInterval,{ticks:ticks,tickCategoryInterval:tickCategoryInterval});}functionmakeRealNumberLabels(axis){varticks=axis.scale.getTicks();varlabelFormatter=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// probably be fetched by multiple times. So we cache the result.// axis is created each time during a ec process, so we do not need to clear cache.functiongetListCache(axis,prop){// Because key can be funciton, and cache size always be small, we use array cache.returninner$6(axis)[prop]||(inner$6(axis)[prop]=[]);}functionlistCacheGet(cache,key){for(vari=0;i<cache.length;i++){if(cache[i].key===key){returncache[i].value;}}}functionlistCacheSet(cache,key,value){cache.push({key:key,value:value});returnvalue;}functionmakeAutoCategoryInterval(axis){varresult=inner$6(axis).autoInterval;returnresult!=null?result:(inner$6(axis).autoInterval=axis.calculateCategoryInterval());}/** * Calculate interval for category axis ticks and labels. * To get precise result, at least one of `getRotate` and `isHorizontal` * should be implemented in axis. */functioncalculateCategoryInterval(axis){varparams=fetchAutoCategoryIntervalCalculationParams(axis);varlabelFormatter=makeLabelFormatter(axis);varrotation=(params.axisRotate-params.labelRotate)/180*Math.PI;varordinalScale=axis.scale;varordinalExtent=ordinalScale.getExtent();// Providing this method is for optimization:// avoid generating a long array by `getTicks`// in large category data case.vartickCount=ordinalScale.count();if(ordinalExtent[1]-ordinalExtent[0]<1){return0;}varstep=1;// Simple optimization. Empirical value: tick count should less than 40.if(tickCount>40){step=Math.max(1,Math.floor(tickCount/40));}vartickValue=ordinalExtent[0];varunitSpan=axis.dataToCoord(tickValue+1)-axis.dataToCoord(tickValue);varunitW=Math.abs(unitSpan*Math.cos(rotation));varunitH=Math.abs(unitSpan*Math.sin(rotation));varmaxW=0;varmaxH=0;// Caution: Performance sensitive for large category data.// Consider dataZoom, we should make appropriate step to avoid O(n) loop.for(;tickValue<=ordinalExtent[1];tickValue+=step){varwidth=0;varheight=0;// Not precise, do not consider align and vertical align// and each distance from axis line yet.varrect=getBoundingRect(labelFormatter(tickValue),params.font,'center','top');// Magic numberwidth=rect.width*1.3;height=rect.height*1.3;// Min size, void long loop.maxW=Math.max(maxW,width,7);maxH=Math.max(maxH,height,7);}vardw=maxW/unitW;vardh=maxH/unitH;// 0/0 is NaN, 1/0 is Infinity.isNaN(dw)&&(dw=Infinity);isNaN(dh)&&(dh=Infinity);varinterval=Math.max(0,Math.floor(Math.min(dw,dh)));varcache=inner$6(axis.model);varlastAutoInterval=cache.lastAutoInterval;varlastTickCount=cache.lastTickCount;// Use cache to keep interval stable while moving zoom window,// otherwise the calculated interval might jitter when the zoom// window size is close to the interval-changing size.if(lastAutoInterval!=null&&lastTickCount!=null&&Math.abs(lastAutoInterval-interval)<=1&&Math.abs(lastTickCount-tickCount)<=1// Always choose the bigger one, otherwise the critical// point is not the same when zooming in or zooming out.&&lastAutoInterval>interval){interval=lastAutoInterval;}// Only update cache if cache not used, otherwise the// changing of interval is too insensitive.else{cache.lastTickCount=tickCount;cache.lastAutoInterval=interval;}returninterval;}functionfetchAutoCategoryIntervalCalculationParams(axis){varlabelModel=axis.getLabelModel();return{axisRotate:axis.getRotate?axis.getRotate():(axis.isHorizontal&&!axis.isHorizontal())?90:0,labelRotate:labelModel.get('rotate')||0,font:labelModel.getFont()};}functionmakeLabelsByNumericCategoryInterval(axis,categoryInterval,onlyTick){varlabelFormatter=makeLabelFormatter(axis);varordinalScale=axis.scale;varordinalExtent=ordinalScale.getExtent();varlabelModel=axis.getLabelModel();varresult=[];// TODO: axisType: ordinalTime, pick the tick from each month/day/year/...varstep=Math.max((categoryInterval||0)+1,1);varstartTick=ordinalExtent[0];vartickCount=ordinalScale.count();// Calculate start tick based on zero if possible to keep label consistent// while zooming and moving while interval > 0. Otherwise the selection// of displayable ticks and symbols probably keep changing.// 3 is empirical value.if(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// to render stage, which also ensure the returned list// suitable for splitLine and splitArea rendering.// (2) Scales except category always contain min max label so// do not need to perform this process.varshowMinMax={min:labelModel.get('showMinLabel'),max:labelModel.get('showMaxLabel')};if(showMinMax.min&&startTick!==ordinalExtent[0]){addItem(ordinalExtent[0]);}// Optimize: avoid generating large array by `ordinalScale.getTicks()`.vartickValue=startTick;for(;tickValue<=ordinalExtent[1];tickValue+=step){addItem(tickValue);}if(showMinMax.max&&tickValue!==ordinalExtent[1]){addItem(ordinalExtent[1]);}functionaddItem(tVal){result.push(onlyTick?tVal:{formattedLabel:labelFormatter(tVal),rawLabel:ordinalScale.getLabel(tVal),tickValue:tVal});}returnresult;}// When interval is function, the result `false` means ignore the tick.// It is time consuming for large category data.functionmakeLabelsByCustomizedCategoryInterval(axis,categoryInterval,onlyTick){varordinalScale=axis.scale;varlabelFormatter=makeLabelFormatter(axis);varresult=[];each$1(ordinalScale.getTicks(),function(tickValue){varrawLabel=ordinalScale.getLabel(tickValue);if(categoryInterval(tickValue,rawLabel)){result.push(onlyTick?tickValue:{formattedLabel:labelFormatter(tickValue),rawLabel:rawLabel,tickValue:tickValue});}});returnresult;}// Can be null|'auto'|number|functionfunctiongetOptionCategoryInterval(model){varinterval=model.get('interval');returninterval==null?'auto':interval;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var NORMALIZED_EXTENT = [0, 1];/***BaseclassofAxis.*@constructor*/var Axis = function (dim, scale, extent) { /***Axisdimension.Suchas'x','y','z','angle','radius'.*@type{string}*/ this.dim = dim; /***Axisscale*@type{module:echarts/coord/scale/*}*/ this.scale = scale; /***@type{Array.<number>}*@private*/ this._extent = extent || [0, 0]; /***@type{boolean}*/ this.inverse = false; /***Usuallytruewhenaxishasaordinalscale*@type{boolean}*/ this.onBand = false;};Axis.prototype = { constructor: Axis, /***Ifaxisextentcontaingivencoord*@param{number}coord*@return{boolean}*/ contain: function (coord) { var extent = this._extent; var min = Math.min(extent[0], extent[1]); var max = Math.max(extent[0], extent[1]); return coord >= min && coord <= max; }, /***Ifaxisextentcontaingivendata*@param{number}data*@return{boolean}*/ containData: function (data) { return this.contain(this.dataToCoord(data)); }, /***Getcoordextent.*@return{Array.<number>}*/ getExtent: function () { return this._extent.slice(); }, /***Getprecisionusedforformatting*@param{Array.<number>}[dataExtent]*@return{number}*/ getPixelPrecision: function (dataExtent) { return getPixelPrecision( dataExtent || this.scale.getExtent(), this._extent); }, /***Setcoordextent*@param{number}start*@param{number}end*/ setExtent: function (start, end) { var extent = this._extent; extent[0] = start; extent[1] = end; }, /***Convertdatatocoord.Dataistherankifithasanordinalscale*@param{number}data*@param{boolean}clamp*@return{number}*/ dataToCoord: function (data, clamp) { var extent = this._extent; var scale = this.scale; data = scale.normalize(data); if (this.onBand && scale.type === 'ordinal') { extent = extent.slice(); fixExtentWithBands(extent, scale.count()); } return linearMap(data, NORMALIZED_EXTENT, extent, clamp); }, /***Convertcoordtodata.Dataistherankifithasanordinalscale*@param{number}coord*@param{boolean}clamp*@return{number}*/ coordToData: function (coord, clamp) { var extent = this._extent; var scale = this.scale; if (this.onBand && scale.type === 'ordinal') { extent = extent.slice(); fixExtentWithBands(extent, scale.count()); } var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp); return this.scale.scale(t); }, /***Convertpixelpointtodatainaxis*@param{Array.<number>}point*@param{boolean}clamp*@return{number}data*/ pointToData: function (point, clamp) { //Shouldbeimplementedinderivedclassifnecessary.},/** * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`, * `axis.getTicksCoords` considers `onBand`, which is used by * `boundaryGap:true` of category axis and splitLine and splitArea. * @param {Object} [opt] * @param {number} [opt.tickModel=axis.model.getModel('axisTick')] * @param {boolean} [opt.clamp] If `true`, the first and the last * tick must be at the axis end points. Otherwise, clip ticks * that outside the axis extent. * @return {Array.<Object>} [{ * coord: ..., * tickValue: ... * }, ...] */getTicksCoords:function(opt){opt=opt||{};vartickModel=opt.tickModel||this.getTickModel();varresult=createAxisTicks(this,tickModel);varticks=result.ticks;varticksCoords=map(ticks,function(tickValue){return{coord:this.dataToCoord(tickValue),tickValue:tickValue};},this);varalignWithLabel=tickModel.get('alignWithLabel');fixOnBandTicksCoords(this,ticksCoords,result.tickCategoryInterval,alignWithLabel,opt.clamp);returnticksCoords;},/** * @return {Array.<Object>} [{ * formattedLabel: string, * rawLabel: axis.scale.getLabel(tickValue) * tickValue: number * }, ...] */getViewLabels:function(){returncreateAxisLabels(this).labels;},/** * @return {module:echarts/coord/model/Model}*/ getLabelModel: function () { return this.model.getModel('axisLabel'); }, /***Noticehereweonlygetthedefaulttickmodel.ForsplitLine*orsplitArea,weshouldpassthesplitLineModelorsplitAreaModel*manuallywhencalling`getTicksCoords`.*InGL,thismethodmaybeoverridedto:*`axisModel.getModel('axisTick',grid3DModel.getModel('axisTick'));`*@return{module:echarts/coord/model/Model}*/ getTickModel: function () { return this.model.getModel('axisTick'); }, /***Getwidthofband*@return{number}*/ getBandWidth: function () { var axisExtent = this._extent; var dataExtent = this.scale.getExtent(); var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); //Fix#2728,avoidNaNwhenonlyonedata.len===0&&(len=1);varsize=Math.abs(axisExtent[1]-axisExtent[0]);returnMath.abs(size)/len;},/** * @abstract * @return {boolean} Is horizontal */isHorizontal:null,/** * @abstract * @return {number} Get axis rotate, by degree. */getRotate:null,/** * Only be called in category axis. * Can be overrided, consider other axes like in 3D. * @return {number} Auto interval for cateogry axis tick and label */calculateCategoryInterval:function(){returncalculateCategoryInterval(this);}};functionfixExtentWithBands(extent,nTick){varsize=extent[1]-extent[0];varlen=nTick;varmargin=size/len/2;extent[0]+=margin;extent[1]-=margin;}// If axis has labels [1, 2, 3, 4]. Bands on the axis are// |---1---|---2---|---3---|---4---|.// So the displayed ticks and splitLine/splitArea should between// each data item, otherwise cause misleading (e.g., split tow bars// of a single data item when there are two bar series).// Also consider if tickCategoryInterval > 0 and onBand, ticks and// splitLine/spliteArea should layout appropriately corresponding// to displayed labels. (So we should not use `getBandWidth` in this// case).functionfixOnBandTicksCoords(axis,ticksCoords,tickCategoryInterval,alignWithLabel,clamp){varticksLen=ticksCoords.length;if(!axis.onBand||alignWithLabel||!ticksLen){return;}varaxisExtent=axis.getExtent();varlast;if(ticksLen===1){ticksCoords[0].coord=axisExtent[0];last=ticksCoords[1]={coord:axisExtent[0]};}else{varshift=(ticksCoords[1].coord-ticksCoords[0].coord);each$1(ticksCoords,function(ticksItem){ticksItem.coord-=shift/2;vartickCategoryInterval=tickCategoryInterval||0;// Avoid split a single data item when odd interval.if(tickCategoryInterval%2>0){ticksItem.coord-=shift/((tickCategoryInterval+1)*2);}});last={coord:ticksCoords[ticksLen-1].coord+shift};ticksCoords.push(last);}varinverse=axisExtent[0]>axisExtent[1];if(littleThan(ticksCoords[0].coord,axisExtent[0])){clamp?(ticksCoords[0].coord=axisExtent[0]):ticksCoords.shift();}if(clamp&&littleThan(axisExtent[0],ticksCoords[0].coord)){ticksCoords.unshift({coord:axisExtent[0]});}if(littleThan(axisExtent[1],last.coord)){clamp?(last.coord=axisExtent[1]):ticksCoords.pop();}if(clamp&&littleThan(last.coord,axisExtent[1])){ticksCoords.push({coord:axisExtent[1]});}functionlittleThan(a,b){returninverse?a>b:a<b;}}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Extendaxis2d*@constructormodule:echarts/coord/cartesian/Axis2D*@extends{module:echarts/coord/cartesian/Axis}*@param{string}dim*@param{*}scale*@param{Array.<number>}coordExtent*@param{string}axisType*@param{string}position*/var Axis2D = function (dim, scale, coordExtent, axisType, position) { Axis.call(this, dim, scale, coordExtent); /***Axistype*-'category'*-'value'*-'time'*-'log'*@type{string}*/ this.type = axisType || 'value'; /***Axisposition*-'top'*-'bottom'*-'left'*-'right'*/ this.position = position || 'bottom';};Axis2D.prototype = { constructor: Axis2D, /***Indexofaxis,canbeusedaskey*/ index: 0, /***Implementedin<module:echarts/coord/cartesian/Grid>.*@return{Array.<module:echarts/coord/cartesian/Axis2D>}*Ifnotonzeroofotheraxis,returnnull/undefined.*Ifnoaxes,returnanemptyarray.*/ getAxesOnZeroOf: null, /***Axismodel*@param{module:echarts/coord/cartesian/AxisModel}*/ model: null, isHorizontal: function () { var position = this.position; return position === 'top' || position === 'bottom'; }, /***Eachitemcoorespondstothis.getExtent(),which*meansglobalExtent[0]maygreaterthanglobalExtent[1],*unless`asc`isinput.**@param{boolean}[asc]*@return{Array.<number>}*/ getGlobalExtent: function (asc) { var ret = this.getExtent(); ret[0] = this.toGlobalCoord(ret[0]); ret[1] = this.toGlobalCoord(ret[1]); asc && ret[0] > ret[1] && ret.reverse(); return ret; }, getOtherAxis: function () { this.grid.getOtherAxis(); }, /***@override*/ pointToData: function (point, clamp) { return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); }, /***Transformglobalcoordtolocalcoord,*i.e.varlocalCoord=axis.toLocalCoord(80);*designatebymodule:echarts/coord/cartesian/Grid.*@type{Function}*/ toLocalCoord: null, /***Transformglobalcoordtolocalcoord,*i.e.varglobalCoord=axis.toLocalCoord(40);*designatebymodule:echarts/coord/cartesian/Grid.*@type{Function}*/ toGlobalCoord: null};inherits(Axis2D, Axis);/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var defaultOption = { show: true, zlevel: 0, z: 0, //Inversetheaxis.inverse:false,// Axis name displayed.name:'',// 'start' | 'middle' | 'end'nameLocation:'end',// By degree. By defualt auto rotate by nameLocation.nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:'...',placeholder:'.'},// Use global text style by default.nameTextStyle:{},// The gap between axisName and axisLine.nameGap:15,// Default `false` to support tooltip.silent:false,// Default `false` to avoid legacy user event listener fail.triggerEvent: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.symbol:['none','none'],symbolSize:[10,15]},axisTick:{show:true,// Whether axisTick is inside the grid or outside the grid.inside:false,// The length of axisTick.length:5,lineStyle:{width:1}},axisLabel:{show:true,// Whether axisLabel is inside the grid or outside the grid.inside:false,rotate:0,// true | false | null/undefined (auto)showMinLabel:null,// true | false | null/undefined (auto)showMaxLabel:null,margin:8,// formatter: null,fontSize: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)']}}};varaxisDefault={};axisDefault.categoryAxis=merge({// The gap at both ends of the axis. For categoryAxis, boolean.boundaryGap:true,// Set false to faster category collection.// Only usefull in the case like: category is// ['2012-01-01', '2012-01-02', ...], where the input// data has been ensured not duplicate and is large data.// null means "auto":// if axis.data provided, do not deduplication,// else do deduplication.deduplication:null,// splitArea: {// show: false// },splitLine:{show:false},axisTick:{// If tick is align with label when boundaryGap is truealignWithLabel:false,interval:'auto'},axisLabel:{interval:'auto'}},defaultOption);axisDefault.valueAxis=merge({// The gap at both ends of the axis. For value axis, [GAP, GAP], where// `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`)boundaryGap:[0,0],// TODO// min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60]// Min value of the axis. can be:// + a number// + 'dataMin': use the min value in data.// + null/undefined: auto decide min value (consider pretty look and boundaryGap).// min: null,// Max value of the axis. can be:// + a number// + 'dataMax': use the max value in data.// + null/undefined: auto decide max value (consider pretty look and boundaryGap).// max: null,// Readonly prop, specifies start value of the range when using data zoom.// rangeStart: null// Readonly prop, specifies end value of the range when using data zoom.// rangeEnd: null// Optional value can be:// + `false`: always include value 0.// + `true`: the extent do not consider value 0.// scale: false,// AxisTick and axisLabel and splitLine are caculated based on splitNumber.splitNumber:5// Interval specifies the span of the ticks is mandatorily.// interval: null// Specify min interval when auto calculate tick interval.// minInterval: null// Specify max interval when auto calculate tick interval.// maxInterval: null},defaultOption);axisDefault.timeAxis=defaults({scale:true,min:'dataMin',max:'dataMax'},axisDefault.valueAxis);axisDefault.logAxis=defaults({scale:true,logBase:10},axisDefault.valueAxis);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///FIXMEaxisTypeisfixed?varAXIS_TYPES=['value','category','time','log'];/** * Generate sub axis model class * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel' * @param {module:echarts/model/Component}BaseAxisModelClass*@param{Function}axisTypeDefaulter*@param{Object}[extraDefaultOption]*/var axisModelCreator = function (axisName, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) { each$1(AXIS_TYPES, function (axisType) { BaseAxisModelClass.extend({ /***@readOnly*/ type: axisName + 'Axis.' + axisType, mergeDefaultAndTheme: function (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); } }, /***@override*/ optionUpdated: function () { var thisOption = this.option; if (thisOption.type === 'category') { this.__ordinalMeta = OrdinalMeta.createByAxisModel(this); } }, /***Shouldnotbecalledbeforeallof'getInitailData'finished.*Becausecategoriesarecollectedduringinitializingdata.*/ getCategories: function (rawData) { var option = this.option; //FIXME// warning if called before all of 'getInitailData' finished.if(option.type==='category'){if(rawData){returnoption.data;}returnthis.__ordinalMeta.categories;}},getOrdinalMeta:function(){returnthis.__ordinalMeta;},defaultOption:mergeAll([{},axisDefault[axisType+'Axis'],extraDefaultOption],true)});});ComponentModel.registerSubTypeDefaulter(axisName+'Axis',curry(axisTypeDefaulter,axisName));};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///import*asaxisHelperfrom'./axisHelper';varaxisModelCommonMixin={/***@param{boolean}origin*@return{number|string}minvalueor'dataMin'ornull/undefined(meansauto)orNaN*/ getMin: function (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; }, /***@param{boolean}origin*@return{number|string}maxvalueor'dataMax'ornull/undefined(meansauto)orNaN*/ getMax: function (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; }, /***@return{boolean}*/ getNeedCrossZero: function () { var option = this.option; return (option.rangeStart != null || option.rangeEnd != null)? false : !option.scale; }, /***Shouldbeimplementedbyeachaxismodelifnecessary.*@return{module:echarts/model/Component}coordinatesystemmodel*/ getCoordSysModel: noop, /***@param{number}rangeStartCanonlybefinitenumberornull/undefinedorNaN.*@param{number}rangeEndCanonlybefinitenumberornull/undefinedorNaN.*/ setRange: function (rangeStart, rangeEnd) { this.option.rangeStart = rangeStart; this.option.rangeEnd = rangeEnd; }, /***Resetrange*/ resetRange: function () { //rangeStartandrangeEndisreadonly.this.option.rangeStart=this.option.rangeEnd=null;}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var AxisModel = ComponentModel.extend({ type: 'cartesian2dAxis', /***@type{module:echarts/coord/cartesian/Axis2D}*/ axis: null, /***@override*/ init: function () { AxisModel.superApply(this, 'init', arguments); this.resetRange(); }, /***@override*/ mergeOption: function () { AxisModel.superApply(this, 'mergeOption', arguments); this.resetRange(); }, /***@override*/ restoreData: function () { AxisModel.superApply(this, 'restoreData', arguments); this.resetRange(); }, /***@override*@return{module:echarts/model/Component}*/ getCoordSysModel: function () { return this.ecModel.queryComponents({ mainType: 'grid', index: this.option.gridIndex, id: this.option.gridId })[0]; }});function getAxisType(axisDim, option) { //Defaultaxiswithdataiscategoryaxisreturnoption.type||(option.data?'category':'value');}merge(AxisModel.prototype,axisModelCommonMixin);varextraOption={// gridIndex: 0,// gridId: '',// Offset is for multiple axis on the same positionoffset:0};axisModelCreator('x',AxisModel,getAxisType,extraOption);axisModelCreator('y',AxisModel,getAxisType,extraOption);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Grid是在有直角坐标系的时候必须要存在的// 所以这里也要被 Cartesian2D 依赖ComponentModel.extend({type:'grid',dependencies:['xAxis','yAxis'],layoutMode:'box',/** * @type {module:echarts/coord/cartesian/Grid}*/ coordinateSystem: null, defaultOption: { show: false, zlevel: 0, z: 0, left: '10%', top: 60, right: '10%', bottom: 60, //IfgridsizecontainlabelcontainLabel:false,// width: {totalWidth} - left - right,// height: {totalHeight} - top - bottom,backgroundColor:'rgba(0,0,0,0)',borderWidth:1,borderColor:'#ccc'}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Gridisaregionwhichcontainsatmost4cartesiansystems**TODODefaultcartesian*///DependsonGridModel,AxisModel,whichperformspreprocess./***Checkiftheaxisisusedinthespecifiedgrid*@inner*/function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) { return axisModel.getCoordSysModel() === gridModel;}function Grid(gridModel, ecModel, api) { /***@type{Object.<string,module:echarts/coord/cartesian/Cartesian2D>}*@private*/ this._coordsMap = {}; /***@type{Array.<module:echarts/coord/cartesian/Cartesian>}*@private*/ this._coordsList = []; /***@type{Object.<string,module:echarts/coord/cartesian/Axis2D>}*@private*/ this._axesMap = {}; /***@type{Array.<module:echarts/coord/cartesian/Axis2D>}*@private*/ 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,whetheronZerotarget.varonZeroRecords={};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// FIXME It may cause getting wrong grid size in data processing stagethis.resize(this.model,api);};functionfixAxisOnZero(axesMap,otherAxisDim,axis,onZeroRecords){axis.getAxesOnZeroOf=function(){// TODO: onZero of multiple axes.returnotherAxisOnZeroOf?[otherAxisOnZeroOf]:[];};// onZero can not be enabled in these two situations:// 1. When any other axis is a category axis.// 2. When no axis is cross 0 point.varotherAxes=axesMap[otherAxisDim];varotherAxisOnZeroOf;varaxisModel=axis.model;varonZero=axisModel.get('axisLine.onZero');varonZeroAxisIndex=axisModel.get('axisLine.onZeroAxisIndex');if(!onZero){return;}// If target axis is specified.if(onZeroAxisIndex!=null){if(canOnZeroToAxis(otherAxes[onZeroAxisIndex])){otherAxisOnZeroOf=otherAxes[onZeroAxisIndex];}}else{// Find the first available other axis.for(varidxinotherAxes){if(otherAxes.hasOwnProperty(idx)&&canOnZeroToAxis(otherAxes[idx])// Consider that two Y axes on one value axis,// if both onZero, the two Y axes overlap.&&!onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]){otherAxisOnZeroOf=otherAxes[idx];break;}}}if(otherAxisOnZeroOf){onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)]=true;}functiongetOnZeroRecordKey(axis){returnaxis.dim+'_'+axis.index;}}functioncanOnZeroToAxis(axis){returnaxis&&axis.type!=='category'&&axis.type!=='time'&&ifAxisCrossZero(axis);}/** * Resize the grid * @param {module:echarts/coord/cartesian/GridModel}gridModel*@param{module:echarts/ExtensionAPI}api*/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(); //Minuslabelsizeif(!ignoreContainLabel&&gridModel.get('containLabel')){each$1(axesList,function(axis){if(!axis.model.get('axisLabel.inside')){varlabelUnionRect=estimateLabelUnionRect(axis);if(labelUnionRect){vardim=axis.isHorizontal()?'height':'width';varmargin=axis.model.get('axisLabel.margin');gridRect[dim]-=labelUnionRect[dim]+margin;if(axis.position==='top'){gridRect.y+=labelUnionRect.height+margin;}elseif(axis.position==='left'){gridRect.x+=labelUnionRect.width+margin;}}}});adjustAxes();}functionadjustAxes(){each$1(axesList,function(axis){varisHorizontal=axis.isHorizontal();varextent=isHorizontal?[0,gridRect.width]:[0,gridRect.height];varidx=axis.inverse?1:0;axis.setExtent(extent[idx],extent[1-idx]);updateAxisTransform(axis,isHorizontal?gridRect.x:gridRect.y);});}};/** * @param {string} axisType * @param {number} [axisIndex] */gridProto.getAxis=function(axisType,axisIndex){varaxesMapOnDim=this._axesMap[axisType];if(axesMapOnDim!=null){if(axisIndex==null){// Find first axisfor(varnameinaxesMapOnDim){if(axesMapOnDim.hasOwnProperty(name)){returnaxesMapOnDim[name];}}}returnaxesMapOnDim[axisIndex];}};/** * @return {Array.<module:echarts/coord/Axis>}*/gridProto.getAxes = function () { return this._axesList.slice();};/***Usage:*grid.getCartesian(xAxisIndex,yAxisIndex);*grid.getCartesian(xAxisIndex);*grid.getCartesian(null,yAxisIndex);*grid.getCartesian({xAxisIndex:...,yAxisIndex:...});**@param{number|Object}[xAxisIndex]*@param{number}[yAxisIndex]*/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; } //WhenonlyxAxisIndexoryAxisIndexgiven,finditsfirstcartesian.for(vari=0,coordList=this._coordsList;i<coordList.length;i++){if(coordList[i].getAxis('x').index===xAxisIndex||coordList[i].getAxis('y').index===yAxisIndex){returncoordList[i];}}};gridProto.getCartesians=function(){returnthis._coordsList.slice();};/** * @implements * see {module:echarts/CoodinateSystem}*/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;};/***@implements*see{module:echarts/CoodinateSystem}*/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;};/***@inner*/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); } //Lowestpriority.elseif(gridModel){vargrid=gridModel.coordinateSystem;if(grid===this){cartesian=this._coordsList[0];}}return{cartesian:cartesian,axis:axis};};/** * @implements * see {module:echarts/CoodinateSystem}*/gridProto.containPoint = function (point) { var coord = this._coordsList[0]; if (coord) { return coord.containPoint(point); }};/***Initializecartesiancoordinatesystems*@private*/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 axisecModel.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 axisthis._axesMap={};this._axesList=[];return;}this._axesMap=axesMap;/// Create cartesian2deach$1(axesMap.x,function(xAxis,xAxisIndex){each$1(axesMap.y,function(yAxis,yAxisIndex){varkey='x'+xAxisIndex+'y'+yAxisIndex;varcartesian=newCartesian2D(key);cartesian.grid=this;cartesian.model=gridModel;this._coordsMap[key]=cartesian;this._coordsList.push(cartesian);cartesian.addAxis(xAxis);cartesian.addAxis(yAxis);},this);},this);functioncreateAxisCreator(axisType){returnfunction(axisModel,idx){if(!isAxisUsedInTheGrid(axisModel,gridModel,ecModel)){return;}varaxisPosition=axisModel.get('position');if(axisType==='x'){// Fix positionif(axisPosition!=='top'&&axisPosition!=='bottom'){// Default bottom of XaxisPosition='bottom';if(axisPositionUsed[axisPosition]){axisPosition=axisPosition==='top'?'bottom':'top';}}}else{// Fix positionif(axisPosition!=='left'&&axisPosition!=='right'){// Default left of YaxisPosition='left';if(axisPositionUsed[axisPosition]){axisPosition=axisPosition==='left'?'right':'left';}}}axisPositionUsed[axisPosition]=true;varaxis=newAxis2D(axisType,createScaleByModel(axisModel),[0,0],axisModel.get('type'),axisPosition);varisCategory=axis.type==='category';axis.onBand=isCategory&&axisModel.get('boundaryGap');axis.inverse=axisModel.get('inverse');// Inject axis into axisModelaxisModel.axis=axis;// Inject axisModel into axisaxis.model=axisModel;// Inject grid info axisaxis.grid=this;// Index of axis, can be used as keyaxis.index=idx;this._axesList.push(axis);axesMap[axisType][idx]=axis;axesCount[axisType]++;};}};/** * Update cartesian properties from series * @param {module:echarts/model/Option}option*@private*/gridProto._updateScale = function (ecModel, gridModel) { //Resetscaleeach$1(this._axesList,function(axis){axis.scale.setExtent(Infinity,-Infinity);});ecModel.eachSeries(function(seriesModel){if(isCartesian2D(seriesModel)){varaxesModels=findAxesModels(seriesModel,ecModel);varxAxisModel=axesModels[0];varyAxisModel=axesModels[1];if(!isAxisUsedInTheGrid(xAxisModel,gridModel,ecModel)||!isAxisUsedInTheGrid(yAxisModel,gridModel,ecModel)){return;}varcartesian=this.getCartesian(xAxisModel.componentIndex,yAxisModel.componentIndex);vardata=seriesModel.getData();varxAxis=cartesian.getAxis('x');varyAxis=cartesian.getAxis('y');if(data.type==='list'){unionExtent(data,xAxis,seriesModel);unionExtent(data,yAxis,seriesModel);}}},this);functionunionExtent(data,axis,seriesModel){each$1(data.mapDimension(axis.dim,true),function(dim){axis.scale.unionExtentFromData(// For example, the extent of the orginal dimension// is [0.1, 0.5], the extent of the `stackResultDimension`// is [7, 9], the final extent should not include [0.1, 0.5].data,getStackedDimension(data,dim));});}};/** * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined*@return{Object}{baseAxes:[],otherAxes:[]}*/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};};/***@inner*/function updateAxisTransform(axis, coordBase) { var axisExtent = axis.getExtent(); var axisExtentSum = axisExtent[0] + axisExtent[1]; //Fasttransformaxis.toGlobalCoord=axis.dim==='x'?function(coord){returncoord+coordBase;}:function(coord){returnaxisExtentSum-coord+coordBase;};axis.toLocalCoord=axis.dim==='x'?function(coord){returncoord-coordBase;}:function(coord){returnaxisExtentSum-coord+coordBase;};}varaxesTypes=['xAxis','yAxis'];/** * @inner */functionfindAxesModels(seriesModel,ecModel){returnmap(axesTypes,function(axisType){varaxisModel=seriesModel.getReferringComponents(axisType)[0];if(__DEV__){if(!axisModel){thrownewError(axisType+' "'+retrieve(seriesModel.get(axisType+'Index'),seriesModel.get(axisType+'Id'),0)+'" not found');}}returnaxisModel;});}/** * @inner */functionisCartesian2D(seriesModel){returnseriesModel.get('coordinateSystem')==='cartesian2d';}Grid.create=function(ecModel,api){vargrids=[];ecModel.eachComponent('grid',function(gridModel,idx){vargrid=newGrid(gridModel,ecModel,api);grid.name='grid_'+idx;// dataSampling requires axis extent, so resize// should be performed in create stage.grid.resize(gridModel,api,true);gridModel.coordinateSystem=grid;grids.push(grid);});// Inject the coordinateSystems into seriesModelecModel.eachSeries(function(seriesModel){if(!isCartesian2D(seriesModel)){return;}varaxesModels=findAxesModels(seriesModel,ecModel);varxAxisModel=axesModels[0];varyAxisModel=axesModels[1];vargridModel=xAxisModel.getCoordSysModel();if(__DEV__){if(!gridModel){thrownewError('Grid "'+retrieve(xAxisModel.get('gridIndex'),xAxisModel.get('gridId'),0)+'" not found');}if(xAxisModel.getCoordSysModel()!==yAxisModel.getCoordSysModel()){thrownewError('xAxis and yAxis must use the same grid');}}vargrid=gridModel.coordinateSystem;seriesModel.coordinateSystem=grid.getCartesian(xAxisModel.componentIndex,yAxisModel.componentIndex);});returngrids;};// For deciding which dimensions to use when creating list dataGrid.dimensions=Grid.prototype.dimensions=Cartesian2D.prototype.dimensions;CoordinateSystemManager.register('cartesian2d',Grid);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var PI$2 = Math.PI;function makeAxisEventDataBase(axisModel) { var eventData = { componentType: axisModel.mainType, componentIndex: axisModel.componentIndex }; eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; return eventData;}/***Afinalaxisistranslatedandrotatedfroma"standard axis".*Soopt.positionandopt.rotationisrequired.**Astandardaxisisandaxisfrom[0,0]to[0,axisExtent[1]],*forexample:(0,0)------------>(0,50)**nameDirectionortickDirectionorlabelDirectionis1meanstick*orlabelisbelowthestandardaxis,whereasis-1meansabove*thestandardaxis.labelOffsetmeansoffsetbetweenlabelandaxis,*whichisusefulwhen'onZero',whereaxisLabelisinthegridand*labelinoutsidegrid.**Tips:likealways,*positiverotationrepresentsanticlockwise,andnegativerotation*representsclockwise.*Thedirectionofpositioncoordinateisthesameasthedirection*ofscreencoordinate.**Donotneedtoconsideraxis'inverse',whichisautoprocessedby*axisextent.**@param{module:zrender/container/Group}group*@param{Object}axisModel*@param{Object}optStandardaxisparameters.*@param{Array.<number>}opt.position[x,y]*@param{number}opt.rotationbyradian*@param{number}[opt.nameDirection=1]1or-1UsedwhennameLocationis'middle'or'center'.*@param{number}[opt.tickDirection=1]1or-1*@param{number}[opt.labelDirection=1]1or-1*@param{number}[opt.labelOffset=0]UsefullwhenonZero.*@param{string}[opt.axisLabelShow]defaultgetfromaxisModel.*@param{string}[opt.axisName]defaultgetfromaxisModel.*@param{number}[opt.axisNameAvailableWidth]*@param{number}[opt.labelRotate]bydegree,defaultgetfromaxisModel.*@param{number}[opt.strokeContainThreshold]Defaultlabelintervalwhenlabel*@param{number}[opt.nameTruncateMaxWidth]*/var AxisBuilder = function (axisModel, opt) { /***@readOnly*/ this.opt = opt; /***@readOnly*/ this.axisModel = axisModel; //Defaultvaluedefaults(opt,{labelOffset:0,nameDirection:1,tickDirection:1,labelDirection:1,silent:true});/** * @readOnly */this.group=newGroup();// FIXME Not use a seperate text group?vardumbGroup=newGroup({position:opt.position.slice(),rotation:opt.rotation});// this.group.add(dumbGroup);// this._dumbGroup = dumbGroup;dumbGroup.updateTransform();this._transform=dumbGroup.transform;this._dumbGroup=dumbGroup;};AxisBuilder.prototype={constructor:AxisBuilder,hasBuilder:function(name){return!!builders[name];},add:function(name){builders[name].call(this);},getGroup:function(){returnthis.group;}};varbuilders={/***@private*/ axisLine: function () { 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(subPixelOptimizeLine({ //Idforanimationanid:'line',shape:{x1:pt1[0],y1:pt1[1],x2:pt2[0],y2:pt2[1]},style:lineStyle,strokeContainThreshold:opt.strokeContainThreshold||5,silent:true,z2:1})));vararrows=axisModel.get('axisLine.symbol');vararrowSize=axisModel.get('axisLine.symbolSize');vararrowOffset=axisModel.get('axisLine.symbolOffset')||0;if(typeofarrowOffset==='number'){arrowOffset=[arrowOffset,arrowOffset];}if(arrows!=null){if(typeofarrows==='string'){// Use the same arrow for start and end pointarrows=[arrows,arrows];}if(typeofarrowSize==='string'||typeofarrowSize==='number'){// Use the same size for width and heightarrowSize=[arrowSize,arrowSize];}varsymbolWidth=arrowSize[0];varsymbolHeight=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){varsymbol=createSymbol(arrows[index],-symbolWidth/2,-symbolHeight/2,symbolWidth,symbolHeight,lineStyle.stroke,true);// Calculate arrow position with offsetvarr=point.r+point.offset;varpos=[pt1[0]+r*Math.cos(opt.rotation),pt1[1]-r*Math.sin(opt.rotation)];symbol.attr({rotation:point.rotate,position:pos,silent:true});this.group.add(symbol);}},this);}},/** * @private */axisTickLabel:function(){varaxisModel=this.axisModel;varopt=this.opt;vartickEls=buildAxisTick(this,axisModel,opt);varlabelEls=buildAxisLabel(this,axisModel,opt);fixMinMaxLabelShow(axisModel,labelEls,tickEls);},/** * @private */axisName:function(){varopt=this.opt;varaxisModel=this.axisModel;varname=retrieve(opt.axisName,axisModel.get('name'));if(!name){return;}varnameLocation=axisModel.get('nameLocation');varnameDirection=opt.nameDirection;vartextStyleModel=axisModel.getModel('nameTextStyle');vargap=axisModel.get('nameGap')||0;varextent=this.axisModel.axis.getExtent();vargapSignal=extent[0]>extent[1]?-1:1;varpos=[nameLocation==='start'?extent[0]-gapSignal*gap:nameLocation==='end'?extent[1]+gapSignal*gap:(extent[0]+extent[1])/2,// 'middle'// Reuse labelOffset.isNameLocationCenter(nameLocation)?opt.labelOffset+nameDirection*gap:0];varlabelLayout;varnameRotation=axisModel.get('nameRotate');if(nameRotation!=null){nameRotation=nameRotation*PI$2/180;// To radian.}varaxisNameAvailableWidth;if(isNameLocationCenter(nameLocation)){labelLayout=innerTextLayout(opt.rotation,nameRotation!=null?nameRotation:opt.rotation,// Adapt to axis.nameDirection);}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);}}vartextFont=textStyleModel.getFont();vartruncateOpt=axisModel.get('nameTruncate',true)||{};varellipsis=truncateOpt.ellipsis;varmaxWidth=retrieve(opt.nameTruncateMaxWidth,truncateOpt.maxWidth,axisNameAvailableWidth);// FIXME// truncate rich text? (consider performance)vartruncatedText=(ellipsis!=null&&maxWidth!=null)?truncateText$1(name,maxWidth,textFont,ellipsis,{minChar:2,placeholder:truncateOpt.placeholder}):name;vartooltipOpt=axisModel.get('tooltip',true);varmainType=axisModel.mainType;varformatterParams={componentType:mainType,name:name,$vars:['name']};formatterParams[mainType+'Index']=axisModel.componentIndex;vartextEl=newText({// Id for animationanid:'name',__fullText:name,__truncatedText:truncatedText,position:pos,rotation:labelLayout.rotation,silent:isSilent(axisModel),z2:1,tooltip:(tooltipOpt&&tooltipOpt.show)?extend({content:name,formatter:function(){returnname;},formatterParams:formatterParams},tooltipOpt):null});setTextStyle(textEl.style,textStyleModel,{text:truncatedText,textFont:textFont,textFill:textStyleModel.getTextColor()||axisModel.get('axisLine.lineStyle.color'),textAlign:labelLayout.textAlign,textVerticalAlign:labelLayout.textVerticalAlign});if(axisModel.get('triggerEvent')){textEl.eventData=makeAxisEventDataBase(axisModel);textEl.eventData.targetType='axisName';textEl.eventData.name=name;}// FIXMEthis._dumbGroup.add(textEl);textEl.updateTransform();this.group.add(textEl);textEl.decomposeTransform();}};/** * @public * @static * @param {Object} opt * @param {number} axisRotation in radian * @param {number} textRotation in radian * @param {number} direction * @return {Object} { * rotation, //accordingtoaxis*textAlign,*textVerticalAlign*}*/var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { var rotationDiff = remRadian(textRotation - axisRotation); var textAlign; var textVerticalAlign; if (isRadianAroundZero(rotationDiff)) { //Labelisparallelwithaxisline.textVerticalAlign=direction>0?'top':'bottom';textAlign='center';}elseif(isRadianAroundZero(rotationDiff-PI$2)){// Label is inverse parallel with axis line.textVerticalAlign=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};};functionendTextLayout(opt,textPosition,textRotate,extent){varrotationDiff=remRadian(textRotate-opt.rotation);vartextAlign;vartextVerticalAlign;varinverse=extent[0]>extent[1];varonLeft=(textPosition==='start'&&!inverse)||(textPosition!=='start'&&inverse);if(isRadianAroundZero(rotationDiff-PI$2/2)){textVerticalAlign=onLeft?'bottom':'top';textAlign='center';}elseif(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};}functionisSilent(axisModel){vartooltipOpt=axisModel.get('tooltip');returnaxisModel.get('silent')// Consider mouse cursor, add these restrictions.||!(axisModel.get('triggerEvent')||(tooltipOpt&&tooltipOpt.show));}functionfixMinMaxLabelShow(axisModel,labelEls,tickEls){// If min or max are user set, we need to check// If the tick on min(max) are overlap on their neighbour tick// If they are overlapped, we need to hide the min(max) tick labelvarshowMinLabel=axisModel.get('axisLabel.showMinLabel');varshowMaxLabel=axisModel.get('axisLabel.showMaxLabel');// FIXME// Have not consider onBand yet, where tick els is more than label els.labelEls=labelEls||[];tickEls=tickEls||[];varfirstLabel=labelEls[0];varnextLabel=labelEls[1];varlastLabel=labelEls[labelEls.length-1];varprevLabel=labelEls[labelEls.length-2];varfirstTick=tickEls[0];varnextTick=tickEls[1];varlastTick=tickEls[tickEls.length-1];varprevTick=tickEls[tickEls.length-2];if(showMinLabel===false){ignoreEl(firstLabel);ignoreEl(firstTick);}elseif(isTwoLabelOverlapped(firstLabel,nextLabel)){if(showMinLabel){ignoreEl(nextLabel);ignoreEl(nextTick);}else{ignoreEl(firstLabel);ignoreEl(firstTick);}}if(showMaxLabel===false){ignoreEl(lastLabel);ignoreEl(lastTick);}elseif(isTwoLabelOverlapped(prevLabel,lastLabel)){if(showMaxLabel){ignoreEl(prevLabel);ignoreEl(prevTick);}else{ignoreEl(lastLabel);ignoreEl(lastTick);}}}functionignoreEl(el){el&&(el.ignore=true);}functionisTwoLabelOverlapped(current,next,labelLayout){// current and next has the same rotation.varfirstRect=current&¤t.getBoundingRect().clone();varnextRect=next&&next.getBoundingRect().clone();if(!firstRect||!nextRect){return;}// When checking intersect of two rotated labels, we use mRotationBack// to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.varmRotationBack=identity([]);rotate(mRotationBack,mRotationBack,-current.rotation);firstRect.applyTransform(mul$1([],mRotationBack,current.getLocalTransform()));nextRect.applyTransform(mul$1([],mRotationBack,next.getLocalTransform()));returnfirstRect.intersect(nextRect);}functionisNameLocationCenter(nameLocation){returnnameLocation==='middle'||nameLocation==='center';}functionbuildAxisTick(axisBuilder,axisModel,opt){varaxis=axisModel.axis;if(!axisModel.get('axisTick.show')||axis.scale.isBlank()){return;}vartickModel=axisModel.getModel('axisTick');varlineStyleModel=tickModel.getModel('lineStyle');vartickLen=tickModel.get('length');varticksCoords=axis.getTicksCoords();varpt1=[];varpt2=[];varmatrix=axisBuilder._transform;vartickEls=[];for(vari=0;i<ticksCoords.length;i++){vartickCoord=ticksCoords[i].coord;pt1[0]=tickCoord;pt1[1]=0;pt2[0]=tickCoord;pt2[1]=opt.tickDirection*tickLen;if(matrix){applyTransform(pt1,pt1,matrix);applyTransform(pt2,pt2,matrix);}// Tick line, Not use group transform to have better line drawvartickEl=newLine(subPixelOptimizeLine({// Id for animationanid:'tick_'+ticksCoords[i].tickValue,shape:{x1:pt1[0],y1:pt1[1],x2:pt2[0],y2:pt2[1]},style:defaults(lineStyleModel.getLineStyle(),{stroke:axisModel.get('axisLine.lineStyle.color')}),z2:2,silent:true}));axisBuilder.group.add(tickEl);tickEls.push(tickEl);}returntickEls;}functionbuildAxisLabel(axisBuilder,axisModel,opt){varaxis=axisModel.axis;varshow=retrieve(opt.axisLabelShow,axisModel.get('axisLabel.show'));if(!show||axis.scale.isBlank()){return;}varlabelModel=axisModel.getModel('axisLabel');varlabelMargin=labelModel.get('margin');varlabels=axis.getViewLabels();// Special label rotate.varlabelRotation=(retrieve(opt.labelRotate,labelModel.get('rotate'))||0)*PI$2/180;varlabelLayout=innerTextLayout(opt.rotation,labelRotation,opt.labelDirection);varrawCategoryData=axisModel.getCategories(true);varlabelEls=[];varsilent=isSilent(axisModel);vartriggerEvent=axisModel.get('triggerEvent');each$1(labels,function(labelItem,index){vartickValue=labelItem.tickValue;varformattedLabel=labelItem.formattedLabel;varrawLabel=labelItem.rawLabel;varitemLabelModel=labelModel;if(rawCategoryData&&rawCategoryData[tickValue]&&rawCategoryData[tickValue].textStyle){itemLabelModel=newModel(rawCategoryData[tickValue].textStyle,labelModel,axisModel.ecModel);}vartextColor=itemLabelModel.getTextColor()||axisModel.get('axisLine.lineStyle.color');vartickCoord=axis.dataToCoord(tickValue);varpos=[tickCoord,opt.labelOffset+opt.labelDirection*labelMargin];vartextEl=newText({// Id for animationanid:'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:typeoftextColor==='function'?textColor(// (1) In category axis with data zoom, tick is not the original// index of axis.data. So tick should not be exposed to user// in category axis.// (2) Compatible with previous version, which always use formatted label as// input. But in interval scale the formatted label is like '223,445', which// maked user repalce ','. So we modify it to return original val but remain// it as 'string' to avoid error in replacing.axis.type==='category'?rawLabel:axis.type==='value'?tickValue+'':tickValue,index):textColor});// Pack data for mouse eventif(triggerEvent){textEl.eventData=makeAxisEventDataBase(axisModel);textEl.eventData.targetType='axisLabel';textEl.eventData.value=rawLabel;}// FIXMEaxisBuilder._dumbGroup.add(textEl);textEl.updateTransform();labelEls.push(textEl);axisBuilder.group.add(textEl);textEl.decomposeTransform();});returnlabelEls;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///BuildaxisPointerModel,mergintooltip.axisPointermodelforeachaxis.// allAxesInfo should be updated when setOption performed.functionfixValue(axisModel){varaxisInfo=getAxisInfo(axisModel);if(!axisInfo){return;}varaxisPointerModel=axisInfo.axisPointerModel;varscale=axisInfo.axis.scale;varoption=axisPointerModel.option;varstatus=axisPointerModel.get('status');varvalue=axisPointerModel.get('value');// Parse init value for category and time axis.if(value!=null){value=scale.parse(value);}varuseHandle=isHandleTrigger(axisPointerModel);// If `handle` used, `axisPointer` will always be displayed, so value// and status should be initialized.if(status==null){option.status=useHandle?'show':'hide';}varextent=scale.getExtent().slice();extent[0]>extent[1]&&extent.reverse();if(// Pick a value on axis when initializing.value==null// If both `handle` and `dataZoom` are used, value may be out of axis extent,// where we should re-pick a value to keep `handle` displaying normally.||value>extent[1]){// Make handle displayed on the end of the axis when init, which looks better.value=extent[1];}if(value<extent[0]){value=extent[0];}option.value=value;if(useHandle){option.status=axisInfo.axis.scale.isBlank()?'hide':'show';}}functiongetAxisInfo(axisModel){varcoordSysAxesInfo=(axisModel.ecModel.getComponent('axisPointer')||{}).coordSysAxesInfo;returncoordSysAxesInfo&&coordSysAxesInfo.axesInfo[makeKey(axisModel)];}functiongetAxisPointerModel(axisModel){varaxisInfo=getAxisInfo(axisModel);returnaxisInfo&&axisInfo.axisPointerModel;}functionisHandleTrigger(axisPointerModel){return!!axisPointerModel.get('handle.show');}/** * @param {module:echarts/model/Model}model*@return{string}uniquekey*/function makeKey(model) { return model.type + '||' + model.id;}/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***BaseclassofAxisView.*/var AxisView = extendComponentView({ type: 'axis', /***@private*/ _axisPointer: null, /***@protected*@type{string}*/ axisPointerClass: null, /***@override*/ render: function (axisModel, ecModel, api, payload) { //FIXME// This process should proformed after coordinate systems updated// (axis scale updated), and should be performed each time update.// So put it here temporarily, although it is not appropriate to// put a model-writing procedure in `view`.this.axisPointerClass&&fixValue(axisModel);AxisView.superApply(this,'render',arguments);updateAxisPointer(this,axisModel,ecModel,api,payload,true);},/** * Action handler. * @public * @param {module:echarts/coord/cartesian/AxisModel}axisModel*@param{module:echarts/model/Global}ecModel*@param{module:echarts/ExtensionAPI}api*@param{Object}payload*/ updateAxisPointer: function (axisModel, ecModel, api, payload, force) { updateAxisPointer(this, axisModel, ecModel, api, payload, false); }, /***@override*/ remove: function (ecModel, api) { var axisPointer = this._axisPointer; axisPointer && axisPointer.remove(api); AxisView.superApply(this, 'remove', arguments); }, /***@override*/ dispose: function (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];};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Canonlybecalledaftercoordinatesystemcreationstage.*(Canbecalledbeforecoordinatesystemupdatestage).**@param{Object}opt{labelInside}*@return{Object}{*position,rotation,labelDirection,labelOffset,*tickDirection,labelRotate,z2*}*/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]); } //Axispositionlayout.position=[axisDim==='y'?posBound[idx[axisPosition]]:rectBound[0],axisDim==='x'?posBound[idx[axisPosition]]:rectBound[3]];// Axis rotationlayout.rotation=Math.PI/2*(axisDim==='x'?0:1);// Tick and label direction, x y is axisDimvardirMap={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 rotationvarlabelRotate=axisModel.get('axisLabel.rotate');layout.labelRotate=axisPosition==='top'?-labelRotate:labelRotate;// Over splitLine and splitArealayout.z2=1;returnlayout;}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var axisBuilderAttrs = [ 'axisLine', 'axisTickLabel', 'axisName'];var selfBuilderAttrs = [ 'splitArea', 'splitLine'];//functiongetAlignWithLabel(model,axisModel){// var alignWithLabel = model.get('alignWithLabel');// if (alignWithLabel === 'auto') {// alignWithLabel = axisModel.get('axisTick.alignWithLabel');// }// return alignWithLabel;// }varCartesianAxisView=AxisView.extend({type:'cartesianAxis',axisPointerClass:'CartesianAxisPointer',/** * @override */render:function(axisModel,ecModel,api,payload){this.group.removeAll();varoldAxisGroup=this._axisGroup;this._axisGroup=newGroup();this.group.add(this._axisGroup);if(!axisModel.get('show')){return;}vargridModel=axisModel.getCoordSysModel();varlayout=layout$1(gridModel,axisModel);varaxisBuilder=newAxisBuilder(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(){this._splitAreaColors=null;},/** * @param {module:echarts/coord/cartesian/AxisModel}axisModel*@param{module:echarts/coord/cartesian/GridModel}gridModel*@private*/ _splitLine: function (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 = []; //Simpleoptimization// Batching the lines if color are the samevarlineStyle=lineStyleModel.getLineStyle();for(vari=0;i<ticksCoords.length;i++){vartickCoord=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;}varcolorIndex=(lineCount++)%lineColors.length;vartickValue=ticksCoords[i].tickValue;this._axisGroup.add(newLine(subPixelOptimizeLine({anid:tickValue!=null?'line_'+ticksCoords[i].tickValue:null,shape:{x1:p1[0],y1:p1[1],x2:p2[0],y2:p2[1]},style:defaults({stroke:lineColors[colorIndex]},lineStyle),silent:true})));}},/** * @param {module:echarts/coord/cartesian/AxisModel}axisModel*@param{module:echarts/coord/cartesian/GridModel}gridModel*@private*/ _splitArea: function (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; } //ForMakingappropriatesplitAreaanimation,thecolorandanid// should be corresponding to previous one if possible.varareaColorsLen=areaColors.length;varlastSplitAreaColors=this._splitAreaColors;varnewSplitAreaColors=createHashMap();varcolorIndex=0;if(lastSplitAreaColors){for(vari=0;i<ticksCoords.length;i++){varcIndex=lastSplitAreaColors.get(ticksCoords[i].tickValue);if(cIndex!=null){colorIndex=(cIndex+(areaColorsLen-1)*i)%areaColorsLen;break;}}}varprev=axis.toGlobalCoord(ticksCoords[0].coord);varareaStyle=areaStyleModel.getAreaStyle();areaColors=isArray(areaColors)?areaColors:[areaColors];for(vari=1;i<ticksCoords.length;i++){vartickCoord=axis.toGlobalCoord(ticksCoords[i].coord);varx;vary;varwidth;varheight;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;}vartickValue=ticksCoords[i-1].tickValue;tickValue!=null&&newSplitAreaColors.set(tickValue,colorIndex);this._axisGroup.add(newRect({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;}this._splitAreaColors=newSplitAreaColors;}});CartesianAxisView.extend({type:'xAxis'});CartesianAxisView.extend({type:'yAxis'});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///GridviewextendComponentView({type:'grid',render:function(gridModel,ecModel){this.group.removeAll();if(gridModel.get('show')){this.group.add(newRect({shape:gridModel.coordinateSystem.getRect(),style:defaults({fill:gridModel.get('backgroundColor')},gridModel.getItemStyle()),silent:true,z2:-1}));}}});registerPreprocessor(function(option){// Only create grid when needif(option.xAxis&&option.yAxis&&!option.grid){option.grid={};}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///IncasedeveloperforgettoincludegridcomponentregisterVisual(visualSymbol('line','circle','line'));registerLayout(layoutPoints('line'));// Down sample after filterregisterProcessor(PRIORITY.PROCESSOR.STATISTIC,dataSample('line'));/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var BaseBarSeries = SeriesModel.extend({ type: 'series.__base_bar__', getInitialData: function (option, ecModel) { return createListFromArray(this.getSource(), this); }, getMarkerPosition: function (value) { var coordSys = this.coordinateSystem; if (coordSys) { //PENDINGifclamp?varpt=coordSys.dataToPoint(coordSys.clampData(value));vardata=this.getData();varoffset=data.getLayout('offset');varsize=data.getLayout('size');varoffsetIndex=coordSys.getBaseAxis().isHorizontal()?0:1;pt[offsetIndex]+=offset+size/2;returnpt;}return[NaN,NaN];},defaultOption:{zlevel:0,// 一级层叠z:2,// 二级层叠coordinateSystem:'cartesian2d',legendHoverLink:true,// stack: null// Cartesian coordinate system// xAxisIndex: 0,// yAxisIndex: 0,// 最小高度改为0barMinHeight:0,// 最小角度为0,仅对极坐标系下的柱状图有效barMinAngle:0,// cursor: null,large:false,largeThreshold:400,progressive:3e3,progressiveChunkMode:'mod',// barMaxWidth: null,// 默认自适应// barWidth: null,// 柱间距离,默认为柱形宽度的30%,可设固定值// barGap: '30%',// 类目间柱形距离,默认为类目间距的20%,可设固定值// barCategoryGap: '20%',// label: {// show: false// },itemStyle:{},emphasis:{}}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/BaseBarSeries.extend({ type: 'series.bar', dependencies: ['grid', 'polar'], brushSelector: 'rect', /***@override*/ getProgressive: function () { //Donotsupportprogressiveinnormalmode.returnthis.get('large')?this.get('progressive'):false;},/** * @override */getProgressiveThreshold:function(){// Do not support progressive in normal mode.varprogressiveThreshold=this.get('progressiveThreshold');varlargeThreshold=this.get('largeThreshold');if(largeThreshold>progressiveThreshold){progressiveThreshold=largeThreshold;}returnprogressiveThreshold;}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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; }}/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var getBarItemStyle = makeStyleMapper([ ['fill', 'color'],['stroke', 'borderColor'],['lineWidth', 'borderWidth'], //Compatitablewith2['stroke','barBorderColor'],['lineWidth','barBorderWidth'],['opacity'],['shadowBlur'],['shadowOffsetX'],['shadowOffsetY'],['shadowColor']]);varbarItemStyle={getBarItemStyle:function(excludes){varstyle=getBarItemStyle(this,excludes);if(this.getBorderLineDash){varlineDash=this.getBorderLineDash();lineDash&&(style.lineDash=lineDash);}returnstyle;}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];//FIXME// Just for compatible with ec2.extend(Model.prototype,barItemStyle);extendChartView({type:'bar',render:function(seriesModel,ecModel,api){this._updateDrawMode(seriesModel);varcoordinateSystemType=seriesModel.get('coordinateSystem');if(coordinateSystemType==='cartesian2d'||coordinateSystemType==='polar'){this._isLargeDraw?this._renderLarge(seriesModel,ecModel,api):this._renderNormal(seriesModel,ecModel,api);}elseif(__DEV__){console.warn('Only cartesian2d and polar supported for bar.');}returnthis.group;},incrementalPrepareRender:function(seriesModel,ecModel,api){this._clear();this._updateDrawMode(seriesModel);},incrementalRender:function(params,seriesModel,ecModel,api){// Do not support progressive in normal mode.this._incrementalRenderLarge(params,seriesModel);},_updateDrawMode:function(seriesModel){varisLargeDraw=seriesModel.pipelineContext.large;if(this._isLargeDraw==null||isLargeDraw^this._isLargeDraw){this._isLargeDraw=isLargeDraw;this._clear();}},_renderNormal:function(seriesModel,ecModel,api){vargroup=this.group;vardata=seriesModel.getData();varoldData=this._data;varcoord=seriesModel.coordinateSystem;varbaseAxis=coord.getBaseAxis();varisHorizontalOrRadial;if(coord.type==='cartesian2d'){isHorizontalOrRadial=baseAxis.isHorizontal();}elseif(coord.type==='polar'){isHorizontalOrRadial=baseAxis.dim==='angle';}varanimationModel=seriesModel.isAnimationEnabled()?seriesModel:null;data.diff(oldData).add(function(dataIndex){if(!data.hasValue(dataIndex)){return;}varitemModel=data.getItemModel(dataIndex);varlayout=getLayout[coord.type](data,dataIndex,itemModel);varel=elementCreator[coord.type](data,dataIndex,itemModel,layout,isHorizontalOrRadial,animationModel);data.setItemGraphicEl(dataIndex,el);group.add(el);updateStyle(el,data,dataIndex,itemModel,layout,seriesModel,isHorizontalOrRadial,coord.type==='polar');}).update(function(newIndex,oldIndex){varel=oldData.getItemGraphicEl(oldIndex);if(!data.hasValue(newIndex)){group.remove(el);return;}varitemModel=data.getItemModel(newIndex);varlayout=getLayout[coord.type](data,newIndex,itemModel);if(el){updateProps(el,{shape:layout},animationModel,newIndex);}else{el=elementCreator[coord.type](data,newIndex,itemModel,layout,isHorizontalOrRadial,animationModel,true);}data.setItemGraphicEl(newIndex,el);// Add backgroup.add(el);updateStyle(el,data,newIndex,itemModel,layout,seriesModel,isHorizontalOrRadial,coord.type==='polar');}).remove(function(dataIndex){varel=oldData.getItemGraphicEl(dataIndex);if(coord.type==='cartesian2d'){el&&removeRect(dataIndex,animationModel,el);}else{el&&removeSector(dataIndex,animationModel,el);}}).execute();this._data=data;},_renderLarge:function(seriesModel,ecModel,api){this._clear();createLarge(seriesModel,this.group);},_incrementalRenderLarge:function(params,seriesModel){createLarge(seriesModel,this.group,true);},dispose:noop,remove:function(ecModel){this._clear(ecModel);},_clear:function(ecModel){vargroup=this.group;vardata=this._data;if(ecModel&&ecModel.get('animation')&&data&&!this._isLargeDraw){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;}});varelementCreator={cartesian2d:function(data,dataIndex,itemModel,layout,isHorizontal,animationModel,isUpdate){varrect=newRect({shape:extend({},layout)});// Animationif(animationModel){varrectShape=rect.shape;varanimateProperty=isHorizontal?'height':'width';varanimateTarget={};rectShape[animateProperty]=0;animateTarget[animateProperty]=layout[animateProperty];graphic[isUpdate?'updateProps':'initProps'](rect,{shape:animateTarget},animationModel,dataIndex);}returnrect;},polar:function(data,dataIndex,itemModel,layout,isRadial,animationModel,isUpdate){// Keep the same logic with bar in catesion: use end value to control// direction. Notice that if clockwise is true (by default), the sector// will always draw clockwisely, no matter whether endAngle is greater// or less than startAngle.varclockwise=layout.startAngle<layout.endAngle;varsector=newSector({shape:defaults({clockwise:clockwise},layout)});// Animationif(animationModel){varsectorShape=sector.shape;varanimateProperty=isRadial?'r':'endAngle';varanimateTarget={};sectorShape[animateProperty]=isRadial?0:layout.startAngle;animateTarget[animateProperty]=layout[animateProperty];graphic[isUpdate?'updateProps':'initProps'](sector,{shape:animateTarget},animationModel,dataIndex);}returnsector;}};functionremoveRect(dataIndex,animationModel,el){// Not show text when animatingel.style.text=null;updateProps(el,{shape:{width:0}},animationModel,dataIndex,function(){el.parent&&el.parent.remove(el);});}functionremoveSector(dataIndex,animationModel,el){// Not show text when animatingel.style.text=null;updateProps(el,{shape:{r:el.shape.r0}},animationModel,dataIndex,function(){el.parent&&el.parent.remove(el);});}vargetLayout={cartesian2d:function(data,dataIndex,itemModel){varlayout=data.getItemLayout(dataIndex);varfixedLineWidth=getLineWidth(itemModel,layout);// fix layout with lineWidthvarsignX=layout.width>0?1:-1;varsignY=layout.height>0?1:-1;return{x:layout.x+signX*fixedLineWidth/2,y:layout.y+signY*fixedLineWidth/2,width:layout.width-signX*fixedLineWidth,height:layout.height-signY*fixedLineWidth};},polar:function(data,dataIndex,itemModel){varlayout=data.getItemLayout(dataIndex);return{cx:layout.cx,cy:layout.cy,r0:layout.r0,r:layout.r,startAngle:layout.startAngle,endAngle:layout.endAngle};}};functionupdateStyle(el,data,dataIndex,itemModel,layout,seriesModel,isHorizontal,isPolar){varcolor=data.getItemVisual(dataIndex,'color');varopacity=data.getItemVisual(dataIndex,'opacity');varitemStyleModel=itemModel.getModel('itemStyle');varhoverStyle=itemModel.getModel('emphasis.itemStyle').getBarItemStyle();if(!isPolar){el.setShape('r',itemStyleModel.get('barBorderRadius')||0);}el.useStyle(defaults({fill:color,opacity:opacity},itemStyleModel.getBarItemStyle()));varcursorStyle=itemModel.getShallow('cursor');cursorStyle&&el.attr('cursor',cursorStyle);varlabelPositionOutside=isHorizontal?(layout.height>0?'bottom':'top'):(layout.width>0?'left':'right');if(!isPolar){setLabel(el.style,hoverStyle,itemModel,color,seriesModel,dataIndex,labelPositionOutside);}setHoverStyle(el,hoverStyle);}// In case width or height are too small.functiongetLineWidth(itemModel,rawLayout){varlineWidth=itemModel.get(BAR_BORDER_WIDTH_QUERY)||0;returnMath.min(lineWidth,Math.abs(rawLayout.width),Math.abs(rawLayout.height));}varLargePath=Path.extend({type:'largeBar',shape:{points:[]},buildPath:function(ctx,shape){// Drawing lines is more efficient than drawing// a whole line or drawing rects.varpoints=shape.points;varstartPoint=this.__startPoint;varvalueIdx=this.__valueIdx;for(vari=0;i<points.length;i+=2){startPoint[this.__valueIdx]=points[i+valueIdx];ctx.moveTo(startPoint[0],startPoint[1]);ctx.lineTo(points[i],points[i+1]);}}});functioncreateLarge(seriesModel,group,incremental){// TODO support polarvardata=seriesModel.getData();varstartPoint=[];varvalueIdx=data.getLayout('valueAxisHorizontal')?1:0;startPoint[1-valueIdx]=data.getLayout('valueAxisStart');varel=newLargePath({shape:{points:data.getLayout('largePoints')},incremental:!!incremental,__startPoint:startPoint,__valueIdx:valueIdx});group.add(el);setLargeStyle(el,seriesModel,data);}functionsetLargeStyle(el,seriesModel,data){varborderColor=data.getVisual('borderColor')||data.getVisual('color');varitemStyle=seriesModel.getModel('itemStyle').getItemStyle(['color','borderColor']);el.useStyle(itemStyle);el.style.fill=null;el.style.stroke=borderColor;el.style.lineWidth=data.getLayout('barWidth');}/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///IncasedeveloperforgettoincludegridcomponentregisterLayout(curry(layout,'bar'));// Should after normal bar layout, otherwise it is blocked by normal bar layout.registerLayout(largeLayout);registerVisual({seriesType:'bar',reset:function(seriesModel){// Visual coding for legendseriesModel.getData().setVisual('legendSymbol','roundRect');}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***[Usage]:*(1)*createListSimply(seriesModel,['value']);*(2)*createListSimply(seriesModel,{*coordDimensions:['value'],*dimensionsCount:5*});**@param{module:echarts/model/Series}seriesModel*@param{Object|Array.<string|Object>}optoptorcoordDimensions*Theoptionsinopt,see`echarts/data/helper/createDimensions`*@param{Array.<string>}[nameList]*@return{module:echarts/data/List}*/var createListSimply = function (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;};/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***Dataselectablemixinforchartseries.*Toeanbledataselect,optionofseriesmusthave`selectedMode`.*Andeachdataitemwilluse`selected`totoggleitselfselectedstatus*/var dataSelectableMixin = { /***@param{Array.<Object>}targetList[{name,value,selected},...]*IftargetListisanarray,itshouldlike[{name:...,value:...},...].*IftargetListisa"List",itmusthavecoordDim:'value'dimensionandname.*/ updateSelectedMap: function (targetList) { this._targetList = isArray(targetList)? targetList.slice() : []; this._selectTargetMap = reduce(targetList || [], function (targetMap, target) { targetMap.set(target.name, target); return targetMap; }, createHashMap()); }, /***Eithernameoridshouldbepassedasinputhere.*Ifbothofthemaredefined,idisused.**@param{string|undefined}namenameofdata*@param{number|undefined}iddataIndexofdata*/ //PENGINGIfselectedModeisnull?select:function(name,id){vartarget=id!=null?this._targetList[id]:this._selectTargetMap.get(name);varselectedMode=this.get('selectedMode');if(selectedMode==='single'){this._selectTargetMap.each(function(target){target.selected=false;});}target&&(target.selected=true);},/** * Either name or id should be passed as input here. * If both of them are defined, id is used. * * @param {string|undefined} name name of data * @param {number|undefined} id dataIndex of data */unSelect:function(name,id){vartarget=id!=null?this._targetList[id]:this._selectTargetMap.get(name);// var selectedMode = this.get('selectedMode');// selectedMode !== 'single' && target && (target.selected = false);target&&(target.selected=false);},/** * Either name or id should be passed as input here. * If both of them are defined, id is used. * * @param {string|undefined} name name of data * @param {number|undefined} id dataIndex of data */toggleSelected:function(name,id){vartarget=id!=null?this._targetList[id]:this._selectTargetMap.get(name);if(target!=null){this[target.selected?'unSelect':'select'](name,id);returntarget.selected;}},/** * Either name or id should be passed as input here. * If both of them are defined, id is used. * * @param {string|undefined} name name of data * @param {number|undefined} id dataIndex of data */isSelected:function(name,id){vartarget=id!=null?this._targetList[id]:this._selectTargetMap.get(name);returntarget&&target.selected;}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var PieSeries = extendSeriesModel({ type: 'series.pie', //Overwriteinit:function(option){PieSeries.superApply(this,'init',arguments);// Enable legend selection for each data item// Use a function instead of direct access because data reference may changedthis.legendDataProvider=function(){returnthis.getRawData();};this.updateSelectedMap(this._createSelectableList());this._defaultLabelLine(option);},// OverwritemergeOption:function(newOption){PieSeries.superCall(this,'mergeOption',newOption);this.updateSelectedMap(this._createSelectableList());},getInitialData:function(option,ecModel){returncreateListSimply(this,['value']);},_createSelectableList:function(){vardata=this.getRawData();varvalueDim=data.mapDimension('value');vartargetList=[];for(vari=0,len=data.count();i<len;i++){targetList.push({name:data.getName(i),value:data.get(valueDim,i),selected:retrieveRawAttr(data,i,'selected')});}returntargetList;},// OverwritegetDataParams:function(dataIndex){vardata=this.getData();varparams=PieSeries.superCall(this,'getDataParams',dataIndex);// FIXME toFixed?varvalueList=[];data.each(data.mapDimension('value'),function(value){valueList.push(value);});params.percent=getPercentWithPrecision(valueList,dataIndex,data.hostModel.get('percentPrecision'));params.$vars.push('percent');returnparams;},_defaultLabelLine:function(option){// Extend labelLine emphasisdefaultEmphasis(option,'labelLine',['show']);varlabelLineNormalOpt=option.labelLine;varlabelLineEmphasisOpt=option.emphasis.labelLine;// Not show label line if `label.normal.show = false`labelLineNormalOpt.show=labelLineNormalOpt.show&&option.label.show;labelLineEmphasisOpt.show=labelLineEmphasisOpt.show&&option.emphasis.label.show;},defaultOption:{zlevel:0,z:2,legendHoverLink:true,hoverAnimation:true,// 默认全局居中center:['50%','50%'],radius:[0,'75%'],// 默认顺时针clockwise:true,startAngle:90,// 最小角度改为0minAngle:0,// 选中时扇区偏移量selectedOffset:10,// 高亮扇区偏移量hoverOffset:10,// If use strategy to avoid label overlappingavoidLabelOverlap:true,// 选择模式,默认关闭,可选single,multiple// selectedMode: false,// 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积)// roseType: null,percentPrecision:2,// If still show when all data zero.stillShowZeroSum:true,// cursor: null,label:{// If rotate around circlerotate:false,show:true,// 'outer', 'inside', 'center'position:'outer'// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调// 默认使用全局文本样式,详见TEXTSTYLE// distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数},// Enabled when label.normal.position is 'outer'labelLine:{show:true,// 引导线两段中的第一段长度length:15,// 引导线两段中的第二段长度length2:15,smooth:false,lineStyle:{// color: 各异,width:1,type:'solid'}},itemStyle:{borderWidth:1},// Animation type canbe expansion, scaleanimationType:'expansion',animationEasing:'cubicOut'}});mixin(PieSeries,dataSelectableMixin);/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*//***@param{module:echarts/model/Series}seriesModel*@param{boolean}hasAnimation*@inner*/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); });}/***@param{module:zrender/graphic/Sector}el*@param{Object}layout*@param{boolean}isSelected*@param{number}selectedOffset*@param{boolean}hasAnimation*@inner*/function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) { var midAngle = (layout.startAngle + layout.endAngle) /2;vardx=Math.cos(midAngle);vardy=Math.sin(midAngle);varoffset=isSelected?selectedOffset:0;varposition=[dx*offset,dy*offset];hasAnimation// animateTo will stop revious animation like update transition?el.animate().when(200,{position:position}).start('bounceOut'):el.attr('position',position);}/** * Piece of pie including Sector, Label, LabelLine * @constructor * @extends {module:zrender/graphic/Group}*/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); //HovertochangelabelandlabelLinefunctiononEmphasis(){polyline.ignore=polyline.hoverIgnore;text.ignore=text.hoverIgnore;}functiononNormal(){polyline.ignore=polyline.normalIgnore;text.ignore=text.normalIgnore;}this.on('emphasis',onEmphasis).on('normal',onNormal).on('mouseover',onEmphasis).on('mouseout',onNormal);}varpiePieceProto=PiePiece.prototype;piePieceProto.updateData=function(data,idx,firstCreate){varsector=this.childAt(0);varseriesModel=data.hostModel;varitemModel=data.getItemModel(idx);varlayout=data.getItemLayout(idx);varsectorShape=extend({},layout);sectorShape.label=null;if(firstCreate){sector.setShape(sectorShape);varanimationType=seriesModel.getShallow('animationType');if(animationType==='scale'){sector.shape.r=layout.r0;initProps(sector,{shape:{r:layout.r}},seriesModel,idx);}// Expansionelse{sector.shape.endAngle=layout.startAngle;updateProps(sector,{shape:{endAngle:layout.endAngle}},seriesModel,idx);}}else{updateProps(sector,{shape:sectorShape},seriesModel,idx);}// Update common stylevarvisualColor=data.getItemVisual(idx,'color');sector.useStyle(defaults({lineJoin:'bevel',fill:visualColor},itemModel.getModel('itemStyle').getItemStyle()));sector.hoverStyle=itemModel.getModel('emphasis.itemStyle').getItemStyle();varcursorStyle=itemModel.getShallow('cursor');cursorStyle&§or.attr('cursor',cursorStyle);// Toggle selectedtoggleItemSelected(this,data.getItemLayout(idx),seriesModel.isSelected(null,idx),seriesModel.get('selectedOffset'),seriesModel.get('animation'));functiononEmphasis(){// Sector may has animation of updating data. Force to move to the last frame// Or it may stopped on the wrong shapesector.stopAnimation(true);sector.animateTo({shape:{r:layout.r+seriesModel.get('hoverOffset')}},300,'elasticOut');}functiononNormal(){sector.stopAnimation(true);sector.animateTo({shape:{r:layout.r}},300,'elasticOut');}sector.off('mouseover').off('mouseout').off('emphasis').off('normal');if(itemModel.get('hoverAnimation')&&seriesModel.isAnimationEnabled()){sector.on('mouseover',onEmphasis).on('mouseout',onNormal).on('emphasis',onEmphasis).on('normal',onNormal);}this._updateLabel(data,idx);setHoverStyle(this);};piePieceProto._updateLabel=function(data,idx){varlabelLine=this.childAt(1);varlabelText=this.childAt(2);varseriesModel=data.hostModel;varitemModel=data.getItemModel(idx);varlayout=data.getItemLayout(idx);varlabelLayout=layout.label;varvisualColor=data.getItemVisual(idx,'color');updateProps(labelLine,{shape:{points:labelLayout.linePoints||[[labelLayout.x,labelLayout.y],[labelLayout.x,labelLayout.y],[labelLayout.x,labelLayout.y]]}},seriesModel,idx);updateProps(labelText,{style:{x:labelLayout.x,y:labelLayout.y}},seriesModel,idx);labelText.attr({rotation:labelLayout.rotation,origin:[labelLayout.x,labelLayout.y],z2:10});varlabelModel=itemModel.getModel('label');varlabelHoverModel=itemModel.getModel('emphasis.label');varlabelLineModel=itemModel.getModel('labelLine');varlabelLineHoverModel=itemModel.getModel('emphasis.labelLine');varvisualColor=data.getItemVisual(idx,'color');setLabelStyle(labelText.style,labelText.hoverStyle={},labelModel,labelHoverModel,{labelFetcher:data.hostModel,labelDataIndex:idx,defaultText:data.getName(idx),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 colorlabelLine.setStyle({stroke:visualColor,opacity:data.getItemVisual(idx,'opacity')});labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());labelLine.hoverStyle=labelLineHoverModel.getModel('lineStyle').getLineStyle();varsmooth=labelLineModel.get('smooth');if(smooth&&smooth===true){smooth=0.4;}labelLine.setShape({smooth:smooth});};inherits(PiePiece,Group);// Pie viewvarPieView=Chart.extend({type:'pie',init:function(){varsectorGroup=newGroup();this._sectorGroup=sectorGroup;},render:function(seriesModel,ecModel,api,payload){if(payload&&(payload.from===this.uid)){return;}vardata=seriesModel.getData();varoldData=this._data;vargroup=this.group;varhasAnimation=ecModel.get('animation');varisFirstRender=!oldData;varanimationType=seriesModel.get('animationType');varonSectorClick=curry(updateDataSelected,this.uid,seriesModel,hasAnimation,api);varselectedMode=seriesModel.get('selectedMode');data.diff(oldData).add(function(idx){varpiePiece=newPiePiece(data,idx);// Default expansion animationif(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){varpiePiece=oldData.getItemGraphicEl(oldIdx);piePiece.updateData(data,newIdx);piePiece.off('click');selectedMode&&piePiece.on('click',onSectorClick);group.add(piePiece);data.setItemGraphicEl(newIdx,piePiece);}).remove(function(idx){varpiePiece=oldData.getItemGraphicEl(idx);group.remove(piePiece);}).execute();if(hasAnimation&&isFirstRender&&data.count()>0// Default expansion animation&&animationType!=='scale'){varshape=data.getItemLayout(0);varr=Math.max(api.getWidth(),api.getHeight())/2;varremoveClipPath=bind(group.removeClipPath,group);group.setClipPath(this._createClipPath(shape.cx,shape.cy,r,shape.startAngle,shape.clockwise,removeClipPath,seriesModel));}else{// clipPath is used in first-time animation, so remove it when otherwise. See: #8994group.removeClipPath();}this._data=data;},dispose:function(){},_createClipPath:function(cx,cy,r,startAngle,clockwise,cb,seriesModel){varclipPath=newSector({shape:{cx:cx,cy:cy,r0:0,r:r,startAngle:startAngle,endAngle:startAngle,clockwise:clockwise}});initProps(clipPath,{shape:{endAngle:startAngle+(clockwise?1:-1)*Math.PI*2}},seriesModel,cb);returnclipPath;},/** * @implement */containPoint:function(point,seriesModel){vardata=seriesModel.getData();varitemLayout=data.getItemLayout(0);if(itemLayout){vardx=point[0]-itemLayout.cx;vardy=point[1]-itemLayout.cy;varradius=Math.sqrt(dx*dx+dy*dy);returnradius<=itemLayout.r&&radius>=itemLayout.r0;}}});/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var createDataSelectAction = function (seriesType, actionInfos) { each$1(actionInfos, function (actionInfo) { actionInfo.update = 'updateView'; /***@payload*@property{string}seriesName*@property{string}name*/ 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(); //Createselectedmapdata.each(function(idx){varname=data.getName(idx);selected[name]=seriesModel.isSelected(name)||false;});});return{name:payload.name,selected:selected};});});};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///Pickcolorfrompaletteforeachdataitem.// Applicable for charts that require applying color palette// in data level (like pie, funnel, chord).vardataColor=function(seriesType){return{getTargetSeries:function(ecModel){// Pie and funnel may use diferrent scopevarpaletteScope={};varseiresModelMap=createHashMap();ecModel.eachSeriesByType(seriesType,function(seriesModel){seriesModel.__paletteScope=paletteScope;seiresModelMap.set(seriesModel.uid,seriesModel);});returnseiresModelMap;},reset:function(seriesModel,ecModel){vardataAll=seriesModel.getRawData();varidxMap={};vardata=seriesModel.getData();data.each(function(idx){varrawIdx=data.getRawIndex(idx);idxMap[rawIdx]=idx;});dataAll.each(function(rawIdx){varfilteredIdx=idxMap[rawIdx];// If series.itemStyle.normal.color is a function. itemVisual may be encodedvarsingleDataColor=filteredIdx!=null&&data.getItemVisual(filteredIdx,'color',true);if(!singleDataColor){// FIXME PerformancevaritemModel=dataAll.getItemModel(rawIdx);varcolor=itemModel.get('itemStyle.color')||seriesModel.getColorFromPalette(dataAll.getName(rawIdx)||(rawIdx+''),seriesModel.__paletteScope,dataAll.count());// Legend may use the visual info in data before processeddataAll.setItemVisual(rawIdx,'color',color);// Data is not filteredif(filteredIdx!=null){data.setItemVisual(filteredIdx,'color',color);}}else{// Set data all color for legenddataAll.setItemVisual(rawIdx,'color',singleDataColor);}});}};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*///FIXMEemphasislabelpositionisnotsamewithnormallabelpositionfunctionadjustSingleSide(list,cx,cy,r,dir,viewWidth,viewHeight){list.sort(function(a,b){returna.y-b.y;});// 压functionshiftDown(start,end,delta,dir){for(varj=start;j<end;j++){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);}// 弹functionshiftUp(end,delta){for(varj=end;j>=0;j--){list[j].y-=delta;if(j>0&&list[j].y>list[j-1].y+list[j-1].height){break;}}}functionchangeX(list,isDownList,cx,cy,r,dir){varlastDeltaX=dir>0?isDownList// 右侧?Number.MAX_VALUE// 下:0// 上:isDownList// 左侧?Number.MAX_VALUE// 下:0;// 上for(vari=0,l=list.length;i<l;i++){// Not change x for center labelif(list[i].position==='center'){continue;}vardeltaY=Math.abs(list[i].y-cy);varlength=list[i].len;varlength2=list[i].len2;vardeltaX=(deltaY<r+length)?Math.sqrt((r+length+length2)*(r+length+length2)-deltaY*deltaY):Math.abs(list[i].x-cx);if(isDownList&&deltaX>=lastDeltaX){// 右下,左下deltaX=lastDeltaX-10;}if(!isDownList&&deltaX<=lastDeltaX){// 右上,左上deltaX=lastDeltaX+10;}list[i].x=cx+deltaX*dir;lastDeltaX=deltaX;}}varlastY=0;vardelta;varlen=list.length;varupList=[];vardownList=[];for(vari=0;i<len;i++){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(vari=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);}functionavoidOverlap(labelLayoutList,cx,cy,r,viewWidth,viewHeight){varleftList=[];varrightList=[];for(vari=0;i<labelLayoutList.length;i++){if(labelLayoutList[i].x<cx){leftList.push(labelLayoutList[i]);}else{rightList.push(labelLayoutList[i]);}}adjustSingleSide(rightList,cx,cy,r,1,viewWidth,viewHeight);adjustSingleSide(leftList,cx,cy,r,-1,viewWidth,viewHeight);for(vari=0;i<labelLayoutList.length;i++){varlinePoints=labelLayoutList[i].linePoints;if(linePoints){vardist=linePoints[1][0]-linePoints[2][0];if(labelLayoutList[i].x<cx){linePoints[2][0]=labelLayoutList[i].x+3;}else{linePoints[2][0]=labelLayoutList[i].x-3;}linePoints[1][1]=linePoints[2][1]=labelLayoutList[i].y;linePoints[1][0]=linePoints[2][0]+dist;}}}varlabelLayout=function(seriesModel,r,viewWidth,viewHeight){vardata=seriesModel.getData();varlabelLayoutList=[];varcx;varcy;varhasLabelRotate=false;data.each(function(idx){varlayout=data.getItemLayout(idx);varitemModel=data.getItemModel(idx);varlabelModel=itemModel.getModel('label');// Use position in normal or emphasisvarlabelPosition=labelModel.get('position')||itemModel.get('emphasis.label.position');varlabelLineModel=itemModel.getModel('labelLine');varlabelLineLen=labelLineModel.get('length');varlabelLineLen2=labelLineModel.get('length2');varmidAngle=(layout.startAngle+layout.endAngle)/2;vardx=Math.cos(midAngle);vardy=Math.sin(midAngle);vartextX;vartextY;varlinePoints;vartextAlign;cx=layout.cx;cy=layout.cy;varisLabelInside=labelPosition==='inside'||labelPosition==='inner';if(labelPosition==='center'){textX=layout.cx;textY=layout.cy;textAlign='center';}else{varx1=(isLabelInside?(layout.r+layout.r0)/2*dx:layout.r*dx)+cx;vary1=(isLabelInside?(layout.r+layout.r0)/2*dy:layout.r*dy)+cy;textX=x1+dx*3;textY=y1+dy*3;if(!isLabelInside){// For roseTypevarx2=x1+dx*(labelLineLen+r-layout.r);vary2=y1+dy*(labelLineLen+r-layout.r);varx3=x2+((dx<0?-1:1)*labelLineLen2);vary3=y2;textX=x3+(dx<0?-5:5);textY=y3;linePoints=[[x1,y1],[x2,y2],[x3,y3]];}textAlign=isLabelInside?'center':(dx>0?'left':'right');}varfont=labelModel.getFont();varlabelRotate=labelModel.get('rotate')?(dx<0?-midAngle+Math.PI:-midAngle):0;vartext=seriesModel.getFormattedLabel(idx,'normal')||data.getName(idx);vartextRect=getBoundingRect(text,font,textAlign,'top');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};// Not layout the inside labelif(!isLabelInside){labelLayoutList.push(layout.label);}});if(!hasLabelRotate&&seriesModel.get('avoidLabelOverlap')){avoidOverlap(labelLayoutList,cx,cy,r,viewWidth,viewHeight);}};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var PI2$4 = Math.PI * 2;var RADIAN = Math.PI /180;varpieLayout=function(seriesType,ecModel,api,payload){ecModel.eachSeriesByType(seriesType,function(seriesModel){vardata=seriesModel.getData();varvalueDim=data.mapDimension('value');varcenter=seriesModel.get('center');varradius=seriesModel.get('radius');if(!isArray(radius)){radius=[0,radius];}if(!isArray(center)){center=[center,center];}varwidth=api.getWidth();varheight=api.getHeight();varsize=Math.min(width,height);varcx=parsePercent$1(center[0],width);varcy=parsePercent$1(center[1],height);varr0=parsePercent$1(radius[0],size/2);varr=parsePercent$1(radius[1],size/2);varstartAngle=-seriesModel.get('startAngle')*RADIAN;varminAngle=seriesModel.get('minAngle')*RADIAN;varvalidDataCount=0;data.each(valueDim,function(value){!isNaN(value)&&validDataCount++;});varsum=data.getSum(valueDim);// Sum may be 0varunitRadian=Math.PI/(sum||validDataCount)*2;varclockwise=seriesModel.get('clockwise');varroseType=seriesModel.get('roseType');varstillShowZeroSum=seriesModel.get('stillShowZeroSum');// [0...max]varextent=data.getDataExtent(valueDim);extent[0]=0;// In the case some sector angle is smaller than minAnglevarrestAngle=PI2$4;varvalueSumLargerThanMinAngle=0;varcurrentAngle=startAngle;vardir=clockwise?1:-1;data.each(valueDim,function(value,idx){varangle;if(isNaN(value)){data.setItemLayout(idx,{angle:NaN,startAngle:NaN,endAngle:NaN,clockwise:clockwise,cx:cx,cy:cy,r0:r0,r:roseType?NaN:r});return;}// FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样?if(roseType!=='area'){angle=(sum===0&&stillShowZeroSum)?unitRadian:(value*unitRadian);}else{angle=PI2$4/validDataCount;}if(angle<minAngle){angle=minAngle;restAngle-=minAngle;}else{valueSumLargerThanMinAngle+=value;}varendAngle=currentAngle+dir*angle;data.setItemLayout(idx,{angle:angle,startAngle:currentAngle,endAngle:endAngle,clockwise:clockwise,cx:cx,cy:cy,r0:r0,r:roseType?linearMap(value,extent,[r0,r]):r});currentAngle=endAngle;});// Some sector is constrained by minAngle// Rest sectors needs recalculate angleif(restAngle<PI2$4&&validDataCount){// Average the angle if rest angle is not enough after all angles is// Constrained by minAngleif(restAngle<=1e-3){varangle=PI2$4/validDataCount;data.each(valueDim,function(value,idx){if(!isNaN(value)){varlayout=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)){varlayout=data.getItemLayout(idx);varangle=layout.angle===minAngle?minAngle:value*unitRadian;layout.startAngle=currentAngle;layout.endAngle=currentAngle+dir*angle;currentAngle+=dir*angle;}});}}labelLayout(seriesModel,r,width,height);});};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/var dataFilter = function (seriesType) { return { seriesType: seriesType, reset: function (seriesModel, ecModel) { var legendModels = ecModel.findComponents({ mainType: 'legend' }); if (!legendModels || !legendModels.length) { return; } var data = seriesModel.getData(); data.filterSelf(function (idx) { var name = data.getName(idx); //Ifinanylegendcomponentthestatusisnotselected.for(vari=0;i<legendModels.length;i++){if(!legendModels[i].isSelected(name)){returnfalse;}}returntrue;});}};};/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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'));/**LicensedtotheApacheSoftwareFoundation(ASF)underone*ormorecontributorlicenseagreements.SeetheNOTICEfile*distributedwiththisworkforadditionalinformation*regardingcopyrightownership.TheASFlicensesthisfile*toyouundertheApacheLicense,Version2.0(the*"License");youmaynotusethisfileexceptincompliance*withtheLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedonan*"AS IS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY*KIND,eitherexpressorimplied.SeetheLicenseforthe*specificlanguagegoverningpermissionsandlimitations*undertheLicense.*/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;})));