You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2021/04/23 09:09:48 UTC

[echarts-www] branch master updated: remove unused files

This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/echarts-www.git


The following commit(s) were added to refs/heads/master by this push:
     new 554305b  remove unused files
554305b is described below

commit 554305be54060a671adb268ef016048b0a34c355
Author: pissang <bm...@gmail.com>
AuthorDate: Fri Apr 23 17:09:35 2021 +0800

    remove unused files
---
 bin/build.js                                       |     2 +-
 vendors/echarts/echarts-20190709.min.js            |    22 -
 vendors/echarts/echarts-all-2.2.7.js               |    35 -
 vendors/echarts/echarts-all-3.0.0.js               | 50286 -------------------
 vendors/echarts/echarts.simple.min.js              |     7 -
 vendors/echarts/map/js/china.js                    |    27 -
 vendors/echarts/map/js/province/anhui.js           |    27 -
 vendors/echarts/map/js/province/fujian.js          |    27 -
 vendors/echarts/map/js/province/gansu.js           |    27 -
 vendors/echarts/map/js/province/guangdong.js       |    27 -
 vendors/echarts/map/js/province/guangxi.js         |    27 -
 vendors/echarts/map/js/province/guizhou.js         |    27 -
 vendors/echarts/map/js/province/hainan.js          |    27 -
 vendors/echarts/map/js/province/hebei.js           |    27 -
 vendors/echarts/map/js/province/heilongjiang.js    |    27 -
 vendors/echarts/map/js/province/henan.js           |    27 -
 vendors/echarts/map/js/province/hubei.js           |    27 -
 vendors/echarts/map/js/province/hunan.js           |    27 -
 vendors/echarts/map/js/province/jiangsu.js         |    27 -
 vendors/echarts/map/js/province/jiangxi.js         |    27 -
 vendors/echarts/map/js/province/jilin.js           |    27 -
 vendors/echarts/map/js/province/liaoning.js        |    27 -
 vendors/echarts/map/js/province/neimenggu.js       |    27 -
 vendors/echarts/map/js/province/ningxia.js         |    27 -
 vendors/echarts/map/js/province/qinghai.js         |    27 -
 vendors/echarts/map/js/province/shandong.js        |    27 -
 vendors/echarts/map/js/province/shanxi.js          |    27 -
 vendors/echarts/map/js/province/sichuan.js         |    27 -
 vendors/echarts/map/js/province/xicang.js          |    27 -
 vendors/echarts/map/js/province/xinjiang.js        |    27 -
 vendors/echarts/map/js/province/yunnan.js          |    27 -
 vendors/echarts/map/js/province/zhejiang.js        |    27 -
 vendors/echarts/map/js/world.js                    |    27 -
 vendors/echarts/map/json/china.json                |     1 -
 vendors/echarts/map/json/province/anhui.json       |     1 -
 vendors/echarts/map/json/province/fujian.json      |     1 -
 vendors/echarts/map/json/province/gansu.json       |     1 -
 vendors/echarts/map/json/province/guangdong.json   |     1 -
 vendors/echarts/map/json/province/guangxi.json     |     1 -
 vendors/echarts/map/json/province/guizhou.json     |     1 -
 vendors/echarts/map/json/province/hainan.json      |     1 -
 vendors/echarts/map/json/province/hebei.json       |     1 -
 .../echarts/map/json/province/heilongjiang.json    |     1 -
 vendors/echarts/map/json/province/henan.json       |     1 -
 vendors/echarts/map/json/province/hubei.json       |     1 -
 vendors/echarts/map/json/province/hunan.json       |     1 -
 vendors/echarts/map/json/province/jiangsu.json     |     1 -
 vendors/echarts/map/json/province/jiangxi.json     |     1 -
 vendors/echarts/map/json/province/jilin.json       |     1 -
 vendors/echarts/map/json/province/liaoning.json    |     1 -
 vendors/echarts/map/json/province/neimenggu.json   |     1 -
 vendors/echarts/map/json/province/ningxia.json     |     1 -
 vendors/echarts/map/json/province/qinghai.json     |     1 -
 vendors/echarts/map/json/province/shandong.json    |     1 -
 vendors/echarts/map/json/province/shanxi.json      |     1 -
 vendors/echarts/map/json/province/sichuan.json     |     1 -
 vendors/echarts/map/json/province/xicang.json      |     1 -
 vendors/echarts/map/json/province/xinjiang.json    |     1 -
 vendors/echarts/map/json/province/yunnan.json      |     1 -
 vendors/echarts/map/json/province/zhejiang.json    |     1 -
 vendors/echarts/map/json/world.json                |     1 -
 61 files changed, 1 insertion(+), 51135 deletions(-)

diff --git a/bin/build.js b/bin/build.js
index 8238c46..fc58358 100644
--- a/bin/build.js
+++ b/bin/build.js
@@ -108,7 +108,7 @@ async function clean(config) {
 
     const srcRelativePathList = await globby([
         '**/*',
-        '!.*', // .git .gitignore .htaccess
+        '!.*', // .git .gitignore .htaccess .scripts .github
         '!v4/**/*', // v4 website
         '!README.md'
     ], {
diff --git a/vendors/echarts/echarts-20190709.min.js b/vendors/echarts/echarts-20190709.min.js
deleted file mode 100644
index 3de1ba5..0000000
--- a/vendors/echarts/echarts-20190709.min.js
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/*
-* 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
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasS [...]
diff --git a/vendors/echarts/echarts-all-2.2.7.js b/vendors/echarts/echarts-all-2.2.7.js
deleted file mode 100755
index f30ec17..0000000
--- a/vendors/echarts/echarts-all-2.2.7.js
+++ /dev/null
@@ -1,35 +0,0 @@
-!function(e){var t,i;!function(){function e(e,t){if(!t)return e;if(0===e.indexOf(".")){var i=t.split("/"),n=e.split("/"),a=i.length-1,o=n.length,r=0,s=0;e:for(var l=0;o>l;l++)switch(n[l]){case"..":if(!(a>r))break e;r++,s++;break;case".":s++;break;default:break e}return i.length=a-r,n=n.slice(s),i.concat(n).join("/")}return e}function n(t){function i(i,r){if("string"==typeof i){var s=n[i];return s||(s=o(e(i,t)),n[i]=s),s}i instanceof Array&&(r=r||function(){},r.apply(this,a(i,r,t)))}var n [...]
-
-null==e.__animators&&(e.__animators=[]);var V=e.__animators,U=this.animation.animate(r,{loop:a}).during(function(){o.modShape(e)}).done(function(){var t=i.indexOf(e.__animators,U);t>=0&&V.splice(t,1)});return V.push(U),U}n("Element not existed")},V.prototype.stopAnimation=function(e){if(e.__animators){for(var t=e.__animators,i=t.length,n=0;i>n;n++)t[n].stop();t.length=0}return this},V.prototype.clearAnimation=function(){return this.animation.clear(),this},V.prototype.showLoading=function [...]
-this.zr.modShape(this._axisLineShape.id),e=!0),this._axisShadowShape.invisible||(this._axisShadowShape.invisible=!0,this.zr.modShape(this._axisShadowShape.id),e=!0),this._axisCrossShape.invisible||(this._axisCrossShape.invisible=!0,this.zr.modShape(this._axisCrossShape.id),e=!0),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2),e&&this.zr.refreshNextFrame(),this.showing=!1},_show:functio [...]
-for(var i=this.legendOption.data,n=0,a=i.length;a>n;n++)if(this._getName(i[n])===e)return;this.legendOption.data.push(e),this.setColor(e,t),this._selectedMap[e]=!0,this._hasDataMap[e]=!0},del:function(e){for(var t=this.legendOption.data,i=0,n=t.length;n>i;i++)if(this._getName(t[i])===e)return this.legendOption.data.splice(i,1)},getItemShape:function(e){if(null!=e)for(var t,i=0,n=this.shapeList.length;n>i;i++)if(t=this.shapeList[i],t._name===e&&"text"!=t.type)return t},setItemShape:functi [...]
-
-null==l.x&&(l.x=s.x),null==l.y&&(l.y=s.y+(s.r0+s.r)/2-5);for(var h=this.createTextShape(i.textStyle),m=this.createBackgroundShape(i.backgroundColor),V=s.x,U=s.y,d=s.r0+6,p=s.r-6,c=s.color,u=a.lift(c,.1),y=new o({highlightStyle:n.clone(s)}),g=[],b=a.getGradientColors(["#ff6400","#ffe100","#97ff00"],25),f=15,k=240,x=0;16>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:"fill",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V [...]
-this._processDragLeave(e)),this._lastHover=null,this.storage.delHover(),this.painter.clearHover());var a="default";if(this._draggingTarget)this.storage.drift(this._draggingTarget.id,i,n),this._draggingTarget.modSelf(),this.storage.addHover(this._draggingTarget),this._clickThreshold++;else if(this._isMouseDown){var o=!1;this.painter.eachBuildinLayer(function(e){e.panable&&(a="move",e.position[0]+=i,e.position[1]+=n,o=!0,e.dirty=!0)}),o&&this.painter.refresh()}this._draggingTarget||this._h [...]
-var t=e("../tool/area"),i=e("./Base"),n=function(e){i.call(this,e)};return n.prototype={type:"text",brush:function(e,i){var n=this.style;if(i&&(n=this.getHighlightStyle(n,this.highlightStyle||{})),"undefined"!=typeof n.text&&n.text!==!1){e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.textFont&&(e.font=n.textFont),e.textAlign=n.textAlign||"start",e.textBaseline=n.textBaseline||"middle";var a,o=(n.text+"").split("\n"),r=t.getTextHeight("国",n.textFont),s=this.getRect(n) [...]
-
-if(r.show){var m=e.style;m.text=this._getLabelText(t,i,n,"normal"),m.textPosition=null==r.position?"horizontal"===a?"right":"top":r.position,m.textColor=l.color,m.textFont=this.getFont(l),m.textAlign=l.align,m.textBaseline=l.baseline}if(s.show){var V=e.highlightStyle;V.text=this._getLabelText(t,i,n,"emphasis"),V.textPosition=r.show?e.style.textPosition:null==s.position?"horizontal"===a?"right":"top":s.position,V.textColor=h.color,V.textFont=this.getFont(h),V.textAlign=h.align,V.textBasel [...]
-style:{startAngle:n.style.startAngle,endAngle:n.style.startAngle}}:{style:{r0:n.style.r}});var r=n.style.startAngle,s=n.style.endAngle;i(n,t,"startAngle","endAngle"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{startAngle:r,endAngle:s}).done(function(){n.__animating=!1}).start(o)}function s(e,t,n,a,o){t||(t={style:{x:"left"==n.style.textAlign?n.style.x+100:n.style.x-100,y:n.style.y}});var r=n.style.x,s=n.style.y;i(n,t,"x","y"),e.addShape(n),n.__animating=!0,e.animate(n. [...]
-this._textArea.readOnly=!0,this._textArea.style.cursor="text"),this._tDom.appendChild(this._buttonRefresh),this._sizeCssText="width:"+this._zrWidth+"px;height:"+this._zrHeight+"px;background-color:#fff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText},_optionToContent:function(){var e,t,i,a,o,r,s=[],l="";if(this.option.xAxis)for(s=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],e=0,a=s.length;a>e;e++)if("category"==(s[e].type||"category")){for(r=[],t=0 [...]
-
-"horizontal"==this.zoomOption.orient?(i=l.x.max-l.x.min,n=this._zoom.start/100*i+l.x.min,a=this._zoom.end/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start2/100*i+l.y.min,r=this._zoom.end2/100*i+l.y.min):(i=l.x.max-l.x.min,n=this._zoom.start2/100*i+l.x.min,a=this._zoom.end2/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start/100*i+l.y.min,r=this._zoom.end/100*i+l.y.min);var h;(h=l.x.dataMappingMethods)&&(n=h.coord2Value(n),a=h.coord2Value(a)),(h=l.y.dataMappingMethods)&&(o=h.coord2Value( [...]
-return e>=0&&0>i?(n-=i,i=0):0>=t&&n>0&&(i-=n,n=0),[i,n]}function u(e){return e=(+e).toFixed(15).split("."),e.pop().replace(/0+$/,"").length}function y(e,t,i,n){if(x){var a=o(e,4,1);i.e-a.e>6&&(a={c:0,e:i.e}),s(i,a),s(n,a),n.c+=a.c-i.c,i.c=a.c}else if(_){var r=o(t,4);n.e-r.e>6&&(r={c:0,e:n.e}),s(i,r),s(n,r),i.c+=r.c-n.c,n.c=r.c}}function g(e,t,i){var n=i?[i]:k,s=t-e;if(0===s)return t=o(t,3),i=n[0],t.c=v(t.c+i/2),a(t.c-i,t.c,i,t.e);I(t/s)<1e-6&&(t=0),I(e/s)<1e-6&&(e=0);var l,h,m,V=[[5,10], [...]
-
-},this._selectedMap={},this._range={},this.refresh(a),t.bind(r.EVENT.HOVER,this._onhoverlink)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("../util/shape/HandlePolygon"),r=e("../config");r.dataRange={zlevel:0,z:4,show:!0,orient:"vertical",x:"left",y:"bottom",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,precision:0,splitNumber:5,splitList:null,calculable:!1,selectedMode:!0,hoverLink:!0,re [...]
-this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t]&&!isNaN(a[V].value)&&(0!==+a[V].value?r++:s++,l+=+a[V].value,h=Math.max(h,+a[V].value));if(0!==l){for(var d,p,c,u,y,g,b=100,f=n.clockWise,k=(n.startAngle.toFixed(2)-0+360)%360,x=n.minAngle||.01,_=360-x*r-.01*s,L=n.roseType,V=0,U=a.length;U>V;V++)if(t=a[V].name,this.selectedMap[t]&&!isNaN(a[V].value)){if(p=o?o.getColor(t):this.zr.getColor(V),b=a[V].value/l,d="area"!=L?f?k-b*_-(0!==b?x:.01):b*_+k+(0!==b?x:.01):f?k-360/U:360/U+k,d [...]
-
-i.eachNode(function(t){var i=t.layout.startAngle/Math.PI*180*m,h=t.layout.endAngle/Math.PI*180*m,V=(i*-m+h*-m)/2;V%=360,0>V&&(V+=360);var d=90>=V||V>=270;V=V*Math.PI/180;var p=[Math.cos(V),-Math.sin(V)],c=0;c=a.ribbonType?a.showScaleText?35+r:r:r+t.layout.size;var u=U.scale([],p,l[1]+c);U.add(u,u,s);var y={zlevel:e.zlevel,z:e.z+1,hoverable:!1,style:{text:null==t.data.label?t.id:t.data.label,textAlign:d?"left":"right"}};o?(y.rotation=d?V:Math.PI+V,y.style.x=d?l[1]+c:-l[1]-c,y.style.y=0,y. [...]
-
-}i>0&&r.scale(n,n,1/i)}this.updateForce(),this.updatePosition()},a.prototype.updateForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];r.copy(i.forcePrev,i.force),r.copy(i.speedPrev,i.speed),r.set(i.force,0,0)}this.updateNodeNodeForce(),this.gravity>0&&this.updateGravityForce(),this.updateEdgeForce(),this.preventNodeEdgeOverlap&&this.updateNodeEdgeForce()},a.prototype.updatePosition=function(){for(var e=this.nodes.length,t=r.create(),i=0;e>i;i++){var n=this.node [...]
-y:Math.round(e.y-e.b-t/2),width:2*e.a+t,height:2*e.b+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/component/roamController",["require","./base","zrender/shape/Rectangle","zrender/shape/Sector","zrender/shape/Circle","../config","zrender/tool/util","zrender/tool/color","zrender/tool/event","../component"],function(e){function t(e,t,n,a,o){if(this.rcOption={},a.roamController&&a.roamController.show){if(!a.roamController.mapTypeControl)return void console.error("option.roamC [...]
-encodeOffsets:[[118750,41232]]}},{type:"Feature",id:"110115",properties:{name:"大兴区",cp:[116.4716,39.6352],childNum:1},geometry:{type:"Polygon",coordinates:["@@F\\E~DFN@BDFEpHFCHBBEGCDCJBHUDSBB@ELCPbF@B\\J@BJVAFJ\\ADKTCBGECFMT@BMN@@FH@DaNBEnvB@FPBATK@FHEFIAKFBFL@@PKBFJHC@FXBRAFCDMPDTOL@JIVFDHH@DDH@BGRFCDLD@N^@@CNA@KNOAEBCECFEGCFGMGFIPMOEJOLBADBBHGG@GCHIECY@INC@DMGS\\AIOZAAEYA@GT@KKMBEETCGMVINFxA@MJADB@FlA@HJA@NND@DFA@DVAZBBOFKH_JA@K^GBC@EFE„G@gAENMXKJigC@IbSJMqGOP£RGSMGE@kbQFDPEFiBSGGSBK] [...]
-encodeOffsets:[[119858,27754]]}},{type:"Feature",id:"3508",properties:{name:"龙岩市",cp:[116.8066,25.2026],childNum:7},geometry:{type:"Polygon",coordinates:["@@ša„I@ƒVU„bVb°m@b„UXJ@nV@VUUwVW@klJ@UXK@Ul@Xa‚@UVaXKVLlJU£lm„@XLlL@`VXnlVVnIVašll@XV@@Ulw@aV@XwW¥XU@mlLnUlƒV@XwWaXUšJVnUVlb@l„zlJUVk@UXVVVxlVn@nXV@@lVVlI@w@K@mnI@W@wU_VWšbV„VVnKšbla„_n‚bX@°»Van@VUUaUamXUKW„K@a@Ukƒ@wWkXƒWW@wUU™Kw@_lyƒwUkU@@Uƒ@kamVmƒXašUVUka@Wk@»UUUVƒKkbWU™VUbk@mkƒxkƒƒKnIVUmW@kUKmXUmVaU@kU@m@KUWVkIWJ@ŽU@UI@wUUU [...]
-encodeOffsets:[[[108799,29239]],[[110532,27822]]]}},{type:"Feature",id:"5226",properties:{name:"黔东南苗族侗族自治州",cp:[108.4241,26.4166],childNum:17},geometry:{type:"MultiPolygon",coordinates:[["@@VV@XkV@bUbWJU¼Vb@Vnb@bš„@J@bƒL@LV@UVƒlUI@a™KULVb@bkJmx„šlLVxknVJk„‚xnKmnnL@bn`WIXlWLU@UxVbUVmKV„XI@JVIVJ@U„L@Wš@@UmUXUlV„UVJXImm@K„L@UVmVXV‚„LXblKlV@LXV„LlVVnkbmJ@xnXl@šbXa‚@Vana„ÒšL„m‚VnIl‚Þ¦°k@b„@@lV„nJlUnš‚VX_„@lVlK„šV„UUxVLVWVIXJšUlnnWlI@KUaUUVKn@VaVXV@na@ƒmw¯@mUkJUamI@lk@@am@@I„ƒUmVImUUw˜™@anU [...]
-return{type:"FeatureCollection",features:[{type:"Feature",id:"4113",properties:{name:"南阳市",cp:[112.4011,33.0359],childNum:12},geometry:{type:"Polygon",coordinates:["@@lKl@nVV@„bn„@VVnm‚nL‚LXx@š„‚VLlKVU„IXWÜ@șlbl@XUĊUlwnW„LÞw‚m@ÞUVmnVl@nX‚JXLm@VnnJla„I@VkxVb„@VŽln„J@knKVn„@°aVanal@XK°b„‚@š¯VJXIš„VK@al@nV„k‚@nK„a‚b„@XL@blVVKVLXK„@VaVI°mVaX@V_@a@yUkVw„VšIVašJ°™@anIlaV@nKnXÆm@wUUV±UUWUKnaWwXUWmŁ¯Vƒam@kakImƒUKƒ»lan@VXXa˜W@@UlUUa@a@UlwUƒV@Xal@@anIVaUK@V™XmwVmUmV„LXl‚@nalLnal@„šnKlkV@@ [...]
-encodeOffsets:[[122344,34504]]}},{type:"Feature",id:"3203",properties:{name:"徐州市",cp:[117.5208,34.3268],childNum:7},geometry:{type:"Polygon",coordinates:["@@XKVX@WnIVx@K°Lnll@@I°K„nVašU°x²mlxš@VanU@aƒk@akmV@@w™@Ua@aUwVwUw@w›@UK@£kaĉlóIÇVkŽ±@@kUKmVkIkxW@Ua¯UUm@UVI@WVI„JV@ƒ@Um@Uana„U@m‚I@J@XV@XaVlkXƒVaUUWLUyVIXmWak@ƒXkJókƒJUL@KWkk@ULU@Wa™lUIkJmI™mk„VbVš@lV°kXUKWKULU„mb@VUlVnƒb@VV@IVKUUmU@ak@@bmV@xklƒUƒU@UKmV@nƒJVbkXƒKUamLUJ¯UUVmI™bVV—Ll`@LƒLU`m@kXUVU@V„lxUK@xkIWbUKƒx@V‚kVVn™b¯@@U™@ƒxk [...]
-properties:{name:"呼和浩特市",cp:[111.4124,40.4901],childNum:6},geometry:{type:"Polygon",coordinates:["@@ʶUĊ¥ÈřĠ¯šĉômšīƒÑ¯m„wk¯ÇV°ÑƒżġĊljǓɱţǓ›ƝóX¯ƒɛÒóa@nÝÆôƜŚĉĢʉŰĊҙ¤ȗĖV¼ÅxWƞۂlXXèm„ÝmUnšĠƒĢóÒkƚ„ÆUÞ¼ÞJĸÑ°„ɲĕš°Ŏn"],encodeOffsets:[[114098,42312]]}},{type:"Feature",id:"1503",properties:{name:"乌海市",cp:[106.886,39.4739],childNum:1},geometry:{type:"Polygon",coordinates:["@@Ș°ÇīXњŗ@ȍlkƒlUŁ±īĵKō¼VŽÇôXĸ¯Ž@šťê„°ź„k¤„x™œ@Ĭ"],encodeOffsets:[[109317,40799]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData [...]
-encodeOffsets:[[113614,39657]]}},{type:"Feature",id:"1411",properties:{name:"吕梁市",cp:[111.3574,37.7325],childNum:13},geometry:{type:"Polygon",coordinates:["@@@a@w„@„wlbnJVb„@VbšVVV„InaWmXI@a‚aUmVUVkn@°J@_„Wš@lIX¥lUnaV„V@naV@„xĊ„n‚V@‚wn¯wƱX_WmXaWUnKV_V›VUUUUWJkUVnKlk¯™@@kmKUaŁ±KkU@WmI@WUIlUUmVwXƒ‚w@ƒUlUVwœV‚@„Lnb‚W@anU@UšaVkô@l»n@na˜JnUÈLVaƃUUVm„VKVƒ²L@mU_lK@UVWkU‚a@a@U¯aUaƒÑóÑUb™„ƒKk@@aƒk¯mVaUwVƒÑkWUmK@UUKmXUWÝwUa™LUU@aWJUUU@Ua݄U@WL@VKVaVI@WnU@alIVKƒƒ@kIƒmIkJ@™m@ƒ™@@_™K@x [...]
-encodeOffsets:[[-59008,-30941]]}},{type:"Feature",id:"BRN",properties:{name:"Brunei"},geometry:{type:"Polygon",coordinates:["@@ͬ̾܎Ң›Я·՛Б€ǭ˹ϥѦ"],encodeOffsets:[[116945,4635]]}},{type:"Feature",id:"BTN",properties:{name:"Bhutan"},geometry:{type:"Polygon",coordinates:["@@΂ˍÏԩۇ{ۿÈՇſޅ͊kǚ֌زҒɈ׸șѺqπɥ"],encodeOffsets:[[93898,28439]]}},{type:"Feature",id:"BWA",properties:{name:"Botswana"},geometry:{type:"Polygon",coordinates:["@@ǜƭ˄ӡॎइήĝD̑ʚՑٰŹ՚ϝ஑أݭع˩֓ʧ́ҙãƧГďʽ՝țہ¤БɾΟĸХșȵГЉʧпϑ׻đȇ̐üԠӽߚɧŲAរࠤˆ|Ჾش„ಖ͎̎΍՜ [...]
-encodeOffsets:[[50113,9679]]}},{type:"Feature",id:"SOM",properties:{name:"Somalia"},geometry:{type:"Polygon",coordinates:["@@ѼĎЊ˾͈FpɵýӧHѳǯ̣ʁࣥЙयԱ੷ܝ௷ܓवধ଩ࡁڹష࠯޳ٕँৱȗѷȍȣӽۚWᵤܾ॒ɰˆբfݠפબšᛜᡄה۬ϜԪ@ѬBࡒFΌLbːhϰŰ"],encodeOffsets:[[50923,11857]]}},{type:"Feature",id:"SRB",properties:{name:"Republic of Serbia"},geometry:{type:"Polygon",coordinates:["@@Ԡȡà΋Ӫʓ˄ȌȸĿșƗƶƥȷȏø̫Тγ͋ʿƗˋĞijƑšϳa˹µƒØĴĴĦȴšKǍƼƑ ŋƆƽÀšŠƯ±ś˧ȩÑèð͋Ǩ˟ĜūŜɟƠȢšŬЄЛ͔ɀτ̥Ë͔́ˉʈȱ͘٢ɚԾ™ҖͣĦˋ"],encodeOffsets:[[21376,46507]]}},{type:"Feature",id:"SUR",propert [...]
-encodeOffsets:[[124437,30983]]}},{type:"Feature",id:"3310",properties:{name:"台州市",cp:[121.1353,28.6688],childNum:7},geometry:{type:"Polygon",coordinates:["@@lV„IVWVz@bXJl@Xal@°„nLll@nVxnV„K@UJVbƒ¦°„k`UIWJXnƚ@bUJ„Xl@lb„Wn@UzVV@bVVšmVnnJVXna‚bšKUKnUVVUnVLlKVLXa„Jm£@mU@WanaU_°@VWnV@UVWnIVVVKlXœÒlK@wVK„L°m„@„„l@ô„Kšw„ĉƾůUƒl£@»UƒVk„m@ƅUƒƒaÛIŏmUk@m„w@a™£ƒWk@ţšƒIm±@ankôUlaU™Uw¯ƒōaƒbÇbţm™ÞšÞVĖ„b„l@š@n‚VXxƒbUl@XmbƒŽ¯lUUU™W@ÛI±xU@mƒb@bmJ@bUzƒV@b¯bƒKUa¯KV_@Kk@@mWIƒ@lUU›b@bkVm@kwUÇU_WKU@Ux™ [...]
-show:!0,x:5,y:12,textStyle:{align:"left",color:"#000",fontFamily:"Arial",fontSize:13,fontStyle:"normal",fontWeight:"normal"}},breadcrumb:{show:!0,textStyle:{}},borderWidth:1,borderColor:"#ccc",childBorderWidth:1,childBorderColor:"#ccc"},emphasis:{}}};var m=e("../util/ecData"),V=e("zrender/config"),U=(e("zrender/tool/event"),e("zrender/tool/util")),d=e("zrender/tool/color");return t.prototype={type:h.CHART_TYPE_TREEMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=this.op [...]
\ No newline at end of file
diff --git a/vendors/echarts/echarts-all-3.0.0.js b/vendors/echarts/echarts-all-3.0.0.js
deleted file mode 100644
index 94f6f02..0000000
--- a/vendors/echarts/echarts-all-3.0.0.js
+++ /dev/null
@@ -1,50286 +0,0 @@
-(function (root, factory) {
-    if (typeof define === 'function' && define.amd) {
-        // AMD. Register as an anonymous module.
-        define([], factory);
-    } else if (typeof module === 'object' && module.exports) {
-        // Node. Does not work with strict CommonJS, but
-        // only CommonJS-like environments that support module.exports,
-        // like Node.
-        module.exports = factory();
-    } else {
-        // Browser globals (root is window)
-        root.echarts = factory();
-    }
-}(this, function () {
-var require, define;
-(function () {
-    var mods = {};
-
-    define = function (id, deps, factory) {
-        // In case like
-        // define('echarts/model/globalDefault', {...});
-        if (arguments.length === 2) {
-            factory = deps;
-            deps = [];
-            if (typeof factory !== 'function') {
-                var configObj = factory;
-                factory = function () { return configObj; };
-            }
-        }
-        mods[id] = {
-            id: id,
-            deps: deps,
-            factory: factory,
-            defined: 0,
-            exports: {},
-            require: createRequire(id)
-        };
-    };
-
-    require = createRequire('');
-
-    function normalize(id, baseId) {
-        if (!baseId) {
-            return id;
-        }
-
-        if (id.indexOf('.') === 0) {
-            var basePath = baseId.split('/');
-            var namePath = id.split('/');
-            var baseLen = basePath.length - 1;
-            var nameLen = namePath.length;
-            var cutBaseTerms = 0;
-            var cutNameTerms = 0;
-
-            pathLoop: for (var i = 0; i < nameLen; i++) {
-                switch (namePath[i]) {
-                    case '..':
-                        if (cutBaseTerms < baseLen) {
-                            cutBaseTerms++;
-                            cutNameTerms++;
-                        }
-                        else {
-                            break pathLoop;
-                        }
-                        break;
-                    case '.':
-                        cutNameTerms++;
-                        break;
-                    default:
-                        break pathLoop;
-                }
-            }
-
-            basePath.length = baseLen - cutBaseTerms;
-            namePath = namePath.slice(cutNameTerms);
-
-            return basePath.concat(namePath).join('/');
-        }
-
-        return id;
-    }
-
-    function createRequire(baseId) {
-        var cacheMods = {};
-
-        function localRequire(id, callback) {
-            if (typeof id === 'string') {
-                var exports = cacheMods[id];
-                if (!exports) {
-                    exports = getModExports(normalize(id, baseId));
-                    cacheMods[id] = exports;
-                }
-
-                return exports;
-            }
-            else if (id instanceof Array) {
-                callback = callback || function () {};
-                callback.apply(this, getModsExports(id, callback, baseId));
-            }
-        };
-
-        return localRequire;
-    }
-
-    function getModsExports(ids, factory, baseId) {
-        var es = [];
-        var mod = mods[baseId];
-
-        for (var i = 0, l = Math.min(ids.length, factory.length); i < l; i++) {
-            var id = normalize(ids[i], baseId);
-            var arg;
-            switch (id) {
-                case 'require':
-                    arg = (mod && mod.require) || require;
-                    break;
-                case 'exports':
-                    arg = mod.exports;
-                    break;
-                case 'module':
-                    arg = mod;
-                    break;
-                default:
-                    arg = getModExports(id);
-            }
-            es.push(arg);
-        }
-
-        return es;
-    }
-
-    function getModExports(id) {
-        var mod = mods[id];
-        if (!mod) {
-            throw new Error('No ' + id);
-        }
-
-        if (!mod.defined) {
-            var factory = mod.factory;
-            var factoryReturn = factory.apply(
-                this,
-                getModsExports(mod.deps || [], factory, id)
-            );
-            if (typeof factoryReturn !== 'undefined') {
-                mod.exports = factoryReturn;
-            }
-            mod.defined = 1;
-        }
-
-        return mod.exports;
-    }
-}());
-
-
-define('zrender/graphic/Gradient',['require'],function (require) {
-
-    /**
-     * @param {Array.<Object>} colorStops
-     */
-    var Gradient = function (colorStops) {
-
-        this.colorStops = colorStops || [];
-    };
-
-    Gradient.prototype = {
-
-        constructor: Gradient,
-
-        addColorStop: function (offset, color) {
-            this.colorStops.push({
-
-                offset: offset,
-
-                color: color
-            });
-        }
-    };
-
-    return Gradient;
-});
-/**
- */
-define('zrender/core/util',['require','../graphic/Gradient'],function(require) {
-    var Gradient = require('../graphic/Gradient');
-    // 用于处理merge时无法遍历Date等对象的问题
-    var BUILTIN_OBJECT = {
-        '[object Function]': 1,
-        '[object RegExp]': 1,
-        '[object Date]': 1,
-        '[object Error]': 1,
-        '[object CanvasGradient]': 1
-    };
-
-    var objToString = Object.prototype.toString;
-
-    var arrayProto = Array.prototype;
-    var nativeForEach = arrayProto.forEach;
-    var nativeFilter = arrayProto.filter;
-    var nativeSlice = arrayProto.slice;
-    var nativeMap = arrayProto.map;
-    var nativeReduce = arrayProto.reduce;
-
-    /**
-     * @param {*} source
-     * @return {*} 拷贝后的新对象
-     */
-    function clone(source) {
-        if (typeof source == 'object' && source !== null) {
-            var result = source;
-            if (source instanceof Array) {
-                result = [];
-                for (var i = 0, len = source.length; i < len; i++) {
-                    result[i] = clone(source[i]);
-                }
-            }
-            else if (
-                !isBuildInObject(source)
-                // 是否为 dom 对象
-                && !isDom(source)
-            ) {
-                result = {};
-                for (var key in source) {
-                    if (source.hasOwnProperty(key)) {
-                        result[key] = clone(source[key]);
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        return source;
-    }
-
-    /**
-     * @param {Object=} target
-     * @param {Object=} source
-     * @param {boolean} [overwrite=false]
-     */
-    function merge(target, source, overwrite) {
-        if (!target) { // Might be null/undefined
-            return;
-        }
-        if (!source) { // Might be null/undefined
-            return target;
-        }
-
-        for (var key in source) {
-            if (source.hasOwnProperty(key)) {
-                var targetProp = target[key];
-                var sourceProp = source[key];
-
-                if (isObject(sourceProp)
-                    && isObject(targetProp)
-                    && !isArray(sourceProp)
-                    && !isArray(targetProp)
-                    && !isDom(sourceProp)
-                    && !isDom(targetProp)
-                    && !isBuildInObject(sourceProp)
-                    && !isBuildInObject(targetProp)
-                ) {
-                    // 如果需要递归覆盖,就递归调用merge
-                    merge(targetProp, sourceProp, overwrite);
-                }
-                else if (overwrite || !(key in target)) {
-                    // 否则只处理overwrite为true,或者在目标对象中没有此属性的情况
-                    // NOTE,在 target[key] 不存在的时候也是直接覆盖
-                    target[key] = clone(source[key], true);
-                }
-            }
-        }
-
-        return target;
-    }
-
-    /**
-     * @param {Array} targetAndSources The first item is target, and the rests are source.
-     * @param {boolean} [overwrite=false]
-     * @return {*} target
-     */
-    function mergeAll(targetAndSources, overwrite) {
-        var result = targetAndSources[0];
-        for (var i = 1, len = targetAndSources.length; i < len; i++) {
-            result = merge(result, targetAndSources[i], overwrite);
-        }
-        return result;
-    }
-
-    /**
-     * @param {*} target
-     * @param {*} source
-     */
-    function extend(target, source) {
-        for (var key in source) {
-            if (source.hasOwnProperty(key)) {
-                target[key] = source[key];
-            }
-        }
-        return target;
-    }
-
-    /**
-     * @param {*} target
-     * @param {*} source
-     * @param {boolen} [overlay=false]
-     */
-    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;
-    }
-
-    function createCanvas() {
-        return document.createElement('canvas');
-    }
-    // FIXME
-    var _ctx;
-    function getContext() {
-        if (!_ctx) {
-            // Use util.createCanvas instead of createCanvas
-            // because createCanvas may be overwritten in different environment
-            _ctx = util.createCanvas().getContext('2d');
-        }
-        return _ctx;
-    }
-
-    /**
-     * 查询数组中元素的index
-     */
-    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;
-    }
-
-    /**
-     * 构造类继承关系
-     *
-     * @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;
-    }
-
-    /**
-     * @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);
-    }
-
-    /**
-     * @param {Array|TypedArray} data
-     */
-    function isArrayLike(data) {
-        if (! data) {
-            return;
-        }
-        if (typeof data == 'string') {
-            return false;
-        }
-        return typeof data.length == 'number';
-    }
-
-    /**
-     * 数组或对象遍历
-     * @memberOf module:zrender/tool/util
-     * @param {Object|Array} obj
-     * @param {Function} cb
-     * @param {*} [context]
-     */
-    function each(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);
-                }
-            }
-        }
-    }
-
-    /**
-     * 数组映射
-     * @memberOf module:zrender/tool/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;
-        }
-    }
-
-    /**
-     * @memberOf module:zrender/tool/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;
-        }
-    }
-
-    /**
-     * 数组过滤
-     * @memberOf module:zrender/tool/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;
-        }
-    }
-
-    /**
-     * 数组项查找
-     * @memberOf module:zrender/tool/util
-     * @param {Array} obj
-     * @param {Function} cb
-     * @param {*} [context]
-     * @return {Array}
-     */
-    function find(obj, cb, context) {
-        if (!(obj && cb)) {
-            return;
-        }
-        for (var i = 0, len = obj.length; i < len; i++) {
-            if (cb.call(context, obj[i], i, obj)) {
-                return obj[i];
-            }
-        }
-    }
-
-    /**
-     * @memberOf module:zrender/tool/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)));
-        };
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {Function} func
-     * @param {...}
-     * @return {Function}
-     */
-    function curry(func) {
-        var args = nativeSlice.call(arguments, 1);
-        return function () {
-            return func.apply(this, args.concat(nativeSlice.call(arguments)));
-        };
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isArray(value) {
-        return objToString.call(value) === '[object Array]';
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isFunction(value) {
-        return typeof value === 'function';
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isString(value) {
-        return objToString.call(value) === '[object String]';
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isObject(value) {
-        // Avoid a V8 JIT bug in Chrome 19-20.
-        // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
-        var type = typeof value;
-        return type === 'function' || (!!value && type == 'object');
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isBuildInObject(value) {
-        return !!BUILTIN_OBJECT[objToString.call(value)]
-            || (value instanceof Gradient);
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {*} value
-     * @return {boolean}
-     */
-    function isDom(value) {
-        return value && value.nodeType === 1
-               && typeof(value.nodeName) == 'string';
-    }
-
-    /**
-     * If value1 is not null, then return value1, otherwise judget rest of values.
-     * @param  {*...} values
-     * @return {*} Final value
-     */
-    function retrieve(values) {
-        for (var i = 0, len = arguments.length; i < len; i++) {
-            if (arguments[i] != null) {
-                return arguments[i];
-            }
-        }
-    }
-
-    /**
-     * @memberOf module:zrender/tool/util
-     * @param {Array} arr
-     * @param {number} startIndex
-     * @param {number} endIndex
-     * @return {Array}
-     */
-    function slice() {
-        return Function.call.apply(nativeSlice, arguments);
-    }
-
-    /**
-     * @param {boolean} condition
-     * @param {string} message
-     */
-    function assert(condition, message) {
-        if (!condition) {
-            throw new Error(message);
-        }
-    }
-
-    var util = {
-        inherits: inherits,
-        mixin: mixin,
-        clone: clone,
-        merge: merge,
-        mergeAll: mergeAll,
-        extend: extend,
-        defaults: defaults,
-        getContext: getContext,
-        createCanvas: createCanvas,
-        indexOf: indexOf,
-        slice: slice,
-        find: find,
-        isArrayLike: isArrayLike,
-        each: each,
-        map: map,
-        reduce: reduce,
-        filter: filter,
-        bind: bind,
-        curry: curry,
-        isArray: isArray,
-        isString: isString,
-        isObject: isObject,
-        isFunction: isFunction,
-        isBuildInObject: isBuildInObject,
-        isDom: isDom,
-        retrieve: retrieve,
-        assert: assert,
-        noop: function () {}
-    };
-    return util;
-});
-
-define('echarts/util/clazz',['require','zrender/core/util'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-
-    var clazz = {};
-
-    var TYPE_DELIMITER = '.';
-    var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';
-    /**
-     * @public
-     */
-    var parseClassType = clazz.parseClassType = function (componentType) {
-        var ret = {main: '', sub: ''};
-        if (componentType) {
-            componentType = componentType.split(TYPE_DELIMITER);
-            ret.main = componentType[0] || '';
-            ret.sub = componentType[1] || '';
-        }
-        return ret;
-    };
-    /**
-     * @public
-     */
-    clazz.enableClassExtend = function (RootClass, preConstruct) {
-        RootClass.extend = function (proto) {
-            var ExtendedClass = function () {
-                preConstruct && preConstruct.apply(this, arguments);
-                RootClass.apply(this, arguments);
-            };
-
-            zrUtil.extend(ExtendedClass.prototype, zrUtil.extend({
-                $superCall: function (methodName) {
-                    var args = zrUtil.slice(arguments, 1);
-                    return findSuperMethod(this, methodName).apply(this, args);
-                },
-                $superApply: function (methodName, args) {
-                    return findSuperMethod(this, methodName).apply(this, args);
-                }
-            }, proto));
-
-            ExtendedClass.extend = this.extend;
-            zrUtil.inherits(ExtendedClass, this);
-            ExtendedClass.$superClass = this;
-
-            return ExtendedClass;
-        };
-    };
-
-    // Find the first method that different with given metod.
-    // If only use closure to implements $superApply and $supperCall,
-    // Consider this case:
-    // class A has method f,
-    // class B inherits class A, overrides method f, f call this.$superApply('f'),
-    // class C inherits class B, do not overrides method f,
-    // then when method of class C is called, dead loop occured.
-    function findSuperMethod(context, methodName) {
-        var SuperClass = context.constructor;
-        var thisMethod = context[methodName];
-        var method;
-
-        while (
-            (SuperClass = SuperClass.$superClass)
-            && (method = SuperClass.prototype[methodName])
-            && method === thisMethod
-        ) {/*jshint noempty:false */}
-
-        return method;
-    }
-
-    /**
-     * @param {Object} entity
-     * @param {Object} options
-     * @param {boolean} [options.registerWhenExtend]
-     * @public
-     */
-    clazz.enableClassManagement = function (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}
-         */
-        var storage = {};
-
-        entity.registerClass = function (Clazz, componentType) {
-            if (componentType) {
-                componentType = parseClassType(componentType);
-
-                if (!componentType.sub) {
-                    if (storage[componentType.main]) {
-                        throw new Error(componentType.main + 'exists');
-                    }
-                    storage[componentType.main] = Clazz;
-                }
-                else if (componentType.sub !== IS_CONTAINER) {
-                    var container = makeContainer(componentType);
-                    container[componentType.sub] = Clazz;
-                }
-            }
-            return Clazz;
-        };
-
-        entity.getClass = function (componentTypeMain, subType, throwWhenNotFound) {
-            var Clazz = storage[componentTypeMain];
-
-            if (Clazz && Clazz[IS_CONTAINER]) {
-                Clazz = subType ? Clazz[subType] : null;
-            }
-
-            if (throwWhenNotFound && !Clazz) {
-                throw new Error(
-                    'Component ' + componentTypeMain + '.' + (subType || '') + ' not exists'
-                );
-            }
-
-            return Clazz;
-        };
-
-        entity.getClassesByMainType = function (componentType) {
-            componentType = parseClassType(componentType);
-
-            var result = [];
-            var obj = storage[componentType.main];
-
-            if (obj && obj[IS_CONTAINER]) {
-                zrUtil.each(obj, function (o, type) {
-                    type !== IS_CONTAINER && result.push(o);
-                });
-            }
-            else {
-                result.push(obj);
-            }
-
-            return result;
-        };
-
-        entity.hasClass = function (componentType) {
-            // Just consider componentType.main.
-            componentType = parseClassType(componentType);
-            return !!storage[componentType.main];
-        };
-
-        /**
-         * @return {Array.<string>} Like ['aa', 'bb'], but can not be ['aa.xx']
-         */
-        entity.getAllClassMainTypes = function () {
-            var types = [];
-            zrUtil.each(storage, function (obj, type) {
-                types.push(type);
-            });
-            return types;
-        };
-
-        /**
-         * If a main type is container and has sub types
-         * @param  {string}  mainType
-         * @return {boolean}
-         */
-        entity.hasSubTypes = function (componentType) {
-            componentType = parseClassType(componentType);
-            var obj = storage[componentType.main];
-            return obj && obj[IS_CONTAINER];
-        };
-
-        entity.parseClassType = parseClassType;
-
-        function makeContainer(componentType) {
-            var container = storage[componentType.main];
-            if (!container || !container[IS_CONTAINER]) {
-                container = storage[componentType.main] = {};
-                container[IS_CONTAINER] = true;
-            }
-            return container;
-        }
-
-        if (options.registerWhenExtend) {
-            var originalExtend = entity.extend;
-            if (originalExtend) {
-                entity.extend = function (proto) {
-                    var ExtendedClass = originalExtend.call(this, proto);
-                    return entity.registerClass(ExtendedClass, proto.type);
-                };
-            }
-        }
-
-        return entity;
-    };
-
-    /**
-     * @param {string|Array.<string>} properties
-     */
-    clazz.setReadOnly = function (obj, properties) {
-        if (!zrUtil.isArray(properties)) {
-            properties = properties != null ? [properties] : [];
-        }
-        zrUtil.each(properties, function (prop) {
-            var value = obj[prop];
-
-            Object.defineProperty
-                && Object.defineProperty(obj, prop, {
-                    value: value, writable: false
-                });
-            zrUtil.isArray(obj[prop])
-                && Object.freeze
-                && Object.freeze(obj[prop]);
-        });
-    };
-
-    return clazz;
-});
-// TODO Parse shadow style
-// TODO Only shallow path support
-define('echarts/model/mixin/makeStyleMapper',['require','zrender/core/util'],function (require) {
-    var zrUtil = require('zrender/core/util');
-
-    return function (properties) {
-        // Normalize
-        for (var i = 0; i < properties.length; i++) {
-            if (!properties[i][1]) {
-               properties[i][1] = properties[i][0];
-            }
-        }
-        return function (excludes) {
-            var style = {};
-            for (var i = 0; i < properties.length; i++) {
-                var propName = properties[i][1];
-                if (excludes && zrUtil.indexOf(excludes, propName) >= 0) {
-                    continue;
-                }
-                var val = this.getShallow(propName);
-                if (val != null) {
-                    style[properties[i][0]] = val;
-                }
-            }
-            return style;
-        }
-    }
-});
-define('echarts/model/mixin/lineStyle',['require','./makeStyleMapper'],function (require) {
-    var getLineStyle = require('./makeStyleMapper')(
-        [
-            ['lineWidth', 'width'],
-            ['stroke', 'color'],
-            ['opacity'],
-            ['shadowBlur'],
-            ['shadowOffsetX'],
-            ['shadowOffsetY'],
-            ['shadowColor']
-        ]
-    );
-    return {
-        getLineStyle: function (excludes) {
-            var style = getLineStyle.call(this, excludes);
-            var lineDash = this.getLineDash();
-            lineDash && (style.lineDash = lineDash);
-            return style;
-        },
-
-        getLineDash: function () {
-            var lineType = this.get('type');
-            return (lineType === 'solid' || lineType == null) ? null
-                : (lineType === 'dashed' ? [5, 5] : [1, 1]);
-        }
-    };
-});
-define('echarts/model/mixin/areaStyle',['require','./makeStyleMapper'],function (require) {
-    return {
-        getAreaStyle: require('./makeStyleMapper')(
-            [
-                ['fill', 'color'],
-                ['shadowBlur'],
-                ['shadowOffsetX'],
-                ['shadowOffsetY'],
-                ['opacity'],
-                ['shadowColor']
-            ]
-        )
-    };
-});
-define('zrender/core/vector',[],function () {
-    var ArrayCtor = typeof Float32Array === 'undefined'
-        ? Array
-        : Float32Array;
-
-    /**
-     * @typedef {Float32Array|Array.<number>} Vector2
-     */
-    /**
-     * 二维向量类
-     * @exports zrender/tool/vector
-     */
-    var vector = {
-        /**
-         * 创建一个向量
-         * @param {number} [x=0]
-         * @param {number} [y=0]
-         * @return {Vector2}
-         */
-        create: function (x, y) {
-            var out = new ArrayCtor(2);
-            out[0] = x || 0;
-            out[1] = y || 0;
-            return out;
-        },
-
-        /**
-         * 复制向量数据
-         * @param {Vector2} out
-         * @param {Vector2} v
-         * @return {Vector2}
-         */
-        copy: function (out, v) {
-            out[0] = v[0];
-            out[1] = v[1];
-            return out;
-        },
-
-        /**
-         * 克隆一个向量
-         * @param {Vector2} v
-         * @return {Vector2}
-         */
-        clone: function (v) {
-            var out = new ArrayCtor(2);
-            out[0] = v[0];
-            out[1] = v[1];
-            return out;
-        },
-
-        /**
-         * 设置向量的两个项
-         * @param {Vector2} out
-         * @param {number} a
-         * @param {number} b
-         * @return {Vector2} 结果
-         */
-        set: function (out, a, b) {
-            out[0] = a;
-            out[1] = b;
-            return out;
-        },
-
-        /**
-         * 向量相加
-         * @param {Vector2} out
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         */
-        add: function (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
-         */
-        scaleAndAdd: function (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
-         */
-        sub: function (out, v1, v2) {
-            out[0] = v1[0] - v2[0];
-            out[1] = v1[1] - v2[1];
-            return out;
-        },
-
-        /**
-         * 向量长度
-         * @param {Vector2} v
-         * @return {number}
-         */
-        len: function (v) {
-            return Math.sqrt(this.lenSquare(v));
-        },
-
-        /**
-         * 向量长度平方
-         * @param {Vector2} v
-         * @return {number}
-         */
-        lenSquare: function (v) {
-            return v[0] * v[0] + v[1] * v[1];
-        },
-
-        /**
-         * 向量乘法
-         * @param {Vector2} out
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         */
-        mul: function (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
-         */
-        div: function (out, v1, v2) {
-            out[0] = v1[0] / v2[0];
-            out[1] = v1[1] / v2[1];
-            return out;
-        },
-
-        /**
-         * 向量点乘
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         * @return {number}
-         */
-        dot: function (v1, v2) {
-            return v1[0] * v2[0] + v1[1] * v2[1];
-        },
-
-        /**
-         * 向量缩放
-         * @param {Vector2} out
-         * @param {Vector2} v
-         * @param {number} s
-         */
-        scale: function (out, v, s) {
-            out[0] = v[0] * s;
-            out[1] = v[1] * s;
-            return out;
-        },
-
-        /**
-         * 向量归一化
-         * @param {Vector2} out
-         * @param {Vector2} v
-         */
-        normalize: function (out, v) {
-            var d = vector.len(v);
-            if (d === 0) {
-                out[0] = 0;
-                out[1] = 0;
-            }
-            else {
-                out[0] = v[0] / d;
-                out[1] = v[1] / d;
-            }
-            return out;
-        },
-
-        /**
-         * 计算向量间距离
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         * @return {number}
-         */
-        distance: function (v1, v2) {
-            return Math.sqrt(
-                (v1[0] - v2[0]) * (v1[0] - v2[0])
-                + (v1[1] - v2[1]) * (v1[1] - v2[1])
-            );
-        },
-
-        /**
-         * 向量距离平方
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         * @return {number}
-         */
-        distanceSquare: function (v1, v2) {
-            return (v1[0] - v2[0]) * (v1[0] - v2[0])
-                + (v1[1] - v2[1]) * (v1[1] - v2[1]);
-        },
-
-        /**
-         * 求负向量
-         * @param {Vector2} out
-         * @param {Vector2} v
-         */
-        negate: function (out, v) {
-            out[0] = -v[0];
-            out[1] = -v[1];
-            return out;
-        },
-
-        /**
-         * 插值两个点
-         * @param {Vector2} out
-         * @param {Vector2} v1
-         * @param {Vector2} v2
-         * @param {number} t
-         */
-        lerp: function (out, v1, v2, t) {
-            out[0] = v1[0] + t * (v2[0] - v1[0]);
-            out[1] = v1[1] + t * (v2[1] - v1[1]);
-            return out;
-        },
-
-        /**
-         * 矩阵左乘向量
-         * @param {Vector2} out
-         * @param {Vector2} v
-         * @param {Vector2} m
-         */
-        applyTransform: function (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
-         */
-        min: function (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
-         */
-        max: function (out, v1, v2) {
-            out[0] = Math.max(v1[0], v2[0]);
-            out[1] = Math.max(v1[1], v2[1]);
-            return out;
-        }
-    };
-
-    vector.length = vector.len;
-    vector.lengthSquare = vector.lenSquare;
-    vector.dist = vector.distance;
-    vector.distSquare = vector.distanceSquare;
-
-    return vector;
-});
-
-define('zrender/core/matrix',[],function () {
-    var ArrayCtor = typeof Float32Array === 'undefined'
-        ? Array
-        : Float32Array;
-    /**
-     * 3x2矩阵操作类
-     * @exports zrender/tool/matrix
-     */
-    var matrix = {
-        /**
-         * 创建一个单位矩阵
-         * @return {Float32Array|Array.<number>}
-         */
-        create : function() {
-            var out = new ArrayCtor(6);
-            matrix.identity(out);
-
-            return out;
-        },
-        /**
-         * 设置矩阵为单位矩阵
-         * @param {Float32Array|Array.<number>} out
-         */
-        identity : function(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
-         */
-        copy: function(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
-         */
-        mul : function (out, m1, m2) {
-            // Consider matrix.mul(m, m2, m);
-            // where out is the same as m2.
-            // So use temp variable to escape error.
-            var out0 = m1[0] * m2[0] + m1[2] * m2[1];
-            var out1 = m1[1] * m2[0] + m1[3] * m2[1];
-            var out2 = m1[0] * m2[2] + m1[2] * m2[3];
-            var out3 = m1[1] * m2[2] + m1[3] * m2[3];
-            var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
-            var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
-            out[0] = out0;
-            out[1] = out1;
-            out[2] = out2;
-            out[3] = out3;
-            out[4] = out4;
-            out[5] = out5;
-            return out;
-        },
-        /**
-         * 平移变换
-         * @param {Float32Array|Array.<number>} out
-         * @param {Float32Array|Array.<number>} a
-         * @param {Float32Array|Array.<number>} v
-         */
-        translate : function(out, a, v) {
-            out[0] = a[0];
-            out[1] = a[1];
-            out[2] = a[2];
-            out[3] = a[3];
-            out[4] = a[4] + v[0];
-            out[5] = a[5] + v[1];
-            return out;
-        },
-        /**
-         * 旋转变换
-         * @param {Float32Array|Array.<number>} out
-         * @param {Float32Array|Array.<number>} a
-         * @param {number} rad
-         */
-        rotate : function(out, a, rad) {
-            var aa = a[0];
-            var ac = a[2];
-            var atx = a[4];
-            var ab = a[1];
-            var ad = a[3];
-            var aty = a[5];
-            var st = Math.sin(rad);
-            var ct = Math.cos(rad);
-
-            out[0] = aa * ct + ab * st;
-            out[1] = -aa * st + ab * ct;
-            out[2] = ac * ct + ad * st;
-            out[3] = -ac * st + ct * ad;
-            out[4] = ct * atx + st * aty;
-            out[5] = ct * aty - st * atx;
-            return out;
-        },
-        /**
-         * 缩放变换
-         * @param {Float32Array|Array.<number>} out
-         * @param {Float32Array|Array.<number>} a
-         * @param {Float32Array|Array.<number>} v
-         */
-        scale : function(out, a, v) {
-            var vx = v[0];
-            var vy = v[1];
-            out[0] = a[0] * vx;
-            out[1] = a[1] * vy;
-            out[2] = a[2] * vx;
-            out[3] = a[3] * vy;
-            out[4] = a[4] * vx;
-            out[5] = a[5] * vy;
-            return out;
-        },
-        /**
-         * 求逆矩阵
-         * @param {Float32Array|Array.<number>} out
-         * @param {Float32Array|Array.<number>} a
-         */
-        invert : function(out, a) {
-
-            var aa = a[0];
-            var ac = a[2];
-            var atx = a[4];
-            var ab = a[1];
-            var ad = a[3];
-            var aty = a[5];
-
-            var det = aa * ad - ab * ac;
-            if (!det) {
-                return null;
-            }
-            det = 1.0 / det;
-
-            out[0] = ad * det;
-            out[1] = -ab * det;
-            out[2] = -ac * det;
-            out[3] = aa * det;
-            out[4] = (ac * aty - ad * atx) * det;
-            out[5] = (ab * atx - aa * aty) * det;
-            return out;
-        }
-    };
-
-    return matrix;
-});
-
-/**
- * @module echarts/core/BoundingRect
- */
-define('zrender/core/BoundingRect',['require','./vector','./matrix'],function(require) {
-
-
-    var vec2 = require('./vector');
-    var matrix = require('./matrix');
-
-    var v2ApplyTransform = vec2.applyTransform;
-    var mathMin = Math.min;
-    var mathAbs = Math.abs;
-    var mathMax = Math.max;
-    /**
-     * @alias module:echarts/core/BoundingRect
-     */
-    function BoundingRect(x, y, width, 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 min = [];
-            var max = [];
-            return function (m) {
-                // In case usage like this
-                // el.getBoundingRect().applyTransform(el.transform)
-                // And element has no transform
-                if (!m) {
-                    return;
-                }
-                min[0] = this.x;
-                min[1] = this.y;
-                max[0] = this.x + this.width;
-                max[1] = this.y + this.height;
-
-                v2ApplyTransform(min, min, m);
-                v2ApplyTransform(max, max, m);
-
-                this.x = mathMin(min[0], max[0]);
-                this.y = mathMin(min[1], max[1]);
-                this.width = mathAbs(max[0] - min[0]);
-                this.height = mathAbs(max[1] - min[1]);
-            };
-        })(),
-
-        /**
-         * 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;
-            var sy = b.height / a.height;
-
-            var m = matrix.create();
-
-            // 矩阵右乘
-            matrix.translate(m, m, [-a.x, -a.y]);
-            matrix.scale(m, m, [sx, sy]);
-            matrix.translate(m, m, [b.x, b.y]);
-
-            return m;
-        },
-
-        /**
-         * @param {(module:echarts/core/BoundingRect|Object)} b
-         * @return {boolean}
-         */
-        intersect: function (b) {
-            var a = this;
-            var ax0 = a.x;
-            var ax1 = a.x + a.width;
-            var ay0 = a.y;
-            var ay1 = a.y + a.height;
-
-            var bx0 = b.x;
-            var bx1 = b.x + b.width;
-            var by0 = b.y;
-            var by1 = b.y + b.height;
-
-            return ! (ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
-        },
-
-        contain: function (x, y) {
-            var rect = this;
-            return x >= 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);
-        },
-
-        /**
-         * Copy from another rect
-         */
-        copy: function (other) {
-            this.x = other.x;
-            this.y = other.y;
-            this.width = other.width;
-            this.height = other.height;
-        }
-    };
-
-    return BoundingRect;
-});
-define('zrender/contain/text',['require','../core/util','../core/BoundingRect'],function (require) {
-
-    var textWidthCache = {};
-    var textWidthCacheCounter = 0;
-    var TEXT_CACHE_MAX = 5000;
-
-    var util = require('../core/util');
-    var BoundingRect = require('../core/BoundingRect');
-
-    function getTextWidth(text, textFont) {
-        var key = text + ':' + textFont;
-        if (textWidthCache[key]) {
-            return textWidthCache[key];
-        }
-
-        var textLines = (text + '').split('\n');
-        var width = 0;
-
-        for (var i = 0, l = textLines.length; i < l; i++) {
-            // measureText 可以被覆盖以兼容不支持 Canvas 的环境
-            width =  Math.max(textContain.measureText(textLines[i], textFont).width, width);
-        }
-
-        if (textWidthCacheCounter > TEXT_CACHE_MAX) {
-            textWidthCacheCounter = 0;
-            textWidthCache = {};
-        }
-        textWidthCacheCounter++;
-        textWidthCache[key] = width;
-
-        return width;
-    }
-
-    function getTextRect(text, textFont, textAlign, textBaseline) {
-        var textLineLen = ((text || '') + '').split('\n').length;
-
-        var width = getTextWidth(text, textFont);
-        // FIXME 高度计算比较粗暴
-        var lineHeight = getTextWidth('国', textFont);
-        var height = textLineLen * lineHeight;
-
-        var rect = new BoundingRect(0, 0, width, height);
-        // Text has a special line height property
-        rect.lineHeight = lineHeight;
-
-        switch (textBaseline) {
-            case 'bottom':
-            case 'alphabetic':
-                rect.y -= lineHeight;
-                break;
-            case 'middle':
-                rect.y -= lineHeight / 2;
-                break;
-            // case 'hanging':
-            // case 'top':
-        }
-
-        // FIXME Right to left language
-        switch (textAlign) {
-            case 'end':
-            case 'right':
-                rect.x -= rect.width;
-                break;
-            case 'center':
-                rect.x -= rect.width / 2;
-                break;
-            // case 'start':
-            // case 'left':
-        }
-
-        return rect;
-    }
-
-    function adjustTextPositionOnRect(textPosition, rect, textRect, distance) {
-
-        var x = rect.x;
-        var y = rect.y;
-
-        var height = rect.height;
-        var width = rect.width;
-
-        var textHeight = textRect.height;
-
-        var halfHeight = height / 2 - textHeight / 2;
-
-        var textAlign = 'left';
-
-        switch (textPosition) {
-            case 'left':
-                x -= distance;
-                y += halfHeight;
-                textAlign = 'right';
-                break;
-            case 'right':
-                x += distance + width;
-                y += halfHeight;
-                textAlign = 'left';
-                break;
-            case 'top':
-                x += width / 2;
-                y -= distance + textHeight;
-                textAlign = 'center';
-                break;
-            case 'bottom':
-                x += width / 2;
-                y += height + distance;
-                textAlign = 'center';
-                break;
-            case 'inside':
-                x += width / 2;
-                y += halfHeight;
-                textAlign = 'center';
-                break;
-            case 'insideLeft':
-                x += distance;
-                y += halfHeight;
-                textAlign = 'left';
-                break;
-            case 'insideRight':
-                x += width - distance;
-                y += halfHeight;
-                textAlign = 'right';
-                break;
-            case 'insideTop':
-                x += width / 2;
-                y += distance;
-                textAlign = 'center';
-                break;
-            case 'insideBottom':
-                x += width / 2;
-                y += height - textHeight - distance;
-                textAlign = 'center';
-                break;
-            case 'insideTopLeft':
-                x += distance;
-                y += distance;
-                textAlign = 'left';
-                break;
-            case 'insideTopRight':
-                x += width - distance;
-                y += distance;
-                textAlign = 'right';
-                break;
-            case 'insideBottomLeft':
-                x += distance;
-                y += height - textHeight - distance;
-                break;
-            case 'insideBottomRight':
-                x += width - distance;
-                y += height - textHeight - distance;
-                textAlign = 'right';
-                break;
-        }
-
-        return {
-            x: x,
-            y: y,
-            textAlign: textAlign,
-            textBaseline: 'top'
-        };
-    }
-
-    /**
-     * Show ellipsis if overflow.
-     *
-     * @param  {string} text
-     * @param  {string} textFont
-     * @param  {string} containerWidth
-     * @param  {Object} [options]
-     * @param  {number} [options.ellipsis='...']
-     * @param  {number} [options.maxIterations=3]
-     * @param  {number} [options.minCharacters=3]
-     * @return {string}
-     */
-    function textEllipsis(text, textFont, containerWidth, options) {
-        if (!containerWidth) {
-            return '';
-        }
-
-        options = util.defaults({
-            ellipsis: '...',
-            minCharacters: 3,
-            maxIterations: 3,
-            cnCharWidth: getTextWidth('国', textFont),
-            // FIXME
-            // 未考虑非等宽字体
-            ascCharWidth: getTextWidth('a', textFont)
-        }, options, true);
-
-        containerWidth -= getTextWidth(options.ellipsis);
-
-        var textLines = (text + '').split('\n');
-
-        for (var i = 0, len = textLines.length; i < len; i++) {
-            textLines[i] = textLineTruncate(
-                textLines[i], textFont, containerWidth, options
-            );
-        }
-
-        return textLines.join('\n');
-    }
-
-    function textLineTruncate(text, textFont, containerWidth, options) {
-        // FIXME
-        // 粗糙得写的,尚未考虑性能和各种语言、字体的效果。
-        for (var i = 0;; i++) {
-            var lineWidth = getTextWidth(text, textFont);
-
-            if (lineWidth < containerWidth || i >= options.maxIterations) {
-                text += options.ellipsis;
-                break;
-            }
-
-            var subLength = i === 0
-                ? estimateLength(text, containerWidth, options)
-                : Math.floor(text.length * containerWidth / lineWidth);
-
-            if (subLength < options.minCharacters) {
-                text = '';
-                break;
-            }
-
-            text = text.substr(0, subLength);
-        }
-
-        return text;
-    }
-
-    function estimateLength(text, containerWidth, options) {
-        var width = 0;
-        var i = 0;
-        for (var len = text.length; i < len && width < containerWidth; i++) {
-            var charCode = text.charCodeAt(i);
-            width += (0 <= charCode && charCode <= 127)
-                ? options.ascCharWidth : options.cnCharWidth;
-        }
-        return i;
-    }
-
-    var textContain = {
-
-        getWidth: getTextWidth,
-
-        getBoundingRect: getTextRect,
-
-        adjustTextPositionOnRect: adjustTextPositionOnRect,
-
-        ellipsis: textEllipsis,
-
-        measureText: function (text, textFont) {
-            var ctx = util.getContext();
-            ctx.font = textFont;
-            return ctx.measureText(text);
-        }
-    };
-
-    return textContain;
-});
-define('echarts/model/mixin/textStyle',['require','zrender/contain/text'],function (require) {
-
-    var textContain = require('zrender/contain/text');
-
-    function getShallow(model, path) {
-        return model && model.getShallow(path);
-    }
-
-    return {
-        /**
-         * Get color property or get color from option.textStyle.color
-         * @return {string}
-         */
-        getTextColor: function () {
-            var ecModel = this.ecModel;
-            return this.getShallow('color')
-                || (ecModel && ecModel.get('textStyle.color'));
-        },
-
-        /**
-         * Create font string from fontStyle, fontWeight, fontSize, fontFamily
-         * @return {string}
-         */
-        getFont: function () {
-            var ecModel = this.ecModel;
-            var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
-            return [
-                // FIXME in node-canvas fontWeight is before fontStyle
-                this.getShallow('fontStyle') || getShallow(gTextStyleModel, 'fontStyle'),
-                this.getShallow('fontWeight') || getShallow(gTextStyleModel, 'fontWeight'),
-                (this.getShallow('fontSize') || getShallow(gTextStyleModel, 'fontSize') || 12) + 'px',
-                this.getShallow('fontFamily') || getShallow(gTextStyleModel, 'fontFamily') || 'sans-serif'
-            ].join(' ');
-        },
-
-        getTextRect: function (text) {
-            var textStyle = this.get('textStyle') || {};
-            return textContain.getBoundingRect(
-                text,
-                this.getFont(),
-                textStyle.align,
-                textStyle.baseline
-            );
-        },
-
-        ellipsis: function (text, containerWidth, options) {
-            return textContain.ellipsis(
-                text, this.getFont(), containerWidth, options
-            );
-        }
-    };
-});
-define('echarts/model/mixin/itemStyle',['require','./makeStyleMapper'],function (require) {
-    return {
-        getItemStyle: require('./makeStyleMapper')(
-            [
-                ['fill', 'color'],
-                ['stroke', 'borderColor'],
-                ['lineWidth', 'borderWidth'],
-                ['opacity'],
-                ['shadowBlur'],
-                ['shadowOffsetX'],
-                ['shadowOffsetY'],
-                ['shadowColor']
-            ]
-        )
-    };
-});
-/**
- * @module echarts/model/Model
- */
-define('echarts/model/Model',['require','zrender/core/util','../util/clazz','./mixin/lineStyle','./mixin/areaStyle','./mixin/textStyle','./mixin/itemStyle'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-    var clazzUtil = require('../util/clazz');
-
-    /**
-     * @alias module: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 || null;
-
-        /**
-         * @type {module:echarts/model/Global}
-         * @readOnly
-         */
-        this.ecModel = ecModel || null;
-
-        /**
-         * @type {Object}
-         * @protected
-         */
-        this.option = option;
-
-        this.init.apply(this, arguments);
-    }
-
-    Model.prototype = {
-
-        constructor: Model,
-
-        /**
-         * Model 的初始化函数
-         * @param {Object} option
-         */
-        init: function (option) {},
-
-        /**
-         * 从新的 Option merge
-         */
-        mergeOption: function (option) {
-            zrUtil.merge(this.option, option, true);
-        },
-
-        /**
-         * @param {string} path
-         * @param {boolean} [ignoreParent=false]
-         * @return {*}
-         */
-        get: function (path, ignoreParent) {
-            if (!path) {
-                return this.option;
-            }
-
-            if (typeof path === 'string') {
-                path = path.split('.');
-            }
-
-            var obj = this.option;
-            var parentModel = this.parentModel;
-            for (var i = 0; i < path.length; i++) {
-                // obj could be number/string/... (like 0)
-                obj = (obj && typeof obj === 'object') ? obj[path[i]] : null;
-                if (obj == null) {
-                    break;
-                }
-            }
-            if (obj == null && parentModel && !ignoreParent) {
-                obj = parentModel.get(path);
-            }
-            return obj;
-        },
-
-        /**
-         * @param {string} key
-         * @param {boolean} [ignoreParent=false]
-         * @return {*}
-         */
-        getShallow: function (key, ignoreParent) {
-            var option = this.option;
-            var val = option && option[key];
-            var parentModel = this.parentModel;
-            if (val == null && parentModel && !ignoreParent) {
-                val = parentModel.getShallow(key);
-            }
-            return val;
-        },
-
-        /**
-         * @param {string} path
-         * @param {module:echarts/model/Model} [parentModel]
-         * @return {module:echarts/model/Model}
-         */
-        getModel: function (path, parentModel) {
-            var obj = this.get(path, true);
-            var thisParentModel = this.parentModel;
-            var model = new Model(
-                obj, parentModel || (thisParentModel && thisParentModel.getModel(path)),
-                this.ecModel
-            );
-            return model;
-        },
-
-        /**
-         * If model has option
-         */
-        isEmpty: function () {
-            return this.option == null;
-        },
-
-        restoreData: function () {},
-
-        // Pending
-        clone: function () {
-            var Ctor = this.constructor;
-            return new Ctor(zrUtil.clone(this.option));
-        },
-
-        setReadOnly: function (properties) {
-            clazzUtil.setReadOnly(this, properties);
-        }
-    };
-
-    // Enable Model.extend.
-    clazzUtil.enableClassExtend(Model);
-
-    var mixin = zrUtil.mixin;
-    mixin(Model, require('./mixin/lineStyle'));
-    mixin(Model, require('./mixin/areaStyle'));
-    mixin(Model, require('./mixin/textStyle'));
-    mixin(Model, require('./mixin/itemStyle'));
-
-    return Model;
-});
-define('echarts/util/component',['require','zrender/core/util','./clazz'],function(require) {
-
-    var zrUtil = require('zrender/core/util');
-    var clazz = require('./clazz');
-
-    var parseClassType = clazz.parseClassType;
-
-    var base = 0;
-
-    var componentUtil = {};
-
-    var DELIMITER = '_';
-
-    /**
-     * @public
-     * @param {string} type
-     * @return {string}
-     */
-    componentUtil.getUID = function (type) {
-        // Considering the case of crossing js context,
-        // use Math.random to make id as unique as possible.
-        return [(type || ''), base++, Math.random()].join(DELIMITER);
-    };
-
-    /**
-     * @inner
-     */
-    componentUtil.enableSubTypeDefaulter = function (entity) {
-
-        var subTypeDefaulters = {};
-
-        entity.registerSubTypeDefaulter = function (componentType, defaulter) {
-            componentType = parseClassType(componentType);
-            subTypeDefaulters[componentType.main] = defaulter;
-        };
-
-        entity.determineSubType = function (componentType, option) {
-            var type = option.type;
-            if (!type) {
-                var componentTypeMain = parseClassType(componentType).main;
-                if (entity.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) {
-                    type = subTypeDefaulters[componentTypeMain](option);
-                }
-            }
-            return type;
-        };
-
-        return entity;
-    };
-
-    /**
-     * 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.
-     *
-     */
-    componentUtil.enableTopologicalTravel = function (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;
-            }
-
-            var result = makeDepndencyGraph(fullNameList);
-            var graph = result.graph;
-            var stack = result.noEntryList;
-
-            var targetNameSet = {};
-            zrUtil.each(targetNameList, function (name) {
-                targetNameSet[name] = true;
-            });
-
-            while (stack.length) {
-                var currComponentType = stack.pop();
-                var currVertex = graph[currComponentType];
-                var isInTargetNameSet = !!targetNameSet[currComponentType];
-                if (isInTargetNameSet) {
-                    callback.call(context, currComponentType, currVertex.originalDeps.slice());
-                    delete targetNameSet[currComponentType];
-                }
-                zrUtil.each(
-                    currVertex.successor,
-                    isInTargetNameSet ? removeEdgeAndAdd : removeEdge
-                );
-            }
-
-            zrUtil.each(targetNameSet, function () {
-                throw new Error('Circle dependency may exists');
-            });
-
-            function removeEdge(succComponentType) {
-                graph[succComponentType].entryCount--;
-                if (graph[succComponentType].entryCount === 0) {
-                    stack.push(succComponentType);
-                }
-            }
-
-            // Consider this case: legend depends series, 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).
-            function removeEdgeAndAdd(succComponentType) {
-                targetNameSet[succComponentType] = true;
-                removeEdge(succComponentType);
-            }
-        };
-
-        /**
-         * DepndencyGraph: {Object}
-         * key: conponentType,
-         * value: {
-         *     successor: [conponentTypes...],
-         *     originalDeps: [conponentTypes...],
-         *     entryCount: {number}
-         * }
-         */
-        function makeDepndencyGraph(fullNameList) {
-            var graph = {};
-            var noEntryList = [];
-
-            zrUtil.each(fullNameList, function (name) {
-
-                var thisItem = createDependencyGraphItem(graph, name);
-                var originalDeps = thisItem.originalDeps = dependencyGetter(name);
-
-                var availableDeps = getAvailableDependencies(originalDeps, fullNameList);
-                thisItem.entryCount = availableDeps.length;
-                if (thisItem.entryCount === 0) {
-                    noEntryList.push(name);
-                }
-
-                zrUtil.each(availableDeps, function (dependentName) {
-                    if (zrUtil.indexOf(thisItem.predecessor, dependentName) < 0) {
-                        thisItem.predecessor.push(dependentName);
-                    }
-                    var thatItem = createDependencyGraphItem(graph, dependentName);
-                    if (zrUtil.indexOf(thatItem.successor, dependentName) < 0) {
-                        thatItem.successor.push(name);
-                    }
-                });
-            });
-
-            return {graph: graph, noEntryList: noEntryList};
-        }
-
-        function createDependencyGraphItem(graph, name) {
-            if (!graph[name]) {
-                graph[name] = {predecessor: [], successor: []};
-            }
-            return graph[name];
-        }
-
-        function getAvailableDependencies(originalDeps, fullNameList) {
-            var availableDeps = [];
-            zrUtil.each(originalDeps, function (dep) {
-                zrUtil.indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep);
-            });
-            return availableDeps;
-        }
-    };
-
-    return componentUtil;
-});
-/**
- * 数值处理模块
- * @module echarts/util/number
- */
-
-define('echarts/util/number',['require','zrender/core/util'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-    var number = {};
-
-    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>} domain Domain extent domain[0] can be bigger than domain[1]
-     * @param  {Array.<number>} range  Range extent range[0] can be bigger than range[1]
-     * @param  {boolean} clamp
-     * @return {(number|Array.<number>}
-     */
-    number.linearMap = function (val, domain, range, clamp) {
-
-        if (zrUtil.isArray(val)) {
-            return zrUtil.map(val, function (v) {
-                return number.linearMap(v, domain, range, clamp);
-            });
-        }
-
-        var sub = domain[1] - domain[0];
-
-        if (sub === 0) {
-            return (range[0] + range[1]) / 2;
-        }
-        var t = (val - domain[0]) / sub;
-
-        if (clamp) {
-            t = Math.min(Math.max(t, 0), 1);
-        }
-
-        return t * (range[1] - range[0]) + 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}
-     */
-    number.parsePercent = function(percent, all) {
-        switch (percent) {
-            case 'center':
-            case 'middle':
-                percent = '50%';
-                break;
-            case 'left':
-            case 'top':
-                percent = '0%';
-                break;
-            case 'right':
-            case 'bottom':
-                percent = '100%';
-                break;
-        }
-        if (typeof percent === 'string') {
-            if (_trim(percent).match(/%$/)) {
-                return parseFloat(percent) / 100 * all;
-            }
-
-            return parseFloat(percent);
-        }
-
-        return percent == null ? NaN : +percent;
-    };
-
-    /**
-     * Fix rounding error of float numbers
-     * @param {number} x
-     * @return {number}
-     */
-    number.round = function (x) {
-        // PENDING
-        return +(+x).toFixed(12);
-    };
-
-    number.asc = function (arr) {
-        arr.sort(function (a, b) {
-            return a - b;
-        });
-        return arr;
-    };
-
-    /**
-     * Get precision
-     * @param {number} val
-     */
-    number.getPrecision = function (val) {
-        // It is much faster than methods converting number to string as follows
-        //      var tmp = val.toString();
-        //      return tmp.length - 1 - tmp.indexOf('.');
-        // especially when precision is low
-        var e = 1;
-        var count = 0;
-        while (Math.round(val * e) / e !== val) {
-            e *= 10;
-            count++;
-        }
-        return count;
-    };
-
-    /**
-     * @param {Array.<number>} dataExtent
-     * @param {Array.<number>} pixelExtent
-     * @return {number}  precision
-     */
-    number.getPixelPrecision = function (dataExtent, pixelExtent) {
-        var log = Math.log;
-        var LN10 = Math.LN10;
-        var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
-        var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10);
-        return Math.max(
-            -dataQuantity + sizeQuantity,
-            0
-        );
-    };
-
-    // Number.MAX_SAFE_INTEGER, ie do not support.
-    number.MAX_SAFE_INTEGER = 9007199254740991;
-
-    /**
-     * To 0 - 2 * PI, considering negative radian.
-     * @param {number} radian
-     * @return {number}
-     */
-    number.remRadian = function (radian) {
-        var pi2 = Math.PI * 2;
-        return (radian % pi2 + pi2) % pi2;
-    };
-
-    /**
-     * @param {type} radian
-     * @return {boolean}
-     */
-    number.isRadianAroundZero = function (val) {
-        return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
-    };
-
-    /**
-     * @param {string|Date|number} value
-     * @return {number} timestamp
-     */
-    number.parseDate = function (value) {
-        return value instanceof Date
-            ? value
-            : new Date(typeof value === 'string' ? value.replace(/-/g, '/') : value);
-    };
-
-    return number;
-});
-define('echarts/util/format',['require','zrender/core/util'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-    /**
-     * 每三位默认加,格式化
-     * @type {string|number} x
-     */
-    function addCommas(x) {
-        if (isNaN(x)) {
-            return '-';
-        }
-        x = (x + '').split('.');
-        return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,'$1,')
-               + (x.length > 1 ? ('.' + x[1]) : '');
-    }
-
-    /**
-     * @param {string} str
-     * @return {string} str
-     */
-    function toCamelCase(str) {
-        return str.toLowerCase().replace(/-(.)/g, function(match, group1) {
-            return group1.toUpperCase();
-        });
-    }
-
-    /**
-     * Normalize css liked array configuration
-     * 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
-     */
-    function normalizeCssArray(val) {
-        var len = val.length;
-        if (typeof (val) === 'number') {
-            return [val, val, val, val];
-        }
-        else if (len === 2) {
-            // vertical | horizontal
-            return [val[0], val[1], val[0], val[1]];
-        }
-        else if (len === 3) {
-            // top | horizontal | bottom
-            return [val[0], val[1], val[2], val[1]];
-        }
-        return val;
-    }
-
-    function encodeHTML(source) {
-        return String(source)
-            .replace(/&/g, '&amp;')
-            .replace(/</g, '&lt;')
-            .replace(/>/g, '&gt;')
-            .replace(/"/g, '&quot;')
-            .replace(/'/g, '&#39;');
-    }
-
-    var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
-
-    function wrapVar(varName, seriesIdx) {
-        return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
-    }
-    /**
-     * Template formatter
-     * @param  {string} tpl
-     * @param  {Array.<Object>|Object} paramsList
-     * @return {string}
-     */
-    function formatTpl(tpl, paramsList) {
-        if (!zrUtil.isArray(paramsList)) {
-            paramsList = [paramsList];
-        }
-        var seriesLen = paramsList.length;
-        if (!seriesLen) {
-            return '';
-        }
-
-        var $vars = paramsList[0].$vars;
-        for (var i = 0; i < $vars.length; i++) {
-            var alias = TPL_VAR_ALIAS[i];
-            tpl = tpl.replace(wrapVar(alias),  wrapVar(alias, 0));
-        }
-        for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
-            for (var k = 0; k < $vars.length; k++) {
-                tpl = tpl.replace(
-                    wrapVar(TPL_VAR_ALIAS[k], seriesIdx),
-                    paramsList[seriesIdx][$vars[k]]
-                );
-            }
-        }
-
-        return tpl;
-    }
-
-    return {
-
-        normalizeCssArray: normalizeCssArray,
-
-        addCommas: addCommas,
-
-        toCamelCase: toCamelCase,
-
-        encodeHTML: encodeHTML,
-
-        formatTpl: formatTpl
-    };
-});
-// Layout helpers for each component positioning
-define('echarts/util/layout',['require','zrender/core/util','zrender/core/BoundingRect','./number','./format'],function(require) {
-
-
-    var zrUtil = require('zrender/core/util');
-    var BoundingRect = require('zrender/core/BoundingRect');
-    var numberUtil = require('./number');
-    var formatUtil = require('./format');
-    var parsePercent = numberUtil.parsePercent;
-    var each = zrUtil.each;
-
-    var layout = {};
-
-    function boxLayout(orient, group, gap, maxWidth, maxHeight) {
-        var x = 0;
-        var y = 0;
-        if (maxWidth == null) {
-            maxWidth = Infinity;
-        }
-        if (maxHeight == null) {
-            maxHeight = Infinity;
-        }
-        var currentLineMaxSize = 0;
-        group.eachChild(function (child, idx) {
-            var position = child.position;
-            var rect = child.getBoundingRect();
-            var nextChild = group.childAt(idx + 1);
-            var nextChildRect = nextChild && nextChild.getBoundingRect();
-            var nextX;
-            var nextY;
-            if (orient === 'horizontal') {
-                var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0);
-                nextX = x + moveX;
-                // Wrap when width exceeds maxWidth or meet a `newline` group
-                if (nextX > maxWidth || child.newline) {
-                    x = 0;
-                    nextX = moveX;
-                    y += currentLineMaxSize + gap;
-                    currentLineMaxSize = 0;
-                }
-                else {
-                    currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
-                }
-            }
-            else {
-                var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);
-                nextY = y + moveY;
-                // Wrap when width exceeds maxHeight or meet a `newline` group
-                if (nextY > maxHeight || child.newline) {
-                    x += currentLineMaxSize + gap;
-                    y = 0;
-                    nextY = moveY;
-                    currentLineMaxSize = 0;
-                }
-                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]
-     */
-    layout.box = boxLayout;
-
-    /**
-     * VBox layouting
-     * @param {module:zrender/container/Group} group
-     * @param {number} gap
-     * @param {number} [width=Infinity]
-     * @param {number} [height=Infinity]
-     */
-    layout.vbox = zrUtil.curry(boxLayout, 'vertical');
-
-    /**
-     * HBox layouting
-     * @param {module:zrender/container/Group} group
-     * @param {number} gap
-     * @param {number} [width=Infinity]
-     * @param {number} [height=Infinity]
-     */
-    layout.hbox = zrUtil.curry(boxLayout, 'horizontal');
-
-    /**
-     * If x or x2 is not specified or 'center' 'left' 'right',
-     * the width would be as long as possible.
-     * If y or y2 is not specified or 'middle' 'top' 'bottom',
-     * the height would be as long as possible.
-     *
-     * @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
-     * @param {string|number} margin
-     * @return {Object} {width, height}
-     */
-    layout.getAvailableSize = function (positionInfo, containerRect, margin) {
-        var containerWidth = containerRect.width;
-        var containerHeight = containerRect.height;
-
-        var x = parsePercent(positionInfo.x, containerWidth);
-        var y = parsePercent(positionInfo.y, containerHeight);
-        var x2 = parsePercent(positionInfo.x2, containerWidth);
-        var y2 = parsePercent(positionInfo.y2, containerHeight);
-
-        (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0);
-        (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth);
-        (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0);
-        (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight);
-
-        margin = formatUtil.normalizeCssArray(margin || 0);
-
-        return {
-            width: Math.max(x2 - x - margin[1] - margin[3], 0),
-            height: Math.max(y2 - y - margin[0] - margin[2], 0)
-        };
-    };
-
-    /**
-     * Parse position info.
-     *
-     * @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] Aspect is width / height
-     * @param {Object} containerRect
-     * @param {string|number} [margin]
-     *
-     * @return {module:zrender/core/BoundingRect}
-     */
-    layout.getLayoutRect = function (
-        positionInfo, containerRect, margin
-    ) {
-        margin = formatUtil.normalizeCssArray(margin || 0);
-
-        var containerWidth = containerRect.width;
-        var containerHeight = containerRect.height;
-
-        var left = parsePercent(positionInfo.left, containerWidth);
-        var top = parsePercent(positionInfo.top, containerHeight);
-        var right = parsePercent(positionInfo.right, containerWidth);
-        var bottom = parsePercent(positionInfo.bottom, containerHeight);
-        var width = parsePercent(positionInfo.width, containerWidth);
-        var height = parsePercent(positionInfo.height, containerHeight);
-
-        var verticalMargin = margin[2] + margin[0];
-        var horizontalMargin = margin[1] + margin[3];
-        var aspect = positionInfo.aspect;
-
-        // If width is not specified, calculate width from left and right
-        if (isNaN(width)) {
-            width = containerWidth - right - horizontalMargin - left;
-        }
-        if (isNaN(height)) {
-            height = containerHeight - bottom - verticalMargin - top;
-        }
-
-        // 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
-        if (isNaN(width) && isNaN(height)) {
-            if (aspect > containerWidth / containerHeight) {
-                width = containerWidth * 0.8;
-            }
-            else {
-                height = containerHeight * 0.8;
-            }
-        }
-
-        if (aspect != null) {
-            // Calculate width or height with given aspect
-            if (isNaN(width)) {
-                width = aspect * height;
-            }
-            if (isNaN(height)) {
-                height = width / aspect;
-            }
-        }
-
-        // If left is not specified, calculate left from right and width
-        if (isNaN(left)) {
-            left = containerWidth - right - width - horizontalMargin;
-        }
-        if (isNaN(top)) {
-            top = containerHeight - bottom - height - verticalMargin;
-        }
-
-        // Align left and top
-        switch (positionInfo.left || positionInfo.right) {
-            case 'center':
-                left = containerWidth / 2 - width / 2 - margin[3];
-                break;
-            case 'right':
-                left = containerWidth - width - horizontalMargin;
-                break;
-        }
-        switch (positionInfo.top || positionInfo.bottom) {
-            case 'middle':
-            case 'center':
-                top = containerHeight / 2 - height / 2 - margin[0];
-                break;
-            case 'bottom':
-                top = containerHeight - height - verticalMargin;
-                break;
-        }
-
-        var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
-        rect.margin = margin;
-        return rect;
-    };
-
-    /**
-     * Position group of component in viewport
-     *  Group position is specified by either
-     *  {left, top}, {right, bottom}
-     *  If all properties exists, right and bottom will be igonred.
-     *
-     * @param {module:zrender/container/Group} group
-     * @param {Object} positionInfo
-     * @param {number|string} [positionInfo.left]
-     * @param {number|string} [positionInfo.top]
-     * @param {number|string} [positionInfo.right]
-     * @param {number|string} [positionInfo.bottom]
-     * @param {Object} containerRect
-     * @param {string|number} margin
-     */
-    layout.positionGroup = function (
-        group, positionInfo, containerRect, margin
-    ) {
-        var groupRect = group.getBoundingRect();
-
-        positionInfo = zrUtil.extend(zrUtil.clone(positionInfo), {
-            width: groupRect.width,
-            height: groupRect.height
-        });
-
-        positionInfo = layout.getLayoutRect(
-            positionInfo, containerRect, margin
-        );
-
-        group.position = [
-            positionInfo.x - groupRect.x,
-            positionInfo.y - groupRect.y
-        ];
-    };
-
-    /**
-     * Consider Case:
-     * When defulat option has {left: 0, width: 100}, and we set {right: 0}
-     * through setOption or media query, using normal zrUtil.merge will cause
-     * {right: 0} does not take effect.
-     *
-     * @example
-     * ComponentModel.extend({
-     *     init: function () {
-     *         ...
-     *         var inputPositionParams = 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} [opt]
-     * @param {boolean} [opt.ignoreSize=false] Some component must has width and height.
-     */
-    layout.mergeLayoutParam = function (targetOption, newOption, opt) {
-        opt = opt || {};
-        var hNames = ['width', 'left', 'right']; // Order by priority.
-        var vNames = ['height', 'top', 'bottom']; // Order by priority.
-        var hResult = merge(hNames);
-        var vResult = merge(vNames);
-
-        copy(hNames, targetOption, hResult);
-        copy(vNames, targetOption, vResult);
-
-        function merge(names) {
-            var newParams = {};
-            var newValueCount = 0;
-            var merged = {};
-            var mergedValueCount = 0;
-            var enoughParamNumber = opt.ignoreSize ? 1 : 2;
-
-            each(names, function (name) {
-                merged[name] = targetOption[name];
-            });
-            each(names, function (name) {
-                // Consider case: newOption.width is null, which is
-                // set by user for removing width setting.
-                hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
-                hasValue(newParams, name) && newValueCount++;
-                hasValue(merged, name) && mergedValueCount++;
-            });
-
-            // 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) {
-                return merged;
-            }
-            else if (mergedValueCount < enoughParamNumber) {
-                // In common way, 'auto' means auto calculate by left/right
-                // or top/bottom. But Some components may auto calculate by
-                // other way (like dataZoom auto by coordnate system). In
-                // that case we can set defualtOption 'auto', and if
-                // mergedValueCount litter than enoughParamNumber, 'auto'
-                // will filtered by priority and returned.
-                var autoCount = 0;
-                each(names, function (name) {
-                    if (merged[name] === 'auto') {
-                        autoCount < enoughParamNumber - mergedValueCount
-                            ? autoCount++
-                            : (merged[name] = null);
-                    }
-                });
-                return merged;
-            }
-            // Case: newOption: {width: ..., right: ...},
-            // Than we can make sure user only want those two, and ignore
-            // all origin params in targetOption.
-            else if (newValueCount >= enoughParamNumber) {
-                return newParams;
-            }
-            else {
-                // Chose another param from targetOption by priority.
-                // When 'ignoreSize', enoughParamNumber is 1 and those will not happen.
-                for (var i = 0; i < names.length; i++) {
-                    var name = names[i];
-                    if (!hasProp(newParams, name) && hasProp(targetOption, name)) {
-                        newParams[name] = targetOption[name];
-                        break;
-                    }
-                }
-                return newParams;
-            }
-        }
-
-        function hasProp(obj, name) {
-            return obj.hasOwnProperty(name);
-        }
-
-        function hasValue(obj, name) {
-            return obj[name] != null && obj[name] !== 'auto';
-        }
-
-        function copy(names, target, source) {
-            each(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.
-     */
-    layout.getLayoutParams = function (source) {
-        var params = {};
-        source && each(
-            ['left', 'right', 'top', 'bottom', 'width', 'height'],
-            function (name) {
-                source.hasOwnProperty(name) && (params[name] = source[name]);
-            }
-        );
-        return params;
-    };
-
-    return layout;
-});
-define('echarts/model/mixin/boxLayout',['require'],function (require) {
-
-    return {
-        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')
-            };
-        }
-    };
-});
-/**
- * Component model
- *
- * @module echarts/model/Component
- */
-define('echarts/model/Component',['require','./Model','zrender/core/util','../util/component','../util/clazz','../util/layout','./mixin/boxLayout'],function(require) {
-
-    var Model = require('./Model');
-    var zrUtil = require('zrender/core/util');
-    var arrayPush = Array.prototype.push;
-    var componentUtil = require('../util/component');
-    var clazzUtil = require('../util/clazz');
-    var layout = require('../util/layout');
-
-    /**
-     * @alias module: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: '',
-
-        /**
-         * @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:  Component model list, can not be null.
-         * @type {Object.<string, Array.<module:echarts/model/Model>>}
-         * @readOnly
-         */
-        dependentModels: [],
-
-        /**
-         * @type {string}
-         * @readOnly
-         */
-        uid: null,
-
-        /**
-         * Support merge layout params.
-         * Only support 'box' now (left/right/top/bottom/width/height).
-         * @type {string|Object} Object can be {ignoreSize: true}
-         * @readOnly
-         */
-        layoutMode: null,
-
-
-        init: function (option, parentModel, ecModel, extraOpt) {
-            this.mergeDefaultAndTheme(this.option, this.ecModel);
-        },
-
-        mergeDefaultAndTheme: function (option, ecModel) {
-            var layoutMode = this.layoutMode;
-            var inputPositionParams = layoutMode
-                ? layout.getLayoutParams(option) : {};
-
-            var themeModel = ecModel.getTheme();
-            zrUtil.merge(option, themeModel.get(this.mainType));
-            zrUtil.merge(option, this.getDefaultOption());
-
-            if (layoutMode) {
-                layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
-            }
-        },
-
-        mergeOption: function (option) {
-            zrUtil.merge(this.option, option, true);
-
-            var layoutMode = this.layoutMode;
-            if (layoutMode) {
-                layout.mergeLayoutParam(this.option, option, layoutMode);
-            }
-        },
-
-        getDefaultOption: function () {
-            if (!this.hasOwnProperty('__defaultOption')) {
-                var optList = [];
-                var Class = this.constructor;
-                while (Class) {
-                    var opt = Class.prototype.defaultOption;
-                    opt && optList.push(opt);
-                    Class = Class.superClass;
-                }
-
-                var defaultOption = {};
-                for (var i = optList.length - 1; i >= 0; i--) {
-                    defaultOption = zrUtil.merge(defaultOption, optList[i], true);
-                }
-                this.__defaultOption = defaultOption;
-            }
-            return this.__defaultOption;
-        }
-
-    });
-
-    // 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.
-    clazzUtil.enableClassManagement(
-        ComponentModel, {registerWhenExtend: true}
-    );
-    componentUtil.enableSubTypeDefaulter(ComponentModel);
-
-    // Add capability of ComponentModel.topologicalTravel.
-    componentUtil.enableTopologicalTravel(ComponentModel, getDependencies);
-
-    function getDependencies(componentType) {
-        var deps = [];
-        zrUtil.each(ComponentModel.getClassesByMainType(componentType), function (Clazz) {
-            arrayPush.apply(deps, Clazz.prototype.dependencies || []);
-        });
-        // Ensure main type
-        return zrUtil.map(deps, function (type) {
-            return clazzUtil.parseClassType(type).main;
-        });
-    }
-
-    zrUtil.mixin(ComponentModel, require('./mixin/boxLayout'));
-
-    return ComponentModel;
-});
-define('echarts/model/globalDefault',[],function () {
-    var platform = '';
-    // Navigator not exists in node
-    if (typeof navigator !== 'undefined') {
-        platform = navigator.platform || '';
-    }
-    return {
-        // 全图默认背景
-        // backgroundColor: 'rgba(0,0,0,0)',
-
-        // https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization
-        // color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],
-        // 浅色
-        // color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],
-        // color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],
-        // 深色
-        color: ['#c23531', '#314656', '#61a0a8', '#dd8668', '#91c7ae', '#6e7074', '#61a0a8', '#bda29a', '#44525d', '#c4ccd3'],
-
-        // 默认需要 Grid 配置项
-        grid: {},
-        // 主题,主题
-        textStyle: {
-            // color: '#000',
-            // decoration: 'none',
-            // PENDING
-            fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
-            // fontFamily: 'Arial, Verdana, sans-serif',
-            fontSize: 12,
-            fontStyle: 'normal',
-            fontWeight: 'normal'
-        },
-        // 主题,默认标志图形类型列表
-        // symbolList: [
-        //     'circle', 'rectangle', 'triangle', 'diamond',
-        //     'emptyCircle', 'emptyRectangle', 'emptyTriangle', 'emptyDiamond'
-        // ],
-        animation: true,                // 过渡动画是否开启
-        animationThreshold: 2000,       // 动画元素阀值,产生的图形原素超过2000不出动画
-        animationDuration: 1000,        // 过渡动画参数:进入
-        animationDurationUpdate: 300,   // 过渡动画参数:更新
-        animationEasing: 'exponentialOut',    //BounceOut
-        animationEasingUpdate: 'cubicOut'
-    };
-});
-/**
- * ECharts global model
- *
- * @module {echarts/model/Global}
- *
- */
-
-define('echarts/model/Global',['require','zrender/core/util','./Model','./Component','./globalDefault'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-    var Model = require('./Model');
-    var each = zrUtil.each;
-    var filter = zrUtil.filter;
-    var map = zrUtil.map;
-    var isArray = zrUtil.isArray;
-    var indexOf = zrUtil.indexOf;
-    var isObject = zrUtil.isObject;
-
-    var ComponentModel = require('./Component');
-
-    var globalDefault = require('./globalDefault');
-
-    /**
-     * @alias module:echarts/model/Global
-     *
-     * @param {Object} option
-     * @param {module:echarts/model/Model} parentModel
-     * @param {Object} theme
-     */
-    var GlobalModel = Model.extend({
-
-        constructor: GlobalModel,
-
-        init: function (option, parentModel, theme, optionManager) {
-            theme = theme || {};
-
-            this.option = null; // Mark as not initialized.
-
-            /**
-             * @type {module:echarts/model/Model}
-             * @private
-             */
-            this._theme = new Model(theme);
-
-            /**
-             * @type {module:echarts/model/OptionManager}
-             */
-            this._optionManager = optionManager;
-        },
-
-        setOption: function (option, optionPreprocessorFuncs) {
-            this._optionManager.setOption(option, optionPreprocessorFuncs);
-
-            this.resetOption();
-        },
-
-        /**
-         * @param {string} type null/undefined: reset all.
-         *                      'recreate': force recreate all.
-         *                      'timeline': only reset timeline option
-         *                      'media': only reset media query option
-         * @return {boolean} Whether option changed.
-         */
-        resetOption: function (type) {
-            var optionChanged = false;
-            var optionManager = this._optionManager;
-
-            if (!type || type === 'recreate') {
-                var baseOption = optionManager.mountOption();
-
-                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(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 = [];
-
-            // 如果不存在对应的 component model 则直接 merge
-            each(newOption, function (componentOption, mainType) {
-                if (componentOption == null) {
-                    return;
-                }
-
-                if (!ComponentModel.hasClass(mainType)) {
-                    option[mainType] = option[mainType] == null
-                        ? zrUtil.clone(componentOption)
-                        : zrUtil.merge(option[mainType], componentOption, true);
-                }
-                else {
-                    newCptTypes.push(mainType);
-                }
-            });
-
-            // FIXME OPTION 同步是否要改回原来的
-            ComponentModel.topologicalTravel(
-                newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this
-            );
-
-            function visitComponent(mainType, dependencies) {
-                var newCptOptionList = newOption[mainType];
-
-                newCptOptionList
-                    ? handleNew.call(this, mainType, newCptOptionList, dependencies)
-                    : handleNoNew.call(this, mainType);
-
-                // Backup series for filtering.
-                if (mainType === 'series') {
-                    this._seriesIndices = createSeriesIndices(componentsMap.series);
-                }
-            }
-
-            function handleNoNew(mainType) {
-                // Possible when using removeEdgeAndAdd in topologicalTravel
-                // and ComponentModel.getAllClassMainTypes
-                each(componentsMap[mainType], function (cpt) {
-                    cpt.mergeOption({}, this);
-                }, this);
-            }
-
-            function handleNew(mainType, newCptOptionList, dependencies) {
-                // Normalize
-                if (!(zrUtil.isArray(newCptOptionList))) {
-                    newCptOptionList = [newCptOptionList];
-                }
-                if (!componentsMap[mainType]) {
-                    componentsMap[mainType] = [];
-                }
-
-                var existComponents = mappingToExists(
-                    componentsMap[mainType], newCptOptionList
-                );
-
-                var keyInfoList = makeKeyInfo(
-                    mainType, newCptOptionList, existComponents
-                );
-
-                var dependentModels = getComponentsByTypes(
-                    componentsMap, dependencies
-                );
-
-                option[mainType] = [];
-
-                each(newCptOptionList, function (newCptOption, index) {
-                    if (!isObject(newCptOption)) {
-                        return;
-                    }
-
-                    var componentModel = existComponents[index];
-
-                    var ComponentModelClass = ComponentModel.getClass(
-                        mainType, keyInfoList[index].subType, true
-                    );
-
-                    if (componentModel && componentModel instanceof ComponentModelClass) {
-                        componentModel.mergeOption(newCptOption, this);
-                    }
-                    else {
-                        // PENDING Global as parent ?
-                        componentModel = new ComponentModelClass(
-                            newCptOption, this, this,
-                            zrUtil.extend(
-                                {
-                                    dependentModels: dependentModels,
-                                    componentIndex: index
-                                },
-                                keyInfoList[index]
-                            )
-                        );
-                        componentsMap[mainType][index] = componentModel;
-                    }
-
-                    // Keep option
-                    option[mainType][index] = componentModel.option;
-                }, this);
-            }
-        },
-
-        /**
-         * @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[mainType];
-            if (list) {
-                return list[idx || 0];
-            }
-        },
-
-        /**
-         * @param {Object} condition
-         * @param {string} condition.mainType
-         * @param {string} [condition.subType] If ignore, only query by mainType
-         * @param {number} [condition.index] Either input index or id or name.
-         * @param {string} [condition.id] Either input index or id or name.
-         * @param {string} [condition.name] Either input index or id or name.
-         * @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[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);
-                });
-            }
-
-            return filterBySubType(result, condition);
-        },
-
-        /**
-         * The interface is different from queryComponents,
-         * which is convenient for inner usage.
-         *
-         * @usage
-         * findComponents(
-         *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}},
-         *     function (model, index) {...}
-         * );
-         *
-         * findComponents(
-         *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}},
-         *     function (model, index) {...}
-         * );
-         *
-         * var result = findComponents(
-         *     {mainType: 'series'},
-         *     function (model, index) {...}
-         * );
-         * // result like [component0, componnet1, ...]
-         *
-         * @param {Object} condition
-         * @param {string} condition.mainType Mandatory.
-         * @param {string} [condition.subType] Optional.
-         * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName},
-         *        where xxx is mainType.
-         *        If query attribute is null/undefined or has no index/id/name,
-         *        do not filtering by query conditions, which is convenient for
-         *        no-payload situations or when target of action is global.
-         * @param {Function} [condition.filter] parameter: component, return boolean.
-         * @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[mainType];
-
-            return doFilter(filterBySubType(result, condition));
-
-            function getQueryCond(q) {
-                var indexAttr = mainType + 'Index';
-                var idAttr = mainType + 'Id';
-                var nameAttr = mainType + 'Name';
-                return q && (
-                        q.hasOwnProperty(indexAttr)
-                        || q.hasOwnProperty(idAttr)
-                        || q.hasOwnProperty(nameAttr)
-                    )
-                    ? {
-                        mainType: mainType,
-                        // subType will be filtered finally.
-                        index: q[indexAttr],
-                        id: q[idAttr],
-                        name: q[nameAttr]
-                    }
-                    : null;
-            }
-
-            function doFilter(res) {
-                return condition.filter
-                     ? filter(res, condition.filter)
-                     : res;
-            }
-        },
-
-        /**
-         * @usage
-         * eachComponent('legend', function (legendModel, index) {
-         *     ...
-         * });
-         * eachComponent(function (componentType, model, index) {
-         *     // componentType does not include subType
-         *     // (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=} mainType When mainType is object, the definition
-         *                                  is the same as the method 'findComponents'.
-         * @param {Function} cb
-         * @param {*} context
-         */
-        eachComponent: function (mainType, cb, context) {
-            var componentsMap = this._componentsMap;
-
-            if (typeof mainType === 'function') {
-                context = cb;
-                cb = mainType;
-                each(componentsMap, function (components, componentType) {
-                    each(components, function (component, index) {
-                        cb.call(context, componentType, component, index);
-                    });
-                });
-            }
-            else if (zrUtil.isString(mainType)) {
-                each(componentsMap[mainType], cb, context);
-            }
-            else if (isObject(mainType)) {
-                var queryResult = this.findComponents(mainType);
-                each(queryResult, cb, context);
-            }
-        },
-
-        /**
-         * @param {string} name
-         * @return {Array.<module:echarts/model/Series>}
-         */
-        getSeriesByName: function (name) {
-            var series = this._componentsMap.series;
-            return filter(series, function (oneSeries) {
-                return oneSeries.name === name;
-            });
-        },
-
-        /**
-         * @param {number} seriesIndex
-         * @return {module:echarts/model/Series}
-         */
-        getSeriesByIndex: function (seriesIndex) {
-            return this._componentsMap.series[seriesIndex];
-        },
-
-        /**
-         * @param {string} subType
-         * @return {Array.<module:echarts/model/Series>}
-         */
-        getSeriesByType: function (subType) {
-            var series = this._componentsMap.series;
-            return filter(series, function (oneSeries) {
-                return oneSeries.subType === subType;
-            });
-        },
-
-        /**
-         * @return {Array.<module:echarts/model/Series>}
-         */
-        getSeries: function () {
-            return this._componentsMap.series.slice();
-        },
-
-        /**
-         * After filtering, series may be different
-         * frome raw series.
-         *
-         * @param {Function} cb
-         * @param {*} context
-         */
-        eachSeries: function (cb, context) {
-            assertSeriesInitialized(this);
-            each(this._seriesIndices, function (rawSeriesIndex) {
-                var series = this._componentsMap.series[rawSeriesIndex];
-                cb.call(context, series, rawSeriesIndex);
-            }, this);
-        },
-
-        /**
-         * Iterate raw series before filtered.
-         *
-         * @param {Function} cb
-         * @param {*} context
-         */
-        eachRawSeries: function (cb, context) {
-            each(this._componentsMap.series, cb, context);
-        },
-
-        /**
-         * After filtering, series may be different.
-         * frome raw series.
-         *
-         * @parma {string} subType
-         * @param {Function} cb
-         * @param {*} context
-         */
-        eachSeriesByType: function (subType, cb, context) {
-            assertSeriesInitialized(this);
-            each(this._seriesIndices, function (rawSeriesIndex) {
-                var series = this._componentsMap.series[rawSeriesIndex];
-                if (series.subType === subType) {
-                    cb.call(context, series, rawSeriesIndex);
-                }
-            }, this);
-        },
-
-        /**
-         * Iterate raw series before filtered of given type.
-         *
-         * @parma {string} subType
-         * @param {Function} cb
-         * @param {*} context
-         */
-        eachRawSeriesByType: function (subType, cb, context) {
-            return each(this.getSeriesByType(subType), cb, context);
-        },
-
-        /**
-         * @param {module:echarts/model/Series} seriesModel
-         */
-        isSeriesFiltered: function (seriesModel) {
-            assertSeriesInitialized(this);
-            return zrUtil.indexOf(this._seriesIndices, seriesModel.componentIndex) < 0;
-        },
-
-        /**
-         * @param {Function} cb
-         * @param {*} context
-         */
-        filterSeries: function (cb, context) {
-            assertSeriesInitialized(this);
-            var filteredSeries = filter(
-                this._componentsMap.series, cb, context
-            );
-            this._seriesIndices = createSeriesIndices(filteredSeries);
-        },
-
-        restoreData: function () {
-            var componentsMap = this._componentsMap;
-
-            this._seriesIndices = createSeriesIndices(componentsMap.series);
-
-            var componentTypes = [];
-            each(componentsMap, function (components, componentType) {
-                componentTypes.push(componentType);
-            });
-
-            ComponentModel.topologicalTravel(
-                componentTypes,
-                ComponentModel.getAllClassMainTypes(),
-                function (componentType, dependencies) {
-                    each(componentsMap[componentType], function (component) {
-                        component.restoreData();
-                    });
-                }
-            );
-        }
-
-    });
-
-    /**
-     * @inner
-     */
-    function mergeTheme(option, theme) {
-        for (var name in theme) {
-            // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
-            if (!ComponentModel.hasClass(name)) {
-                if (typeof theme[name] === 'object') {
-                    option[name] = !option[name]
-                        ? zrUtil.clone(theme[name])
-                        : zrUtil.merge(option[name], theme[name], false);
-                }
-                else {
-                    option[name] = theme[name];
-                }
-            }
-        }
-    }
-
-    function initBase(baseOption) {
-        baseOption = baseOption;
-
-        this.option = {};
-
-        /**
-         * @type {Object.<string, Array.<module:echarts/model/Model>>}
-         * @private
-         */
-        this._componentsMap = {};
-
-        /**
-         * Mapping between filtered series list and raw series list.
-         * key: filtered series indices, value: raw series indices.
-         * @type {Array.<nubmer>}
-         * @private
-         */
-        this._seriesIndices = null;
-
-        mergeTheme(baseOption, this._theme.option);
-
-        // TODO Needs clone when merging to the unexisted property
-        zrUtil.merge(baseOption, globalDefault, false);
-
-        this.mergeOption(baseOption);
-    }
-
-    /**
-     * @inner
-     * @param {Array.<string>|string} types model types
-     * @return {Object} key: {string} type, value: {Array.<Object>} models
-     */
-    function getComponentsByTypes(componentsMap, types) {
-        if (!zrUtil.isArray(types)) {
-            types = types ? [types] : [];
-        }
-
-        var ret = {};
-        each(types, function (type) {
-            ret[type] = (componentsMap[type] || []).slice();
-        });
-
-        return ret;
-    }
-
-    /**
-     * @inner
-     */
-    function mappingToExists(existComponents, newComponentOptionList) {
-        existComponents = (existComponents || []).slice();
-        var result = [];
-
-        // Mapping by id if specified.
-        each(newComponentOptionList, function (componentOption, index) {
-            if (!isObject(componentOption) || !componentOption.id) {
-                return;
-            }
-            for (var i = 0, len = existComponents.length; i < len; i++) {
-                if (existComponents[i].id === componentOption.id) {
-                    result[index] = existComponents.splice(i, 1)[0];
-                    return;
-                }
-            }
-        });
-
-        // Mapping by name if specified.
-        each(newComponentOptionList, function (componentOption, index) {
-            if (!isObject(componentOption)
-                || !componentOption.name
-                || hasInnerId(componentOption)
-            ) {
-                return;
-            }
-            for (var i = 0, len = existComponents.length; i < len; i++) {
-                if (existComponents[i].name === componentOption.name) {
-                    result[index] = existComponents.splice(i, 1)[0];
-                    return;
-                }
-            }
-        });
-
-        // Otherwise mapping by index.
-        each(newComponentOptionList, function (componentOption, index) {
-            if (!result[index]
-                && existComponents[index]
-                && !hasInnerId(componentOption)
-            ) {
-                result[index] = existComponents[index];
-            }
-        });
-
-        return result;
-    }
-
-    /**
-     * @inner
-     */
-    function makeKeyInfo(mainType, newCptOptionList, existComponents) {
-        // 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 when setOption are called in
-        // no-merge mode, new model is able to replace old model, and
-        // new view instance are able to mapped to old instance.
-        // So we generate id by name and type.
-
-        // name can be duplicated among components, which is convenient
-        // to specify multi components (like series) by one name.
-
-        // raw option should not be modified. for example, xxx.name might
-        // be rendered, so default name ('') should not be replaced by
-        // generated name. So we use keyInfoList wrap key info.
-        var keyInfoList = [];
-
-        // We use a prefix when generating name or id to prevent
-        // user using the generated name or id directly.
-        var prefix = '\0';
-
-        // Ensure that each id is distinct.
-        var idSet = {};
-
-        // key: name, value: count by single name.
-        var nameCount = {};
-
-        // Complete subType
-        each(newCptOptionList, function (opt, index) {
-            if (!isObject(opt)) {
-                return;
-            }
-            var existCpt = existComponents[index];
-            var subType = determineSubType(mainType, opt, existCpt);
-            var item = {mainType: mainType, subType: subType};
-            keyInfoList[index] = item;
-        });
-
-        function eachOpt(cb) {
-            each(newCptOptionList, function (opt, index) {
-                if (!isObject(opt)) {
-                    return;
-                }
-                var existCpt = existComponents[index];
-                var item = keyInfoList[index];
-                var fullType = mainType + '.' + item.subType;
-                cb(item, opt, existCpt, fullType);
-            });
-        }
-
-        // Make name
-        eachOpt(function (item, opt, existCpt, fullType) {
-            item.name = existCpt
-                ? existCpt.name
-                : opt.name != null
-                ? opt.name
-                : prefix + '-';
-            // init nameCount
-            nameCount[item.name] = 0;
-        });
-
-        // Make id
-        eachOpt(function (item, opt, existCpt, fullType) {
-            var itemName = item.name;
-
-            item.id = existCpt
-                ? existCpt.id
-                : opt.id != null
-                ? opt.id
-                // (1) Using delimiter to escapse dulipcation.
-                // (2) Using type tu ensure that view with different
-                //     type will not be mapped.
-                // (3) Consider this situatoin:
-                //      optionA: [{name: 'a'}, {name: 'a'}, {..}]
-                //      optionB [{..}, {name: 'a'}, {name: 'a'}]
-                //     Using nameCount to ensure that series with
-                //     the same name between optionA and optionB
-                //     can be mapped.
-                : prefix + [fullType, itemName, nameCount[itemName]++].join('|');
-
-            if (idSet[item.id]) {
-                // FIXME
-                // how to throw
-                throw new Error('id duplicates: ' + item.id);
-            }
-            idSet[item.id] = 1;
-        });
-
-        return keyInfoList;
-    }
-
-    /**
-     * @inner
-     */
-    function determineSubType(mainType, newCptOption, existComponent) {
-        var subType = 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 subType
-        return subType;
-    }
-
-    /**
-     * @inner
-     */
-    function createSeriesIndices(seriesModels) {
-        return map(seriesModels, function (series) {
-            return series.componentIndex;
-        }) || [];
-    }
-
-    /**
-     * @inner
-     */
-    function filterBySubType(components, condition) {
-        // Using hasOwnProperty for restrict. Consider
-        // subType is undefined in user payload.
-        return condition.hasOwnProperty('subType')
-            ? filter(components, function (cpt) {
-                return cpt.subType === condition.subType;
-            })
-            : components;
-    }
-
-    /**
-     * @inner
-     */
-    function hasInnerId(componentOption) {
-        return componentOption.id
-            // FIXME
-            // Where to put this constant.
-            && (componentOption.id + '').indexOf('\0_ec_\0') === 0;
-    }
-
-    /**
-     * @inner
-     */
-    function assertSeriesInitialized(ecModel) {
-        // Components that use _seriesIndices should depends on series component,
-        // which make sure that their initialization is after series.
-        if (!ecModel._seriesIndices) {
-            // FIXME
-            // 验证和提示怎么写
-            throw new Error('Series is not initialized. Please depends sereis.');
-        }
-    }
-
-    return GlobalModel;
-});
-define('echarts/ExtensionAPI',['require','zrender/core/util'],function(require) {
-
-
-
-    var zrUtil = require('zrender/core/util');
-
-    var echartsAPIList = [
-        'getDom', 'getZr', 'getWidth', 'getHeight', 'dispatchAction',
-        'on', 'off', 'getDataURL', 'getConnectedDataURL'
-    ];
-
-    function ExtensionAPI(chartInstance) {
-        zrUtil.each(echartsAPIList, function (name) {
-            this[name] = zrUtil.bind(chartInstance[name], chartInstance);
-        }, this);
-    }
-
-    return ExtensionAPI;
-});
-define('echarts/CoordinateSystem',['require'],function(require) {
-
-
-
-    // var zrUtil = require('zrender/core/util');
-    var coordinateSystemCreators = {};
-
-    function CoordinateSystemManager() {
-
-        this._coordinateSystems = {};
-
-        this._coordinateSystemsList = [];
-    }
-
-    CoordinateSystemManager.prototype = {
-
-        constructor: CoordinateSystemManager,
-
-        update: function (ecModel, api) {
-            var coordinateSystems = {};
-            for (var type in coordinateSystemCreators) {
-                coordinateSystems[type] = coordinateSystemCreators[type].create(ecModel, api);
-            }
-
-            this._coordinateSystems = coordinateSystems;
-        },
-
-        get: function (type, idx) {
-            var list = this._coordinateSystems[type];
-            if (list) {
-                return list[idx || 0];
-            }
-        }
-    };
-
-    CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
-        coordinateSystemCreators[type] = coordinateSystemCreator;
-    };
-
-    return CoordinateSystemManager;
-});
-/**
- * ECharts option manager
- *
- * @module {echarts/model/OptionManager}
- */
-
-define('echarts/model/OptionManager',['require','zrender/core/util'],function (require) {
-
-    var zrUtil = require('zrender/core/util');
-    var each = zrUtil.each;
-    var clone = zrUtil.clone;
-    var map = zrUtil.map;
-
-    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, means default.
-         * empty means no media.
-         * @private
-         * @type {Array.<number>}
-         */
-        this._currentMediaIndices = [];
-
-        /**
-         * @private
-         * @type {Object}
-         */
-        this._optionBackup;
-    }
-
-    // timeline.notMerge is not supported in ec3. Firstly there is rearly
-    // 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} Init option
-         */
-        setOption: function (rawOption, optionPreprocessorFuncs) {
-            rawOption = clone(rawOption, true);
-
-            // FIXME
-            // 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。
-
-            this._optionBackup = parseRawOption.call(
-                this, rawOption, optionPreprocessorFuncs
-            );
-        },
-
-        /**
-         * @return {Object}
-         */
-        mountOption: function () {
-            var optionBackup = this._optionBackup;
-
-            // FIXME
-            // 如果没有reset功能则不clone。
-
-            this._timelineOptions = map(optionBackup.timelineOptions, clone);
-            this._mediaList = map(optionBackup.mediaList, clone);
-            this._mediaDefault = clone(optionBackup.mediaDefault);
-            this._currentMediaIndices = [];
-
-            return clone(optionBackup.baseOption);
-        },
-
-        /**
-         * @param {module:echarts/model/Global} ecModel
-         * @return {Object}
-         */
-        getTimelineOption: function (ecModel) {
-            var option;
-            var timelineOptions = this._timelineOptions;
-
-            if (timelineOptions.length) {
-                // getTimelineOption can only be called after ecModel inited,
-                // so we can get currentIndex from timelineModel.
-                var timelineModel = ecModel.getComponent('timeline');
-                if (timelineModel) {
-                    option = clone(
-                        timelineOptions[timelineModel.getCurrentIndex()],
-                        true
-                    );
-                }
-            }
-
-            return option;
-        },
-
-        /**
-         * @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 = [];
-
-            // No media defined.
-            if (!mediaList.length && !mediaDefault) {
-                return result;
-            }
-
-            // Multi media may be applied, the latter defined media has higher priority.
-            for (var i = 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(indices, function (index) {
-                    return clone(
-                        index === -1 ? mediaDefault.option : mediaList[index].option
-                    );
-                });
-            }
-            // Otherwise return nothing.
-
-            this._currentMediaIndices = indices;
-
-            return result;
-        }
-    };
-
-    function parseRawOption(rawOption, optionPreprocessorFuncs) {
-        var timelineOptions = [];
-        var mediaList = [];
-        var mediaDefault;
-        var baseOption;
-
-        // Compatible with ec2.
-        var timelineOpt = rawOption.timeline;
-
-        // For timeline
-        if (timelineOpt || rawOption.options) {
-            baseOption = rawOption.baseOption || {};
-            timelineOptions = (rawOption.options || []).slice();
-        }
-        // For media query
-        if (rawOption.media) {
-            baseOption = rawOption.baseOption || {};
-            var media = rawOption.media;
-            each(media, function (singleMedia) {
-                if (singleMedia && singleMedia.option) {
-                    if (singleMedia.query) {
-                        mediaList.push(singleMedia);
-                    }
-                    else if (!mediaDefault) {
-                        // Use the first media default.
-                        mediaDefault = singleMedia;
-                    }
-                }
-            });
-        }
-        // For normal option
-        if (!baseOption) {
-            baseOption = rawOption;
-        }
-
-        // Set timelineOpt to baseOption in ec3,
-        // which is convenient for merge option.
-        if (!baseOption.timeline) {
-            baseOption.timeline = timelineOpt;
-        }
-
-        // Preprocess.
-        each([baseOption].concat(timelineOptions)
-            .concat(zrUtil.map(mediaList, function (media) {
-                return media.option;
-            })),
-            function (option) {
-                each(optionPreprocessorFuncs, function (preProcess) {
-                    preProcess(option);
-                });
-            }
-        );
-
-        return {
-            baseOption: baseOption,
-            timelineOptions: timelineOptions,
-            mediaDefault: mediaDefault,
-            mediaList: mediaList
-        };
-    }
-
-    /**
-     * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>
-     * Support: width, height, aspectRatio
-     * Can use max or min as prefix.
-     */
-    function applyMediaQuery(query, ecWidth, ecHeight) {
-        var realMap = {
-            width: ecWidth,
-            height: ecHeight,
-            aspectratio: ecWidth / ecHeight // lowser case for convenientce.
-        };
-
-        var applicatable = true;
-
-        zrUtil.each(query, function (value, attr) {
-            var matched = attr.match(QUERY_REG);
-
-            if (!matched || !matched[1] || !matched[2]) {
-                return;
-            }
-
-            var operator = matched[1];
-            var realAttr = matched[2].toLowerCase();
-
-            if (!compare(realMap[realAttr], value, operator)) {
-                applicatable = false;
-            }
-        });
-
-        return applicatable;
-    }
-
-    function compare(real, expect, operator) {
-        if (operator === 'min') {
-            return real >= expect;
-        }
-        else if (operator === 'max') {
-            return real <= expect;
-        }
-        else { // Equals
-            return real === expect;
-        }
-    }
-
-    function indicesEquals(indices1, indices2) {
-        // indices is always order by asc and has only finite number.
-        return indices1.join(',') === indices2.join(',');
-    }
-
-    return OptionManager;
-});
-define('echarts/util/model',['require','./format','./number','zrender/core/util','../model/Model'],function(require) {
-
-    var formatUtil = require('./format');
-    var nubmerUtil = require('./number');
-    var zrUtil = require('zrender/core/util');
-
-    var Model = require('../model/Model');
-
-    var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle'];
-
-    var modelUtil = {};
-
-    /**
-     * Create "each" method to iterate names.
-     *
-     * @pubilc
-     * @param  {Array.<string>} names
-     * @param  {Array.<string>=} attrs
-     * @return {Function}
-     */
-    modelUtil.createNameEach = function (names, attrs) {
-        names = names.slice();
-        var capitalNames = zrUtil.map(names, modelUtil.capitalFirst);
-        attrs = (attrs || []).slice();
-        var capitalAttrs = zrUtil.map(attrs, modelUtil.capitalFirst);
-
-        return function (callback, context) {
-            zrUtil.each(names, function (name, index) {
-                var nameObj = {name: name, capital: capitalNames[index]};
-
-                for (var j = 0; j < attrs.length; j++) {
-                    nameObj[attrs[j]] = name + capitalAttrs[j];
-                }
-
-                callback.call(context, nameObj);
-            });
-        };
-    };
-
-    /**
-     * @public
-     */
-    modelUtil.capitalFirst = function (str) {
-        return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
-    };
-
-    /**
-     * Iterate each dimension name.
-     *
-     * @public
-     * @param {Function} callback The parameter is like:
-     *                            {
-     *                                name: 'angle',
-     *                                capital: 'Angle',
-     *                                axis: 'angleAxis',
-     *                                axisIndex: 'angleAixs',
-     *                                index: 'angleIndex'
-     *                            }
-     * @param {Object} context
-     */
-    modelUtil.eachAxisDim = modelUtil.createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index']);
-
-    /**
-     * If value is not array, then translate it to array.
-     * @param  {*} value
-     * @return {Array} [value] or value
-     */
-    modelUtil.normalizeToArray = function (value) {
-        return zrUtil.isArray(value)
-            ? value
-            : value == null
-            ? []
-            : [value];
-    };
-
-    /**
-     * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'.
-     * dataZoomModels and 'links' make up one or more graphics.
-     * This function finds the graphic where the source dataZoomModel is in.
-     *
-     * @public
-     * @param {Function} forEachNode Node iterator.
-     * @param {Function} forEachEdgeType edgeType iterator
-     * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id.
-     * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}}
-     */
-    modelUtil.createLinkedNodesFinder = function (forEachNode, forEachEdgeType, edgeIdGetter) {
-
-        return function (sourceNode) {
-            var result = {
-                nodes: [],
-                records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean).
-            };
-
-            forEachEdgeType(function (edgeType) {
-                result.records[edgeType.name] = {};
-            });
-
-            if (!sourceNode) {
-                return result;
-            }
-
-            absorb(sourceNode, result);
-
-            var existsLink;
-            do {
-                existsLink = false;
-                forEachNode(processSingleNode);
-            }
-            while (existsLink);
-
-            function processSingleNode(node) {
-                if (!isNodeAbsorded(node, result) && isLinked(node, result)) {
-                    absorb(node, result);
-                    existsLink = true;
-                }
-            }
-
-            return result;
-        };
-
-        function isNodeAbsorded(node, result) {
-            return zrUtil.indexOf(result.nodes, node) >= 0;
-        }
-
-        function isLinked(node, result) {
-            var hasLink = false;
-            forEachEdgeType(function (edgeType) {
-                zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
-                    result.records[edgeType.name][edgeId] && (hasLink = true);
-                });
-            });
-            return hasLink;
-        }
-
-        function absorb(node, result) {
-            result.nodes.push(node);
-            forEachEdgeType(function (edgeType) {
-                zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
-                    result.records[edgeType.name][edgeId] = true;
-                });
-            });
-        }
-    };
-
-    /**
-     * Sync default option between normal and emphasis like `position` and `show`
-     * In case some one will write code like
-     *     label: {
-     *         normal: {
-     *             show: false,
-     *             position: 'outside',
-     *             textStyle: {
-     *                 fontSize: 18
-     *             }
-     *         },
-     *         emphasis: {
-     *             show: true
-     *         }
-     *     }
-     * @param {Object} opt
-     * @param {Array.<string>} subOpts
-     */
-     modelUtil.defaultEmphasis = function (opt, subOpts) {
-        if (opt) {
-            var emphasisOpt = opt.emphasis = opt.emphasis || {};
-            var normalOpt = opt.normal = opt.normal || {};
-
-            // Default emphasis option from normal
-            zrUtil.each(subOpts, function (subOptName) {
-                var val = zrUtil.retrieve(emphasisOpt[subOptName], normalOpt[subOptName]);
-                if (val != null) {
-                    emphasisOpt[subOptName] = val;
-                }
-            });
-        }
-    };
-
-    /**
-     * Create a model proxy to be used in tooltip for edge data, markLine data, markPoint data.
-     * @param {Object} opt
-     * @param {string} [opt.seriesIndex]
-     * @param {Object} [opt.name]
-     * @param {module:echarts/data/List} data
-     * @param {Array.<Object>} rawData
-     */
-    modelUtil.createDataFormatModel = function (opt, data, rawData) {
-        var model = new Model();
-        zrUtil.mixin(model, modelUtil.dataFormatMixin);
-        model.seriesIndex = opt.seriesIndex;
-        model.name = opt.name || '';
-
-        model.getData = function () {
-            return data;
-        };
-        model.getRawDataArray = function () {
-            return rawData;
-        };
-        return model;
-    };
-
-    /**
-     * 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>}
-     */
-    modelUtil.getDataItemValue = function (dataItem) {
-        // Performance sensitive.
-        return dataItem && (dataItem.value == null ? dataItem : dataItem.value);
-    };
-
-    /**
-     * This helper method convert value in data.
-     * @param {string|number|Date} value
-     * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'.
-     */
-    modelUtil.converDataValue = function (value, dimInfo) {
-        // Performance sensitive.
-        var dimType = dimInfo && dimInfo.type;
-        if (dimType === 'ordinal') {
-            return value;
-        }
-
-        if (dimType === 'time' && !isFinite(value) && value != null && value !== '-') {
-            value = +nubmerUtil.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 : +value; // If string (like '-'), using '+' parse to NaN
-    };
-
-    modelUtil.dataFormatMixin = {
-        /**
-         * Get params for formatter
-         * @param {number} dataIndex
-         * @return {Object}
-         */
-        getDataParams: function (dataIndex) {
-            var data = this.getData();
-
-            var seriesIndex = this.seriesIndex;
-            var seriesName = this.name;
-
-            var rawValue = this.getRawValue(dataIndex);
-            var rawDataIndex = data.getRawIndex(dataIndex);
-            var name = data.getName(dataIndex, true);
-
-            // Data may not exists in the option given by user
-            var rawDataArray = this.getRawDataArray();
-            var itemOpt = rawDataArray && rawDataArray[rawDataIndex];
-
-            return {
-                seriesIndex: seriesIndex,
-                seriesName: seriesName,
-                name: name,
-                dataIndex: rawDataIndex,
-                data: itemOpt,
-                value: rawValue,
-
-                // Param name list for mapping `a`, `b`, `c`, `d`, `e`
-                $vars: ['seriesName', 'name', 'value']
-            };
-        },
-
-        /**
-         * Format label
-         * @param {number} dataIndex
-         * @param {string} [status='normal'] 'normal' or 'emphasis'
-         * @param {Function|string} [formatter] Default use the `itemStyle[status].label.formatter`
-         * @return {string}
-         */
-        getFormattedLabel: function (dataIndex, status, formatter) {
-            status = status || 'normal';
-            var data = this.getData();
-            var itemModel = data.getItemModel(dataIndex);
-
-            var params = this.getDataParams(dataIndex);
-            if (!formatter) {
-                formatter = itemModel.get(['label', status, 'formatter']);
-            }
-
-            if (typeof formatter === 'function') {
-                params.status = status;
-                return formatter(params);
-            }
-            else if (typeof formatter === 'string') {
-                return formatUtil.formatTpl(formatter, params);
-            }
-        },
-
-        /**
-         * Get raw value in option
-         * @param {number} idx
-         * @return {Object}
-         */
-        getRawValue: function (idx) {
-            var itemModel = this.getData().getItemModel(idx);
-            if (itemModel && itemModel.option) {
-                var dataItem = itemModel.option;
-                return (zrUtil.isObject(dataItem) && !zrUtil.isArray(dataItem))
-                    ? dataItem.value : dataItem;
-            }
-        }
-    };
-
-    return modelUtil;
-});
-define('echarts/model/Series',['require','zrender/core/util','../util/format','../util/model','./Component'],function(require) {
-
-
-
-    var zrUtil = require('zrender/core/util');
-    var formatUtil = require('../util/format');
-    var modelUtil = require('../util/model');
-    var ComponentModel = require('./Component');
-
-    var encodeHTML = formatUtil.encodeHTML;
-    var addCommas = formatUtil.addCommas;
-
-    var SeriesModel = ComponentModel.extend({
-
-        type: 'series',
-
-        /**
-         * @readOnly
-         */
-        seriesIndex: 0,
-
-        // coodinateSystem will be injected in the echarts/CoordinateSystem
-        coordinateSystem: null,
-
-        /**
-         * @type {Object}
-         * @protected
-         */
-        defaultOption: null,
-
-        /**
-         * Data provided for legend
-         * @type {Function}
-         */
-        // PENDING
-        legendDataProvider: null,
-
-        init: function (option, parentModel, ecModel, extraOpt) {
-
-            /**
-             * @type {number}
-             * @readOnly
-             */
-            this.seriesIndex = this.componentIndex;
-
-            this.mergeDefaultAndTheme(option, ecModel);
-
-            /**
-             * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
-             * @private
-             */
-            this._dataBeforeProcessed = this.getInitialData(option, ecModel);
-
-            // When using module:echarts/data/Tree or module:echarts/data/Graph,
-            // cloneShallow will cause this._data.graph.data pointing to new data list.
-            // Wo we make this._dataBeforeProcessed first, and then make this._data.
-            this._data = this._dataBeforeProcessed.cloneShallow();
-        },
-
-        /**
-         * Util for merge default and theme to option
-         * @param  {Object} option
-         * @param  {module:echarts/model/Global} ecModel
-         */
-        mergeDefaultAndTheme: function (option, ecModel) {
-            zrUtil.merge(
-                option,
-                ecModel.getTheme().get(this.subType)
-            );
-            zrUtil.merge(option, this.getDefaultOption());
-
-            // Default label emphasis `position` and `show`
-            modelUtil.defaultEmphasis(
-                option.label, ['position', 'show', 'textStyle', 'distance', 'formatter']
-            );
-        },
-
-        mergeOption: function (newSeriesOption, ecModel) {
-            newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
-
-            var data = this.getInitialData(newSeriesOption, ecModel);
-            // TODO Merge data?
-            if (data) {
-                this._data = data;
-                this._dataBeforeProcessed = data.cloneShallow();
-            }
-            // FIXME
-            // Default label emphasis `position` and `show`
-            // Do it after option is merged. In case newSeriesOption only
-            // set the value in emphasis
-            // modelUtil.defaultNormalEmphasis(this.option.label);
-        },
-
-        /**
-         * Init a data structure from data related option in series
-         * Must be overwritten
-         */
-        getInitialData: function () {},
-
-        /**
-         * @return {module:echarts/data/List}
-         */
-        getData: function () {
-            return this._data;
-        },
-
-        /**
-         * @param {module:echarts/data/List} data
-         */
-        setData: function (data) {
-            this._data = data;
-        },
-
-        /**
-         * Get data before processed
-         * @return {module:echarts/data/List}
-         */
-        getRawData: function () {
-            return this._dataBeforeProcessed;
-        },
-
-        /**
-         * Get raw data array given by user
-         * @return {Array.<Object>}
-         */
-        getRawDataArray: function () {
-            return this.option.data;
-        },
-
-        /**
-         * Get dimensions on the given axis.
-         * @param {string} axisDim
-         * @return {Array.<string>} dimensions on the axis.
-         */
-        getDimensionsOnAxis: function (axisDim) {
-            return [axisDim]; // Retunr axisDim default.
-        },
-
-        // FIXME
-        /**
-         * Default tooltip formatter
-         *
-         * @param {number} dataIndex
-         * @param {boolean} [mutipleSeries=false]
-         */
-        formatTooltip: function (dataIndex, mutipleSeries) {
-            var data = this._data;
-            var value = this.getRawValue(dataIndex);
-            var formattedValue = zrUtil.isArray(value)
-                ? zrUtil.map(value, addCommas).join(', ') : addCommas(value);
-            var name = data.getName(dataIndex);
-
-            return !mutipleSeries
-                ? (encodeHTML(this.name) + '<br />'
-                    + (name
-                        ? encodeHTML(name) + ' : ' + formattedValue
-                        : formattedValue)
-                  )
-                : (encodeHTML(this.name) + ' : ' + formattedValue);
-        },
-
-        restoreData: function () {
-            this._data = this._dataBeforeProcessed.cloneShallow();
-        }
-    });
-
-    zrUtil.mixin(SeriesModel, modelUtil.dataFormatMixin);
-
-    return SeriesModel;
-});
-/**
- * zrender: 生成唯一id
- *
- * @author errorrik (errorrik@gmail.com)
- */
-
-define(
-    'zrender/core/guid',[],function() {
-        var idStart = 0x0907;
-
-        return function () {
-            return 'zr_' + (idStart++);
-        };
-    }
-);
-
-/**
- * 事件扩展
- * @module zrender/mixin/Eventful
- * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
- *         pissang (https://www.github.com/pissang)
- */
-define('zrender/mixin/Eventful',['require','../core/util'],function (require) {
-
-    var arrySlice = Array.prototype.slice;
-    var zrUtil = require('../core/util');
-    var indexOf = zrUtil.indexOf;
-
-    /**
-     * 事件分发器
-     * @alias module:zrender/mixin/Eventful
-     * @constructor
-     */
-    var Eventful = function () {
-        this._$handlers = {};
-    };
-
-    Eventful.prototype = {
-
-        constructor: Eventful,
-
-        /**
-         * 单次触发绑定,trigger后销毁
-         *
-         * @param {string} event 事件名
-         * @param {Function} handler 响应函数
-         * @param {Object} context
-         */
-        one: function (event, handler, context) {
-            var _h = this._$handlers;
-
-            if (!handler || !event) {
-                return this;
-            }
-
-            if (!_h[event]) {
-                _h[event] = [];
-            }
-
-            if (indexOf(_h[event], event) >= 0) {
-                return this;
-            }
-
-            _h[event].push({
-                h: handler,
-                one: true,
-                ctx: context || this
-            });
-
-            return this;
-        },
-
-        /**
-         * 绑定事件
-         * @param {string} event 事件名
-         * @param {Function} handler 事件处理函数
-         * @param {Object} [context]
-         */
-        on: function (event, handler, context) {
-            var _h = this._$handlers;
-
-            if (!handler || !event) {
-                return this;
-            }
-
-            if (!_h[event]) {
-                _h[event] = [];
-            }
-
-            _h[event].push({
-                h: handler,
-                one: false,
-                ctx: context || this
-            });
-
-            return this;
-        },
-
-        /**
-         * 是否绑定了事件
-         * @param  {string}  event
-         * @return {boolean}
-         */
-        isSilent: function (event) {
-            var _h = this._$handlers;
-            return _h[event] && _h[event].length;
-        },
-
-        /**
-         * 解绑事件
-         * @param {string} event 事件名
-         * @param {Function} [handler] 事件处理函数
-         */
-        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;
-        },
-
-        /**
-         * 事件分发
-         *
-         * @param {string} type 事件类型
-         */
-        trigger: function (type) {
-            if (this._$handlers[type]) {
-                var args = arguments;
-                var argLen = args.length;
-
-                if (argLen > 3) {
-                    args = arrySlice.call(args, 1);
-                }
-
-                var _h = this._$handlers[type];
-                var len = _h.length;
-                for (var i = 0; i < len;) {
-                    // Optimize advise from backbone
-                    switch (argLen) {
-                        case 1:
-                            _h[i]['h'].call(_h[i]['ctx']);
-                            break;
-                        case 2:
-                            _h[i]['h'].call(_h[i]['ctx'], args[1]);
-                            break;
-                        case 3:
-                            _h[i]['h'].call(_h[i]['ctx'], args[1], args[2]);
-                            break;
-                        default:
-                            // have more than 2 given arguments
-                            _h[i]['h'].apply(_h[i]['ctx'], args);
-                            break;
-                    }
-
-                    if (_h[i]['one']) {
-                        _h.splice(i, 1);
-                        len--;
-                    }
-                    else {
-                        i++;
-                    }
-                }
-            }
-
-            return this;
-        },
-
-        /**
-         * 带有context的事件分发, 最后一个参数是事件回调的context
-         * @param {string} type 事件类型
-         */
-        triggerWithContext: function (type) {
-            if (this._$handlers[type]) {
-                var args = arguments;
-                var argLen = args.length;
-
-                if (argLen > 4) {
-                    args = arrySlice.call(args, 1, args.length - 1);
-                }
-                var ctx = args[args.length - 1];
-
-                var _h = this._$handlers[type];
-                var len = _h.length;
-                for (var i = 0; i < len;) {
-                    // Optimize advise from backbone
-                    switch (argLen) {
-                        case 1:
-                            _h[i]['h'].call(ctx);
-                            break;
-                        case 2:
-                            _h[i]['h'].call(ctx, args[1]);
-                            break;
-                        case 3:
-                            _h[i]['h'].call(ctx, args[1], args[2]);
-                            break;
-                        default:
-                            // have more than 2 given arguments
-                            _h[i]['h'].apply(ctx, args);
-                            break;
-                    }
-
-                    if (_h[i]['one']) {
-                        _h.splice(i, 1);
-                        len--;
-                    }
-                    else {
-                        i++;
-                    }
-                }
-            }
-
-            return this;
-        }
-    };
-
-    // 对象可以通过 onxxxx 绑定事件
-    /**
-     * @event module:zrender/mixin/Eventful#onclick
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmouseover
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmouseout
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmousemove
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmousewheel
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmousedown
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#onmouseup
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondragstart
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondragend
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondragenter
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondragleave
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondragover
-     * @type {Function}
-     * @default null
-     */
-    /**
-     * @event module:zrender/mixin/Eventful#ondrop
-     * @type {Function}
-     * @default null
-     */
-
-    return Eventful;
-});
-
-/**
- * 提供变换扩展
- * @module zrender/mixin/Transformable
- * @author pissang (https://www.github.com/pissang)
- */
-define('zrender/mixin/Transformable',['require','../core/matrix','../core/vector'],function (require) {
-
-
-
-    var matrix = require('../core/matrix');
-    var vector = require('../core/vector');
-    var mIdentity = matrix.identity;
-
-    var EPSILON = 5e-5;
-
-    function isNotAroundZero(val) {
-        return val > EPSILON || val < -EPSILON;
-    }
-
-    /**
-     * @alias module:zrender/mixin/Transformable
-     * @constructor
-     */
-    var Transformable = function (opts) {
-        opts = opts || {};
-        // If there are no given position, rotation, scale
-        if (!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;
-    };
-
-    var transformableProto = Transformable.prototype;
-    transformableProto.transform = null;
-
-    /**
-     * 判断是否需要有坐标变换
-     * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵
-     */
-    transformableProto.needLocalTransform = function () {
-        return isNotAroundZero(this.rotation)
-            || isNotAroundZero(this.position[0])
-            || isNotAroundZero(this.position[1])
-            || isNotAroundZero(this.scale[0] - 1)
-            || isNotAroundZero(this.scale[1] - 1);
-    };
-
-    transformableProto.updateTransform = function () {
-        var parent = this.parent;
-        var parentHasTransform = parent && parent.transform;
-        var needLocalTransform = this.needLocalTransform();
-
-        var m = this.transform;
-        if (!(needLocalTransform || parentHasTransform)) {
-            m && mIdentity(m);
-            return;
-        }
-
-        m = m || matrix.create();
-
-        if (needLocalTransform) {
-            this.getLocalTransform(m);
-        }
-        else {
-            mIdentity(m);
-        }
-
-        // 应用父节点变换
-        if (parentHasTransform) {
-            if (needLocalTransform) {
-                matrix.mul(m, parent.transform, m);
-            }
-            else {
-                matrix.copy(m, parent.transform);
-            }
-        }
-        // 保存这个变换矩阵
-        this.transform = m;
-
-        this.invTransform = this.invTransform || matrix.create();
-        matrix.invert(this.invTransform, m);
-    };
-
-    transformableProto.getLocalTransform = function (m) {
-        m = m || [];
-        mIdentity(m);
-
-        var origin = this.origin;
-
-        var scale = this.scale;
-        var rotation = this.rotation;
-        var position = this.position;
-        if (origin) {
-            // Translate to origin
-            m[4] -= origin[0];
-            m[5] -= origin[1];
-        }
-        matrix.scale(m, m, scale);
-        if (rotation) {
-            matrix.rotate(m, m, rotation);
-        }
-        if (origin) {
-            // Translate back from origin
-            m[4] += origin[0];
-            m[5] += origin[1];
-        }
-
-        m[4] += position[0];
-        m[5] += position[1];
-
-        return m;
-    };
-    /**
-     * 将自己的transform应用到context上
-     * @param {Context2D} ctx
-     */
-    transformableProto.setTransform = function (ctx) {
-        var m = this.transform;
-        if (m) {
-            ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
-        }
-    };
-
-    var tmpTransform = [];
-
-    /**
-     * 分解`transform`矩阵到`position`, `rotation`, `scale`
-     */
-    transformableProto.decomposeTransform = function () {
-        if (!this.transform) {
-            return;
-        }
-        var parent = this.parent;
-        var m = this.transform;
-        if (parent && parent.transform) {
-            // Get local transform and decompose them to position, scale, rotation
-            matrix.mul(tmpTransform, parent.invTransform, m);
-            m = tmpTransform;
-        }
-        var sx = m[0] * m[0] + m[1] * m[1];
-        var sy = m[2] * m[2] + m[3] * m[3];
-        var position = this.position;
-        var scale = 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[0] = sx;
-        scale[1] = sy;
-        this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);
-    };
-
-    /**
-     * 变换坐标位置到 shape 的局部坐标空间
-     * @method
-     * @param {number} x
-     * @param {number} y
-     * @return {Array.<number>}
-     */
-    transformableProto.transformCoordToLocal = function (x, y) {
-        var v2 = [x, y];
-        var invTransform = this.invTransform;
-        if (invTransform) {
-            vector.applyTransform(v2, v2, invTransform);
-        }
-        return v2;
-    };
-
-    /**
-     * 变换局部坐标位置到全局坐标空间
-     * @method
-     * @param {number} x
-     * @param {number} y
-     * @return {Array.<number>}
-     */
-    transformableProto.transformCoordToGlobal = function (x, y) {
-        var v2 = [x, y];
-        var transform = this.transform;
-        if (transform) {
-            vector.applyTransform(v2, v2, transform);
-        }
-        return v2;
-    };
-
-    return Transformable;
-});
-
-/**
- * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js
- * @see http://sole.github.io/tween.js/examples/03_graphs.html
- * @exports zrender/animation/easing
- */
-define('zrender/animation/easing',[],function () {
-    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) {
-            return Math.sin(k * Math.PI / 2);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        sinusoidalInOut: function (k) {
-            return 0.5 * (1 - Math.cos(Math.PI * k));
-        },
-
-        // 指数曲线的缓动(2^t)
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        exponentialIn: function (k) {
-            return k === 0 ? 0 : Math.pow(1024, k - 1);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        exponentialOut: function (k) {
-            return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        exponentialInOut: function (k) {
-            if (k === 0) {
-                return 0;
-            }
-            if (k === 1) {
-                return 1;
-            }
-            if ((k *= 2) < 1) {
-                return 0.5 * Math.pow(1024, k - 1);
-            }
-            return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
-        },
-
-        // 圆形曲线的缓动(sqrt(1-t^2))
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        circularIn: function (k) {
-            return 1 - Math.sqrt(1 - k * k);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        circularOut: function (k) {
-            return Math.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);
-            }
-            return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
-        },
-
-        // 创建类似于弹簧在停止前来回振荡的动画
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        elasticIn: function (k) {
-            var s;
-            var a = 0.1;
-            var p = 0.4;
-            if (k === 0) {
-                return 0;
-            }
-            if (k === 1) {
-                return 1;
-            }
-            if (!a || a < 1) {
-                a = 1; s = p / 4;
-            }
-            else {
-                s = p * Math.asin(1 / a) / (2 * Math.PI);
-            }
-            return -(a * Math.pow(2, 10 * (k -= 1)) *
-                        Math.sin((k - s) * (2 * Math.PI) / p));
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        elasticOut: function (k) {
-            var s;
-            var a = 0.1;
-            var p = 0.4;
-            if (k === 0) {
-                return 0;
-            }
-            if (k === 1) {
-                return 1;
-            }
-            if (!a || a < 1) {
-                a = 1; s = p / 4;
-            }
-            else {
-                s = p * Math.asin(1 / a) / (2 * Math.PI);
-            }
-            return (a * Math.pow(2, -10 * k) *
-                    Math.sin((k - s) * (2 * Math.PI) / p) + 1);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        elasticInOut: function (k) {
-            var s;
-            var a = 0.1;
-            var p = 0.4;
-            if (k === 0) {
-                return 0;
-            }
-            if (k === 1) {
-                return 1;
-            }
-            if (!a || a < 1) {
-                a = 1; s = p / 4;
-            }
-            else {
-                s = p * Math.asin(1 / a) / (2 * Math.PI);
-            }
-            if ((k *= 2) < 1) {
-                return -0.5 * (a * Math.pow(2, 10 * (k -= 1))
-                    * Math.sin((k - s) * (2 * Math.PI) / p));
-            }
-            return a * Math.pow(2, -10 * (k -= 1))
-                    * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
-
-        },
-
-        // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        backIn: function (k) {
-            var s = 1.70158;
-            return k * k * ((s + 1) * k - s);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        backOut: function (k) {
-            var s = 1.70158;
-            return --k * k * ((s + 1) * k + s) + 1;
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        backInOut: function (k) {
-            var s = 1.70158 * 1.525;
-            if ((k *= 2) < 1) {
-                return 0.5 * (k * k * ((s + 1) * k - s));
-            }
-            return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
-        },
-
-        // 创建弹跳效果
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        bounceIn: function (k) {
-            return 1 - easing.bounceOut(1 - k);
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        bounceOut: function (k) {
-            if (k < (1 / 2.75)) {
-                return 7.5625 * k * k;
-            }
-            else if (k < (2 / 2.75)) {
-                return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
-            }
-            else if (k < (2.5 / 2.75)) {
-                return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
-            }
-            else {
-                return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
-            }
-        },
-        /**
-        * @param {number} k
-        * @return {number}
-        */
-        bounceInOut: function (k) {
-            if (k < 0.5) {
-                return easing.bounceIn(k * 2) * 0.5;
-            }
-            return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5;
-        }
-    }
-
-    return easing;
-});
-
-
-/**
- * 动画主控制器
- * @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
- */
-define('zrender/animation/Clip',['require','./easing'],function(require) {
-
-    var easingFuncs = require('./easing');
-
-    function Clip(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;
-    };
-
-    Clip.prototype = {
-
-        constructor: Clip,
-
-        step: function (time) {
-            // Set startTime on first step, or _startTime may has milleseconds different between clips
-            // PENDING
-            if (!this._initialized) {
-                this._startTime = new Date().getTime() + this._delay;
-                this._initialized = true;
-            }
-
-            var percent = (time - this._startTime) / this._life;
-
-            // 还没开始
-            if (percent < 0) {
-                return;
-            }
-
-            percent = Math.min(percent, 1);
-
-            var easing = this.easing;
-            var easingFunc = typeof easing == 'string' ? easingFuncs[easing] : easing;
-            var schedule = typeof easingFunc === 'function'
-                ? easingFunc(percent)
-                : percent;
-
-            this.fire('frame', schedule);
-
-            // 结束
-            if (percent == 1) {
-                if (this.loop) {
-                    this.restart();
-                    // 重新开始周期
-                    // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件
-                    return 'restart';
-                }
-
-                // 动画完成将这个控制器标识为待删除
-                // 在Animation.update中进行批量删除
-                this._needsRemove = true;
-                return 'destroy';
-            }
-
-            return null;
-        },
-
-        restart: function() {
-            var time = new Date().getTime();
-            var remainder = (time - this._startTime) % this._life;
-            this._startTime = new Date().getTime() - remainder + this.gap;
-
-            this._needsRemove = false;
-        },
-
-        fire: function(eventType, arg) {
-            eventType = 'on' + eventType;
-            if (this[eventType]) {
-                this[eventType](this._target, arg);
-            }
-        }
-    };
-
-    return Clip;
-});
-
-/**
- * @module zrender/tool/color
- */
-define('zrender/tool/color',['require'],function(require) {
-
-    var kCSSColorTable = {
-        'transparent': [0,0,0,0], 'aliceblue': [240,248,255,1],
-        'antiquewhite': [250,235,215,1], 'aqua': [0,255,255,1],
-        'aquamarine': [127,255,212,1], 'azure': [240,255,255,1],
-        'beige': [245,245,220,1], 'bisque': [255,228,196,1],
-        'black': [0,0,0,1], 'blanchedalmond': [255,235,205,1],
-        'blue': [0,0,255,1], 'blueviolet': [138,43,226,1],
-        'brown': [165,42,42,1], 'burlywood': [222,184,135,1],
-        'cadetblue': [95,158,160,1], 'chartreuse': [127,255,0,1],
-        'chocolate': [210,105,30,1], 'coral': [255,127,80,1],
-        'cornflowerblue': [100,149,237,1], 'cornsilk': [255,248,220,1],
-        'crimson': [220,20,60,1], 'cyan': [0,255,255,1],
-        'darkblue': [0,0,139,1], 'darkcyan': [0,139,139,1],
-        'darkgoldenrod': [184,134,11,1], 'darkgray': [169,169,169,1],
-        'darkgreen': [0,100,0,1], 'darkgrey': [169,169,169,1],
-        'darkkhaki': [189,183,107,1], 'darkmagenta': [139,0,139,1],
-        'darkolivegreen': [85,107,47,1], 'darkorange': [255,140,0,1],
-        'darkorchid': [153,50,204,1], 'darkred': [139,0,0,1],
-        'darksalmon': [233,150,122,1], 'darkseagreen': [143,188,143,1],
-        'darkslateblue': [72,61,139,1], 'darkslategray': [47,79,79,1],
-        'darkslategrey': [47,79,79,1], 'darkturquoise': [0,206,209,1],
-        'darkviolet': [148,0,211,1], 'deeppink': [255,20,147,1],
-        'deepskyblue': [0,191,255,1], 'dimgray': [105,105,105,1],
-        'dimgrey': [105,105,105,1], 'dodgerblue': [30,144,255,1],
-        'firebrick': [178,34,34,1], 'floralwhite': [255,250,240,1],
-        'forestgreen': [34,139,34,1], 'fuchsia': [255,0,255,1],
-        'gainsboro': [220,220,220,1], 'ghostwhite': [248,248,255,1],
-        'gold': [255,215,0,1], 'goldenrod': [218,165,32,1],
-        'gray': [128,128,128,1], 'green': [0,128,0,1],
-        'greenyellow': [173,255,47,1], 'grey': [128,128,128,1],
-        'honeydew': [240,255,240,1], 'hotpink': [255,105,180,1],
-        'indianred': [205,92,92,1], 'indigo': [75,0,130,1],
-        'ivory': [255,255,240,1], 'khaki': [240,230,140,1],
-        'lavender': [230,230,250,1], 'lavenderblush': [255,240,245,1],
-        'lawngreen': [124,252,0,1], 'lemonchiffon': [255,250,205,1],
-        'lightblue': [173,216,230,1], 'lightcoral': [240,128,128,1],
-        'lightcyan': [224,255,255,1], 'lightgoldenrodyellow': [250,250,210,1],
-        'lightgray': [211,211,211,1], 'lightgreen': [144,238,144,1],
-        'lightgrey': [211,211,211,1], 'lightpink': [255,182,193,1],
-        'lightsalmon': [255,160,122,1], 'lightseagreen': [32,178,170,1],
-        'lightskyblue': [135,206,250,1], 'lightslategray': [119,136,153,1],
-        'lightslategrey': [119,136,153,1], 'lightsteelblue': [176,196,222,1],
-        'lightyellow': [255,255,224,1], 'lime': [0,255,0,1],
-        'limegreen': [50,205,50,1], 'linen': [250,240,230,1],
-        'magenta': [255,0,255,1], 'maroon': [128,0,0,1],
-        'mediumaquamarine': [102,205,170,1], 'mediumblue': [0,0,205,1],
-        'mediumorchid': [186,85,211,1], 'mediumpurple': [147,112,219,1],
-        'mediumseagreen': [60,179,113,1], 'mediumslateblue': [123,104,238,1],
-        'mediumspringgreen': [0,250,154,1], 'mediumturquoise': [72,209,204,1],
-        'mediumvioletred': [199,21,133,1], 'midnightblue': [25,25,112,1],
-        'mintcream': [245,255,250,1], 'mistyrose': [255,228,225,1],
-        'moccasin': [255,228,181,1], 'navajowhite': [255,222,173,1],
-        'navy': [0,0,128,1], 'oldlace': [253,245,230,1],
-        'olive': [128,128,0,1], 'olivedrab': [107,142,35,1],
-        'orange': [255,165,0,1], 'orangered': [255,69,0,1],
-        'orchid': [218,112,214,1], 'palegoldenrod': [238,232,170,1],
-        'palegreen': [152,251,152,1], 'paleturquoise': [175,238,238,1],
-        'palevioletred': [219,112,147,1], 'papayawhip': [255,239,213,1],
-        'peachpuff': [255,218,185,1], 'peru': [205,133,63,1],
-        'pink': [255,192,203,1], 'plum': [221,160,221,1],
-        'powderblue': [176,224,230,1], 'purple': [128,0,128,1],
-        'red': [255,0,0,1], 'rosybrown': [188,143,143,1],
-        'royalblue': [65,105,225,1], 'saddlebrown': [139,69,19,1],
-        'salmon': [250,128,114,1], 'sandybrown': [244,164,96,1],
-        'seagreen': [46,139,87,1], 'seashell': [255,245,238,1],
-        'sienna': [160,82,45,1], 'silver': [192,192,192,1],
-        'skyblue': [135,206,235,1], 'slateblue': [106,90,205,1],
-        'slategray': [112,128,144,1], 'slategrey': [112,128,144,1],
-        'snow': [255,250,250,1], 'springgreen': [0,255,127,1],
-        'steelblue': [70,130,180,1], 'tan': [210,180,140,1],
-        'teal': [0,128,128,1], 'thistle': [216,191,216,1],
-        'tomato': [255,99,71,1], 'turquoise': [64,224,208,1],
-        'violet': [238,130,238,1], 'wheat': [245,222,179,1],
-        'white': [255,255,255,1], 'whitesmoke': [245,245,245,1],
-        'yellow': [255,255,0,1], 'yellowgreen': [154,205,50,1]
-    };
-
-    function clampCssByte(i) {  // Clamp to integer 0 .. 255.
-        i = Math.round(i);  // Seems to be what Chrome does (vs truncation).
-        return i < 0 ? 0 : i > 255 ? 255 : i;
-    }
-
-    function clampCssAngle(i) {  // Clamp to integer 0 .. 360.
-        i = Math.round(i);  // Seems to be what Chrome does (vs truncation).
-        return i < 0 ? 0 : i > 360 ? 360 : i;
-    }
-
-    function clampCssFloat(f) {  // Clamp to float 0.0 .. 1.0.
-        return f < 0 ? 0 : f > 1 ? 1 : f;
-    }
-
-    function parseCssInt(str) {  // int or percentage.
-        if (str.length && str.charAt(str.length - 1) === '%') {
-            return clampCssByte(parseFloat(str) / 100 * 255);
-        }
-        return clampCssByte(parseInt(str, 10));
-    }
-
-    function parseCssFloat(str) {  // float or percentage.
-        if (str.length && str.charAt(str.length - 1) === '%') {
-            return clampCssFloat(parseFloat(str) / 100);
-        }
-        return clampCssFloat(parseFloat(str));
-    }
-
-    function cssHueToRgb(m1, m2, h) {
-        if (h < 0) {
-            h += 1;
-        }
-        else if (h > 1) {
-            h -= 1;
-        }
-
-        if (h * 6 < 1) {
-            return m1 + (m2 - m1) * h * 6;
-        }
-        if (h * 2 < 1) {
-            return m2;
-        }
-        if (h * 3 < 2) {
-            return m1 + (m2 - m1) * (2/3 - h) * 6;
-        }
-        return m1;
-    }
-
-    function lerp(a, b, p) {
-        return a + (b - a) * p;
-    }
-
-    /**
-     * @param {string} colorStr
-     * @return {Array.<number>}
-     * @memberOf module:zrender/util/color
-     */
-    function parse(colorStr) {
-        if (!colorStr) {
-            return;
-        }
-        // colorStr may be not string
-        colorStr = colorStr + '';
-        // Remove all whitespace, not compliant, but should just be more accepting.
-        var str = colorStr.replace(/ /g, '').toLowerCase();
-
-        // Color keywords (and transparent) lookup.
-        if (str in kCSSColorTable) {
-            return kCSSColorTable[str].slice();  // dup.
-        }
-
-        // #abc and #abc123 syntax.
-        if (str.charAt(0) === '#') {
-            if (str.length === 4) {
-                var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.
-                if (!(iv >= 0 && iv <= 0xfff)) {
-                    return;  // Covers NaN.
-                }
-                return [
-                    ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
-                    (iv & 0xf0) | ((iv & 0xf0) >> 4),
-                    (iv & 0xf) | ((iv & 0xf) << 4),
-                    1
-                ];
-            }
-            else if (str.length === 7) {
-                var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.
-                if (!(iv >= 0 && iv <= 0xffffff)) {
-                    return;  // Covers NaN.
-                }
-                return [
-                    (iv & 0xff0000) >> 16,
-                    (iv & 0xff00) >> 8,
-                    iv & 0xff,
-                    1
-                ];
-            }
-
-            return;
-        }
-        var op = str.indexOf('('), ep = str.indexOf(')');
-        if (op !== -1 && ep + 1 === str.length) {
-            var fname = str.substr(0, op);
-            var params = str.substr(op + 1, ep - (op + 1)).split(',');
-            var alpha = 1;  // To allow case fallthrough.
-            switch (fname) {
-                case 'rgba':
-                    if (params.length !== 4) {
-                        return;
-                    }
-                    alpha = parseCssFloat(params.pop()); // jshint ignore:line
-                // Fall through.
-                case 'rgb':
-                    if (params.length !== 3) {
-                        return;
-                    }
-                    return [
-                        parseCssInt(params[0]),
-                        parseCssInt(params[1]),
-                        parseCssInt(params[2]),
-                        alpha
-                    ];
-                case 'hsla':
-                    if (params.length !== 4) {
-                        return;
-                    }
-                    params[3] = parseCssFloat(params[3]);
-                    return hsla2rgba(params);
-                case 'hsl':
-                    if (params.length !== 3) {
-                        return;
-                    }
-                    return hsla2rgba(params);
-                default:
-                    return;
-            }
-        }
-
-        return;
-    }
-
-    /**
-     * @param {Array.<number>} hsla
-     * @return {Array.<number>} rgba
-     */
-    function hsla2rgba(hsla) {
-        var h = (((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.
-        var s = parseCssFloat(hsla[1]);
-        var l = parseCssFloat(hsla[2]);
-        var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
-        var m1 = l * 2 - m2;
-
-        var rgba = [
-            clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255),
-            clampCssByte(cssHueToRgb(m1, m2, h) * 255),
-            clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255)
-        ];
-
-        if (hsla.length === 4) {
-            rgba[3] = hsla[3];
-        }
-
-        return rgba;
-    }
-
-    /**
-     * @param {Array.<number>} rgba
-     * @return {Array.<number>} hsla
-     */
-    function rgba2hsla(rgba) {
-        if (!rgba) {
-            return;
-        }
-
-        // RGB from 0 to 255
-        var R = rgba[0] / 255;
-        var G = rgba[1] / 255;
-        var B = rgba[2] / 255;
-
-        var vMin = Math.min(R, G, B); // Min. value of RGB
-        var vMax = Math.max(R, G, B); // Max. value of RGB
-        var delta = vMax - vMin; // Delta RGB value
-
-        var L = (vMax + vMin) / 2;
-        var H;
-        var S;
-        // HSL results from 0 to 1
-        if (delta === 0) {
-            H = 0;
-            S = 0;
-        }
-        else {
-            if (L < 0.5) {
-                S = delta / (vMax + vMin);
-            }
-            else {
-                S = delta / (2 - vMax - vMin);
-            }
-
-            var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta;
-            var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta;
-            var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta;
-
-            if (R === vMax) {
-                H = deltaB - deltaG;
-            }
-            else if (G === vMax) {
-                H = (1 / 3) + deltaR - deltaB;
-            }
-            else if (B === vMax) {
-                H = (2 / 3) + deltaG - deltaR;
-            }
-
-            if (H < 0) {
-                H += 1;
-            }
-
-            if (H > 1) {
-                H -= 1;
-            }
-        }
-
-        var hsla = [H * 360, S, L];
-
-        if (rgba[3] != null) {
-            hsla.push(rgba[3]);
-        }
-
-        return hsla;
-    }
-
-    /**
-     * @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;
-                }
-            }
-            return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
-        }
-    }
-
-    /**
-     * @param {string} color
-     * @return {string}
-     * @memberOf module:zrender/util/color
-     */
-    function toHex(color, level) {
-        var colorArr = parse(color);
-        if (colorArr) {
-            return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1);
-        }
-    }
-
-    /**
-     * Map value to color. Faster than mapToColor methods because color is represented by rgba array
-     * @param {number} normalizedValue A float between 0 and 1.
-     * @param {Array.<Array.<number>>} colors List of rgba color array
-     * @param {Array.<number>} [out] Mapped gba color array
-     * @return {Array.<number>}
-     */
-    function fastMapToColor(normalizedValue, colors, out) {
-        if (!(colors && colors.length)
-            || !(normalizedValue >= 0 && normalizedValue <= 1)
-        ) {
-            return;
-        }
-        out = out || [0, 0, 0, 0];
-        var value = normalizedValue * (colors.length - 1);
-        var leftIndex = Math.floor(value);
-        var rightIndex = Math.ceil(value);
-        var leftColor = colors[leftIndex];
-        var rightColor = colors[rightIndex];
-        var dv = value - leftIndex;
-        out[0] = clampCssByte(lerp(leftColor[0], rightColor[0], dv));
-        out[1] = clampCssByte(lerp(leftColor[1], rightColor[1], dv));
-        out[2] = clampCssByte(lerp(leftColor[2], rightColor[2], dv));
-        out[3] = clampCssByte(lerp(leftColor[3], rightColor[3], dv));
-        return out;
-    }
-    /**
-     * @param {number} normalizedValue A float between 0 and 1.
-     * @param {Array.<string>} colors Color list.
-     * @param {boolean=} fullOutput Default false.
-     * @return {(string|Object)} Result color. If fullOutput,
-     *                           return {color: ..., leftIndex: ..., rightIndex: ..., value: ...},
-     * @memberOf module:zrender/util/color
-     */
-    function mapToColor(normalizedValue, colors, fullOutput) {
-        if (!(colors && colors.length)
-            || !(normalizedValue >= 0 && normalizedValue <= 1)
-        ) {
-            return;
-        }
-
-        var value = normalizedValue * (colors.length - 1);
-        var leftIndex = Math.floor(value);
-        var rightIndex = Math.ceil(value);
-        var leftColor = parse(colors[leftIndex]);
-        var rightColor = parse(colors[rightIndex]);
-        var dv = value - leftIndex;
-
-        var color = stringify(
-            [
-                clampCssByte(lerp(leftColor[0], rightColor[0], dv)),
-                clampCssByte(lerp(leftColor[1], rightColor[1], dv)),
-                clampCssByte(lerp(leftColor[2], rightColor[2], dv)),
-                clampCssFloat(lerp(leftColor[3], rightColor[3], dv))
-            ],
-            'rgba'
-        );
-
-        return fullOutput
-            ? {
-                color: color,
-                leftIndex: leftIndex,
-                rightIndex: rightIndex,
-                value: value
-            }
-            : color;
-    }
-
-    /**
-     * @param {Array<number>} interval  Array length === 2,
-     *                                  each item is normalized value ([0, 1]).
-     * @param {Array.<string>} colors Color list.
-     * @return {Array.<Object>} colors corresponding to the interval,
-     *                          each item is {color: 'xxx', offset: ...}
-     *                          where offset is between 0 and 1.
-     * @memberOf module:zrender/util/color
-     */
-    function mapIntervalToColor(interval, colors) {
-        if (interval.length !== 2 || interval[1] < interval[0]) {
-            return;
-        }
-
-        var info0 = mapToColor(interval[0], colors, true);
-        var info1 = mapToColor(interval[1], colors, true);
-
-        var result = [{color: info0.color, offset: 0}];
-
-        var during = info1.value - info0.value;
-        var start = Math.max(info0.value, info0.rightIndex);
-        var end = Math.min(info1.value, info1.leftIndex);
-
-        for (var i = start; during > 0 && i <= end; i++) {
-            result.push({
-                color: colors[i],
-                offset: (i - info0.value) / during
-            });
-        }
-        result.push({color: info1.color, offset: 1});
-
-        return result;
-    }
-
-    /**
-     * @param {string} color
-     * @param {number=} h 0 ~ 360, ignore when null.
-     * @param {number=} s 0 ~ 1, ignore when null.
-     * @param {number=} l 0 ~ 1, ignore when null.
-     * @return {string} Color string in rgba format.
-     * @memberOf module:zrender/util/color
-     */
-    function modifyHSL(color, h, s, l) {
-        color = parse(color);
-
-        if (color) {
-            color = rgba2hsla(color);
-            h != null && (color[0] = clampCssAngle(h));
-            s != null && (color[1] = parseCssFloat(s));
-            l != null && (color[2] = parseCssFloat(l));
-
-            return stringify(hsla2rgba(color), 'rgba');
-        }
-    }
-
-    /**
-     * @param {string} color
-     * @param {number=} alpha 0 ~ 1
-     * @return {string} Color string in rgba format.
-     * @memberOf module:zrender/util/color
-     */
-    function modifyAlpha(color, alpha) {
-        color = parse(color);
-
-        if (color && alpha != null) {
-            color[3] = clampCssFloat(alpha);
-            return stringify(color, 'rgba');
-        }
-    }
-
-    /**
-     * @param {Array.<string>} colors Color list.
-     * @param {string} type 'rgba', 'hsva', ...
-     * @return {string} Result color.
-     */
-    function stringify(arrColor, type) {
-        if (type === 'rgb' || type === 'hsv' || type === 'hsl') {
-            arrColor = arrColor.slice(0, 3);
-        }
-        return type + '(' + arrColor.join(',') + ')';
-    }
-
-    return {
-        parse: parse,
-        lift: lift,
-        toHex: toHex,
-        fastMapToColor: fastMapToColor,
-        mapToColor: mapToColor,
-        mapIntervalToColor: mapIntervalToColor,
-        modifyHSL: modifyHSL,
-        modifyAlpha: modifyAlpha,
-        stringify: stringify
-    };
-});
-
-
-/**
- * @module echarts/animation/Animator
- */
-define('zrender/animation/Animator',['require','./Clip','../tool/color','../core/util'],function (require) {
-
-    var Clip = require('./Clip');
-    var color = require('../tool/color');
-    var util = require('../core/util');
-    var isArrayLike = util.isArrayLike;
-
-    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 = 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
-                    );
-                }
-            }
-        }
-    }
-
-    function fillArr(arr0, arr1, arrDim) {
-        var arr0Len = arr0.length;
-        var arr1Len = arr1.length;
-        if (arr0Len === arr1Len) {
-            return;
-        }
-        // FIXME Not work for TypedArray
-        var isPreviousLarger = arr0Len > arr1Len;
-        if (isPreviousLarger) {
-            // Cut the previous
-            arr0.length = arr1Len;
-        }
-        else {
-            // Fill the previous
-            for (var i = arr0Len; i < arr1Len; i++) {
-                arr0.push(
-                    arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])
-                );
-            }
-        }
-    }
-
-    /**
-     * @param  {Array} arr0
-     * @param  {Array} arr1
-     * @param  {number} arrDim
-     * @return {boolean}
-     */
-    function isArraySame(arr0, arr1, arrDim) {
-        if (arr0 === arr1) {
-            return true;
-        }
-        var len = arr0.length;
-        if (len !== arr1.length) {
-            return false;
-        }
-        if (arrDim === 1) {
-            for (var i = 0; i < len; i++) {
-                if (arr0[i] !== arr1[i]) {
-                    return false;
-                }
-            }
-        }
-        else {
-            var len2 = arr0[0].length;
-            for (var i = 0; i < len; i++) {
-                for (var j = 0; j < len2; j++) {
-                    if (arr0[i][j] !== arr1[i][j]) {
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * 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
-     */
-    function catmullRomInterpolateArray(
-        p0, p1, p2, p3, t, t2, t3, out, arrDim
-    ) {
-        var len = p0.length;
-        if (arrDim == 1) {
-            for (var i = 0; i < len; i++) {
-                out[i] = catmullRomInterpolate(
-                    p0[i], p1[i], p2[i], p3[i], t, t2, t3
-                );
-            }
-        }
-        else {
-            var len2 = p0[0].length;
-            for (var i = 0; i < len; i++) {
-                for (var j = 0; j < len2; j++) {
-                    out[i][j] = catmullRomInterpolate(
-                        p0[i][j], p1[i][j], p2[i][j], p3[i][j],
-                        t, t2, t3
-                    );
-                }
-            }
-        }
-    }
-
-    /**
-     * 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}
-     */
-    function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
-        var v0 = (p2 - p0) * 0.5;
-        var v1 = (p3 - p1) * 0.5;
-        return (2 * (p1 - p2) + v0 + v1) * t3
-                + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
-                + v0 * t + p1;
-    }
-
-    function cloneValue(value) {
-        if (isArrayLike(value)) {
-            var len = value.length;
-            if (isArrayLike(value[0])) {
-                var ret = [];
-                for (var i = 0; i < len; i++) {
-                    ret.push(arraySlice.call(value[i]));
-                }
-                return ret;
-            }
-
-            return arraySlice.call(value);
-        }
-
-        return value;
-    }
-
-    function rgba2String(rgba) {
-        rgba[0] = Math.floor(rgba[0]);
-        rgba[1] = Math.floor(rgba[1]);
-        rgba[2] = Math.floor(rgba[2]);
-
-        return 'rgba(' + rgba.join(',') + ')';
-    }
-
-    function createTrackClip (animator, easing, oneTrackDone, keyframes, propName) {
-        var getter = animator._getter;
-        var setter = animator._setter;
-        var useSpline = easing === 'spline';
-
-        var trackLen = keyframes.length;
-        if (!trackLen) {
-            return;
-        }
-        // Guess data type
-        var firstVal = keyframes[0].value;
-        var isValueArray = isArrayLike(firstVal);
-        var isValueColor = false;
-        var isValueString = false;
-
-        // For vertices morphing
-        var arrDim = (
-                isValueArray
-                && isArrayLike(firstVal[0])
-            )
-            ? 2 : 1;
-        var trackMaxTime;
-        // Sort keyframe as ascending
-        keyframes.sort(function(a, b) {
-            return a.time - b.time;
-        });
-
-        trackMaxTime = keyframes[trackLen - 1].time;
-        // Percents of each keyframe
-        var kfPercents = [];
-        // Value of each keyframe
-        var kfValues = [];
-        var prevValue = keyframes[0].value;
-        var isAllValueEqual = true;
-        for (var i = 0; i < trackLen; i++) {
-            kfPercents.push(keyframes[i].time / trackMaxTime);
-            // Assume value is a color when it is a string
-            var value = keyframes[i].value;
-
-            // Check if value is equal, deep check if value is array
-            if (!((isValueArray && isArraySame(value, prevValue, arrDim))
-                || (!isValueArray && value === prevValue))) {
-                isAllValueEqual = false;
-            }
-            prevValue = value;
-
-            // Try converting a string to a color array
-            if (typeof value == 'string') {
-                var colorArray = color.parse(value);
-                if (colorArray) {
-                    value = colorArray;
-                    isValueColor = true;
-                }
-                else {
-                    isValueString = true;
-                }
-            }
-            kfValues.push(value);
-        }
-        if (isAllValueEqual) {
-            return;
-        }
-
-        if (isValueArray) {
-            var lastValue = kfValues[trackLen - 1];
-            // Polyfill array
-            for (var i = 0; i < trackLen - 1; i++) {
-                fillArr(kfValues[i], lastValue, arrDim);
-            }
-            fillArr(getter(animator._target, propName), lastValue, arrDim);
-        }
-
-        // Cache the key of last frame to speed up when
-        // animation playback is sequency
-        var lastFrame = 0;
-        var lastFramePercent = 0;
-        var start;
-        var w;
-        var p0;
-        var p1;
-        var p2;
-        var p3;
-
-        if (isValueColor) {
-            var rgba = [0, 0, 0, 0];
-        }
-
-        var onframe = function (target, percent) {
-            // Find the range keyframes
-            // kf1-----kf2---------current--------kf3
-            // find kf2 and kf3 and do interpolation
-            var frame;
-            if (percent < lastFramePercent) {
-                // Start from next key
-                start = Math.min(lastFrame + 1, trackLen - 1);
-                for (frame = start; frame >= 0; frame--) {
-                    if (kfPercents[frame] <= percent) {
-                        break;
-                    }
-                }
-                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;
-
-            var range = (kfPercents[frame + 1] - kfPercents[frame]);
-            if (range === 0) {
-                return;
-            }
-            else {
-                w = (percent - kfPercents[frame]) / range;
-            }
-            if (useSpline) {
-                p1 = kfValues[frame];
-                p0 = kfValues[frame === 0 ? frame : frame - 1];
-                p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1];
-                p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2];
-                if (isValueArray) {
-                    catmullRomInterpolateArray(
-                        p0, p1, p2, p3, w, w * w, w * w * w,
-                        getter(target, propName),
-                        arrDim
-                    );
-                }
-                else {
-                    var value;
-                    if (isValueColor) {
-                        value = catmullRomInterpolateArray(
-                            p0, p1, p2, p3, w, w * w, w * w * w,
-                            rgba, 1
-                        );
-                        value = rgba2String(rgba);
-                    }
-                    else if (isValueString) {
-                        // String is step(0.5)
-                        return interpolateString(p1, p2, w);
-                    }
-                    else {
-                        value = catmullRomInterpolate(
-                            p0, p1, p2, p3, w, w * w, w * w * w
-                        );
-                    }
-                    setter(
-                        target,
-                        propName,
-                        value
-                    );
-                }
-            }
-            else {
-                if (isValueArray) {
-                    interpolateArray(
-                        kfValues[frame], kfValues[frame + 1], w,
-                        getter(target, propName),
-                        arrDim
-                    );
-                }
-                else {
-                    var value;
-                    if (isValueColor) {
-                        interpolateArray(
-                            kfValues[frame], kfValues[frame + 1], w,
-                            rgba, 1
-                        );
-                        value = rgba2String(rgba);
-                    }
-                    else if (isValueString) {
-                        // String is step(0.5)
-                        return interpolateString(kfValues[frame], kfValues[frame + 1], w);
-                    }
-                    else {
-                        value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w);
-                    }
-                    setter(
-                        target,
-                        propName,
-                        value
-                    );
-                }
-            }
-        };
-
-        var clip = new Clip({
-            target: animator._target,
-            life: trackMaxTime,
-            loop: animator._loop,
-            delay: animator._delay,
-            onframe: onframe,
-            ondestroy: oneTrackDone
-        });
-
-        if (easing && easing !== 'spline') {
-            clip.easing = easing;
-        }
-
-        return clip;
-    }
-
-    /**
-     * @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 (!tracks[propName]) {
-                    tracks[propName] = [];
-                    // Invalid value
-                    var value = 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 value
-                    if (time !== 0) {
-                        tracks[propName].push({
-                            time: 0,
-                            value: cloneValue(value)
-                        });
-                    }
-                }
-                tracks[propName].push({
-                    time: time,
-                    value: props[propName]
-                });
-            }
-            return this;
-        },
-        /**
-         * 添加动画每一帧的回调函数
-         * @param  {Function} callback
-         * @return {module:zrender/animation/Animator}
-         */
-        during: function (callback) {
-            this._onframeList.push(callback);
-            return this;
-        },
-
-        _doneCallback: function () {
-            // Clear all tracks
-            this._tracks = {};
-            // Clear all clips
-            this._clipList.length = 0;
-
-            var doneList = this._doneList;
-            var len = doneList.length;
-            for (var i = 0; i < len; i++) {
-                doneList[i].call(this);
-            }
-        },
-        /**
-         * 开始执行动画
-         * @param  {string|Function} easing
-         *         动画缓动函数,详见{@link module:zrender/animation/easing}
-         * @return {module:zrender/animation/Animator}
-         */
-        start: function (easing) {
-
-            var self = this;
-            var clipCount = 0;
-
-            var oneTrackDone = function() {
-                clipCount--;
-                if (!clipCount) {
-                    self._doneCallback();
-                }
-            };
-
-            var lastClip;
-            for (var propName in this._tracks) {
-                var clip = createTrackClip(
-                    this, easing, oneTrackDone,
-                    this._tracks[propName], propName
-                );
-                if (clip) {
-                    this._clipList.push(clip);
-                    clipCount++;
-
-                    // If start after added to animation
-                    if (this.animation) {
-                        this.animation.addClip(clip);
-                    }
-
-                    lastClip = clip;
-                }
-            }
-
-            // Add during callback on the last clip
-            if (lastClip) {
-                var oldOnFrame = lastClip.onframe;
-                lastClip.onframe = function (target, percent) {
-                    oldOnFrame(target, percent);
-
-                    for (var i = 0; i < self._onframeList.length; i++) {
-                        self._onframeList[i](target, percent);
-                    }
-                };
-            }
-
-            if (!clipCount) {
-                this._doneCallback();
-            }
-            return this;
-        },
-        /**
-         * 停止动画
-         * @param {boolean} forwardToLast If move to last frame before stop
-         */
-        stop: function (forwardToLast) {
-            var clipList = this._clipList;
-            var animation = this.animation;
-            for (var i = 0; i < clipList.length; i++) {
-                var clip = clipList[i];
-                if (forwardToLast) {
-                    // Move to last frame before stop
-                    clip.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;
-        }
-    };
-
-    return Animator;
-});
-define('zrender/config',[],function () {
-    var dpr = 1;
-    // If in browser environment
-    if (typeof window !== 'undefined') {
-        dpr = Math.max(window.devicePixelRatio || 1, 1);
-    }
-    /**
-     * config默认配置项
-     * @exports zrender/config
-     * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
-     */
-    var config = {
-        /**
-         * debug日志选项:catchBrushException为true下有效
-         * 0 : 不生成debug数据,发布用
-         * 1 : 异常抛出,调试用
-         * 2 : 控制台输出,调试用
-         */
-        debugMode: 0,
-
-        // retina 屏幕优化
-        devicePixelRatio: dpr
-    };
-    return config;
-});
-
-
-define(
-    'zrender/core/log',['require','../config'],function (require) {
-        var config = require('../config');
-
-        /**
-         * @exports zrender/tool/log
-         * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
-         */
-        return function() {
-            if (config.debugMode === 0) {
-                return;
-            }
-            else if (config.debugMode == 1) {
-                for (var k in arguments) {
-                    throw new Error(arguments[k]);
-                }
-            }
-            else if (config.debugMode > 1) {
-                for (var k in arguments) {
-                    console.log(arguments[k]);
-                }
-            }
-        };
-
-        /* for debug
-        return function(mes) {
-            document.getElementById('wrong-message').innerHTML =
-                mes + ' ' + (new Date() - 0)
-                + '<br/>'
-                + document.getElementById('wrong-message').innerHTML;
-        };
-        */
-    }
-);
-
-/**
- * @module zrender/mixin/Animatable
- */
-define('zrender/mixin/Animatable',['require','../animation/Animator','../core/util','../core/log'],function(require) {
-
-
-
-    var Animator = require('../animation/Animator');
-    var util = require('../core/util');
-    var isString = util.isString;
-    var isFunction = util.isFunction;
-    var isObject = util.isObject;
-    var log = require('../core/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} path 需要添加动画的属性获取路径,可以通过a.b.c来获取深层的属性
-         * @param {boolean} [loop] 动画是否循环
-         * @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;
-                // If animating shape
-                animatingShape = pathSplitted[0] === 'shape';
-                for (var i = 0, l = pathSplitted.length; i < l; i++) {
-                    if (!prop) {
-                        continue;
-                    }
-                    prop = prop[pathSplitted[i]];
-                }
-                if (prop) {
-                    target = prop;
-                }
-            }
-            else {
-                target = el;
-            }
-
-            if (!target) {
-                log(
-                    'Property "'
-                    + path
-                    + '" is not existed in element '
-                    + el.id
-                );
-                return;
-            }
-
-            var animators = el.animators;
-
-            var animator = new Animator(target, loop);
-
-            animator.during(function (target) {
-                el.dirty(animatingShape);
-            })
-            .done(function () {
-                // FIXME Animator will not be removed if use `Animator#stop` to stop animation
-                animators.splice(util.indexOf(animators, animator), 1);
-            });
-
-            animators.push(animator);
-
-            // If animate after added to the zrender
-            if (zr) {
-                zr.animation.addAnimator(animator);
-            }
-
-            return animator;
-        },
-
-        /**
-         * 停止动画
-         * @param {boolean} forwardToLast If move to last frame before stop
-         */
-        stopAnimation: function (forwardToLast) {
-            var animators = this.animators;
-            var len = animators.length;
-            for (var i = 0; i < len; i++) {
-                animators[i].stop(forwardToLast);
-            }
-            animators.length = 0;
-
-            return this;
-        },
-
-        /**
-         * @param {Object} target
-         * @param {number} [time=500] Time in ms
-         * @param {string} [easing='linear']
-         * @param {number} [delay=0]
-         * @param {Function} [callback]
-         *
-         * @example
-         *  // Animate position
-         *  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 })
-         */
-         // TODO Return animation key
-        animateTo: function (target, time, delay, easing, callback) {
-            // animateTo(target, time, easing, callback);
-            if (isString(delay)) {
-                callback = easing;
-                easing = delay;
-                delay = 0;
-            }
-            // animateTo(target, time, delay, callback);
-            else if (isFunction(easing)) {
-                callback = easing;
-                easing = 'linear';
-                delay = 0;
-            }
-            // animateTo(target, time, callback);
-            else if (isFunction(delay)) {
-                callback = delay;
-                delay = 0;
-            }
-            // animateTo(target, callback)
-            else if (isFunction(time)) {
-                callback = time;
-                time = 500;
-            }
-            // animateTo(target)
-            else if (!time) {
-                time = 500;
-            }
-            // Stop all previous animations
-            this.stopAnimation();
-            this._animateToShallow('', this, target, time, delay, easing, callback);
-
-            // Animators may be removed immediately after start
-            // if there is nothing to animate
-            var animators = this.animators.slice();
-            var count = animators.length;
-            function done() {
-                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 changed
-            for (var i = 0; i < animators.length; i++) {
-                animators[i]
-                    .done(done)
-                    .start(easing);
-            }
-        },
-
-        /**
-         * @private
-         * @param {string} path=''
-         * @param {Object} source=this
-         * @param {Object} target
-         * @param {number} [time=500]
-         * @param {number} [delay=0]
-         *
-         * @example
-         *  // Animate position
-         *  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)
-         */
-        _animateToShallow: function (path, source, target, time, delay) {
-            var objShallow = {};
-            var propertyCount = 0;
-            for (var name in target) {
-                if (source[name] != null) {
-                    if (isObject(target[name]) && !util.isArrayLike(target[name])) {
-                        this._animateToShallow(
-                            path ? path + '.' + name : name,
-                            source[name],
-                            target[name],
-                            time,
-                            delay
-                        );
-                    }
-                    else {
-                        objShallow[name] = target[name];
-                        propertyCount++;
-                    }
-                }
-                else if (target[name] != null) {
-                    // Attr directly if not has property
-                    // FIXME, if some property not needed for element ?
-                    if (!path) {
-                        this.attr(name, target[name]);
-                    }
-                    else {  // Shape or style
-                        var props = {};
-                        props[path] = {};
-                        props[path][name] = target[name];
-                        this.attr(props);
-                    }
-                }
-            }
-
-            if (propertyCount > 0) {
-                this.animate(path, false)
-                    .when(time == null ? 500 : time, objShallow)
-                    .delay(delay || 0);
-            }
-
-            return this;
-        }
-    };
-
-    return Animatable;
-});
-/**
- * @module zrender/Element
- */
-define('zrender/Element',['require','./core/guid','./mixin/Eventful','./mixin/Transformable','./mixin/Animatable','./core/util'],function(require) {
-
-
-    var guid = require('./core/guid');
-    var Eventful = require('./mixin/Eventful');
-    var Transformable = require('./mixin/Transformable');
-    var Animatable = require('./mixin/Animatable');
-    var zrUtil = require('./core/util');
-
-    /**
-     * @alias module:zrender/Element
-     * @constructor
-     * @extends {module:zrender/mixin/Animatable}
-     * @extends {module:zrender/mixin/Transformable}
-     * @extends {module:zrender/mixin/Eventful}
-     */
-    var Element = function (opts) {
-
-        Transformable.call(this, opts);
-        Eventful.call(this, opts);
-        Animatable.call(this, opts);
-
-        /**
-         * 画布元素ID
-         * @type {string}
-         */
-        this.id = opts.id || guid();
-    };
-
-    Element.prototype = {
-
-        /**
-         * 元素类型
-         * Element type
-         * @type {string}
-         */
-        type: 'element',
-
-        /**
-         * 元素名字
-         * Element name
-         * @type {string}
-         */
-        name: '',
-
-        /**
-         * ZRender 实例对象,会在 element 添加到 zrender 实例中后自动赋值
-         * ZRender instance will be assigned when element is associated with zrender
-         * @name module:/zrender/Element#__zr
-         * @type {module:zrender/ZRender}
-         */
-        __zr: null,
-
-        /**
-         * 图形是否忽略,为true时忽略图形的绘制以及事件触发
-         * If ignore drawing and events of the element object
-         * @name module:/zrender/Element#ignore
-         * @type {boolean}
-         * @default false
-         */
-        ignore: false,
-
-        /**
-         * 用于裁剪的路径(shape),所有 Group 内的路径在绘制时都会被这个路径裁剪
-         * 该路径会继承被裁减对象的变换
-         * @type {module:zrender/graphic/Path}
-         * @see http://www.w3.org/TR/2dcontext/#clipping-region
-         * @readOnly
-         */
-        clipPath: null,
-
-        /**
-         * Drift element
-         * @param  {number} dx dx on the global space
-         * @param  {number} dy dy on the global space
-         */
-        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();
-        },
-
-        /**
-         * Hook before update
-         */
-        beforeUpdate: function () {},
-        /**
-         * Hook after update
-         */
-        afterUpdate: function () {},
-        /**
-         * Update each frame
-         */
-        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') {
-                // Copy the array
-                if (value) {
-                    var target = 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 (typeof key === 'string') {
-                this.attrKV(key, value);
-            }
-            else if (zrUtil.isObject(key)) {
-                for (var name in key) {
-                    if (key.hasOwnProperty(name)) {
-                        this.attrKV(name, key[name]);
-                    }
-                }
-            }
-            this.dirty();
-
-            return this;
-        },
-
-        /**
-         * @param {module:zrender/graphic/Path} clipPath
-         */
-        setClipPath: function (clipPath) {
-            var zr = this.__zr;
-            if (zr) {
-                clipPath.addSelfToZr(zr);
-            }
-
-            // Remove previous clip path
-            if (this.clipPath && this.clipPath !== clipPath) {
-                this.removeClipPath();
-            }
-
-            this.clipPath = clipPath;
-            clipPath.__zr = zr;
-            clipPath.__clipTarget = this;
-
-            this.dirty();
-        },
-
-        /**
-         */
-        removeClipPath: function () {
-            var clipPath = this.clipPath;
-            if (clipPath) {
-                if (clipPath.__zr) {
-                    clipPath.removeSelfFromZr(clipPath.__zr);
-                }
-
-                clipPath.__zr = null;
-                clipPath.__clipTarget = null;
-                this.clipPath = null;
-
-                this.dirty();
-            }
-        },
-
-        /**
-         * 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;
-            // 添加动画
-            var animators = this.animators;
-            if (animators) {
-                for (var i = 0; i < animators.length; i++) {
-                    zr.animation.addAnimator(animators[i]);
-                }
-            }
-
-            if (this.clipPath) {
-                this.clipPath.addSelfToZr(zr);
-            }
-        },
-
-        /**
-         * 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;
-            // 移除动画
-            var animators = this.animators;
-            if (animators) {
-                for (var i = 0; i < animators.length; i++) {
-                    zr.animation.removeAnimator(animators[i]);
-                }
-            }
-
-            if (this.clipPath) {
-                this.clipPath.removeSelfFromZr(zr);
-            }
-        }
-    };
-
-    zrUtil.mixin(Element, Animatable);
-    zrUtil.mixin(Element, Transformable);
-    zrUtil.mixin(Element, Eventful);
-
-    return Element;
-});
-/**
- * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上
- * @module zrender/graphic/Group
- * @example
- *     var Group = require('zrender/container/Group');
- *     var Circle = require('zrender/graphic/shape/Circle');
- *     var g = new Group();
- *     g.position[0] = 100;
- *     g.position[1] = 100;
- *     g.add(new Circle({
- *         style: {
- *             x: 100,
- *             y: 100,
- *             r: 20,
- *         }
- *     }));
- *     zr.add(g);
- */
-define('zrender/container/Group',['require','../core/util','../Element','../core/BoundingRect'],function (require) {
-
-    var zrUtil = require('../core/util');
-    var Element = require('../Element');
-    var BoundingRect = require('../core/BoundingRect');
-
-    /**
-     * @alias module:zrender/graphic/Group
-     * @constructor
-     * @extends module:zrender/mixin/Transformable
-     * @extends module:zrender/mixin/Eventful
-     */
-    var Group = function (opts) {
-
-        opts = opts || {};
-
-        Element.call(this, opts);
-
-        for (var key in opts) {
-            this[key] = opts[key];
-        }
-
-        this._children = [];
-
-        this.__storage = null;
-
-        this.__dirty = true;
-    };
-
-    Group.prototype = {
-
-        constructor: Group,
-
-        /**
-         * @type {string}
-         */
-        type: 'group',
-
-        /**
-         * @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.addToMap(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 = zrUtil.indexOf(children, child);
-            if (idx < 0) {
-                return this;
-            }
-            children.splice(idx, 1);
-
-            child.parent = null;
-
-            if (storage) {
-
-                storage.delFromMap(child.id);
-
-                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.delFromMap(child.id);
-                    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.addToMap(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.delFromMap(child.id);
-                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) {
-            // TODO Caching
-            // TODO Transform
-            var rect = null;
-            var tmpRect = new BoundingRect(0, 0, 0, 0);
-            var children = includeChildren || this._children;
-            var tmpMat = [];
-
-            for (var i = 0; i < children.length; i++) {
-                var child = children[i];
-                if (child.ignore || child.invisible) {
-                    continue;
-                }
-
-                var childRect = child.getBoundingRect();
-                var transform = child.getLocalTransform(tmpMat);
-                if (transform) {
-                    tmpRect.copy(childRect);
-                    tmpRect.applyTransform(transform);
-                    rect = rect || tmpRect.clone();
-                    rect.union(tmpRect);
-                }
-                else {
-                    rect = rect || childRect.clone();
-                    rect.union(childRect);
-                }
-            }
-            return rect || tmpRect;
-        }
-    };
-
-    zrUtil.inherits(Group, Element);
-
-    return Group;
-});
-define('echarts/view/Component',['require','zrender/container/Group','../util/component','../util/clazz'],function (require) {
-
-    var Group = require('zrender/container/Group');
-    var componentUtil = require('../util/component');
-    var clazzUtil = require('../util/clazz');
-
-    var Component = function () {
-        /**
-         * @type {module:zrender/container/Group}
-         * @readOnly
-         */
-        this.group = new Group();
-
-        /**
-         * @type {string}
-         * @readOnly
-         */
-        this.uid = componentUtil.getUID('viewComponent');
-    };
-
-    Component.prototype = {
-
-        constructor: Component,
-
-        init: function (ecModel, api) {},
-
-        render: function (componentModel, ecModel, api, payload) {},
-
-        dispose: function () {}
-    };
-
-    var componentProto = Component.prototype;
-    componentProto.updateView
-        = componentProto.updateLayout
-        = componentProto.updateVisual
-        = function (seriesModel, ecModel, api, payload) {
-            // Do nothing;
-        };
-    // Enable Component.extend.
-    clazzUtil.enableClassExtend(Component);
-
-    // Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
-    clazzUtil.enableClassManagement(Component, {registerWhenExtend: true});
-
-    return Component;
-});
-define('echarts/view/Chart',['require','zrender/container/Group','../util/component','../util/clazz'],function (require) {
-
-    var Group = require('zrender/container/Group');
-    var componentUtil = require('../util/component');
-    var clazzUtil = require('../util/clazz');
-
-    function Chart() {
-
-        /**
-         * @type {module:zrender/container/Group}
-         * @readOnly
-         */
-        this.group = new Group();
-
-        /**
-         * @type {string}
-         * @readOnly
-         */
-        this.uid = componentUtil.getUID('viewChart');
-    }
-
-    Chart.prototype = {
-
-        type: 'chart',
-
-        /**
-         * Init the chart
-         * @param  {module:echarts/model/Global} ecModel
-         * @param  {module:echarts/ExtensionAPI} api
-         */
-        init: function (ecModel, api) {},
-
-        /**
-         * Render the chart
-         * @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) {},
-
-        /**
-         * Highlight series or specified data item
-         * @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');
-        },
-
-        /**
-         * Downplay series or specified data item
-         * @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');
-        },
-
-        /**
-         * Remove self
-         * @param  {module:echarts/model/Global} ecModel
-         * @param  {module:echarts/ExtensionAPI} api
-         */
-        remove: function (ecModel, api) {
-            this.group.removeAll();
-        },
-
-        /**
-         * Dispose self
-         * @param  {module:echarts/model/Global} ecModel
-         * @param  {module:echarts/ExtensionAPI} api
-         */
-        dispose: function () {}
-    };
-
-    var chartProto = Chart.prototype;
-    chartProto.updateView
-        = chartProto.updateLayout
-        = chartProto.updateVisual
-        = function (seriesModel, ecModel, api, payload) {
-            this.render(seriesModel, ecModel, api, payload);
-        };
-
-    /**
-     * Set state of single element
-     * @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'
-     * @inner
-     */
-    function toggleHighlight(data, payload, state) {
-        if (payload.dataIndex != null) {
-            var el = data.getItemGraphicEl(payload.dataIndex);
-            elSetState(el, state);
-        }
-        else if (payload.name) {
-            var dataIndex = data.indexOfName(payload.name);
-            var el = data.getItemGraphicEl(dataIndex);
-            elSetState(el, state);
-        }
-        else {
-            data.eachItemGraphicEl(function (el) {
-                elSetState(el, state);
-            });
-        }
-    }
-
-    // Enable Chart.extend.
-    clazzUtil.enableClassExtend(Chart);
-
-    // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
-    clazzUtil.enableClassManagement(Chart, {registerWhenExtend: true});
-
-    return Chart;
-});
-/**
- * @module zrender/graphic/Style
- */
-
-define('zrender/graphic/Style',['require'],function (require) {
-
-    var STYLE_LIST_COMMON = [
-        'lineCap', 'lineJoin', 'miterLimit',
-        'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'shadowColor'
-    ];
-
-    var Style = function (opts) {
-        this.extendFrom(opts);
-    };
-
-    Style.prototype = {
-
-        constructor: Style,
-
-        /**
-         * @type {string}
-         */
-        fill: '#000000',
-
-        /**
-         * @type {string}
-         */
-        stroke: null,
-
-        /**
-         * @type {number}
-         */
-        opacity: 1,
-
-        /**
-         * @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,
-
-        /**
-         * @type {string}
-         */
-        textFill: '#000',
-
-        /**
-         * @type {string}
-         */
-        textStroke: null,
-
-        /**
-         * 'inside', 'left', 'right', 'top', 'bottom'
-         * [x, y]
-         * @type {string|Array.<number>}
-         * @default 'inside'
-         */
-        textPosition: 'inside',
-
-        /**
-         * @type {string}
-         */
-        textBaseline: null,
-
-        /**
-         * @type {string}
-         */
-        textAlign: null,
-
-        /**
-         * @type {number}
-         */
-        textDistance: 5,
-
-        /**
-         * @type {number}
-         */
-        textShadowBlur: 0,
-
-        /**
-         * @type {number}
-         */
-        textShadowOffsetX: 0,
-
-        /**
-         * @type {number}
-         */
-        textShadowOffsetY: 0,
-
-        /**
-         * @param {CanvasRenderingContext2D} ctx
-         */
-        bind: function (ctx, el) {
-            var fill = this.fill;
-            var stroke = this.stroke;
-            for (var i = 0; i < STYLE_LIST_COMMON.length; i++) {
-                var styleName = STYLE_LIST_COMMON[i];
-
-                if (this[styleName] != null) {
-                    ctx[styleName] = this[styleName];
-                }
-            }
-            if (stroke != null) {
-                var lineWidth = this.lineWidth;
-                ctx.lineWidth = lineWidth / (
-                    (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1
-                );
-            }
-            if (fill != null) {
-                 // Use canvas gradient if has
-                ctx.fillStyle = fill.canvasGradient ? fill.canvasGradient : fill;
-            }
-            if (stroke != null) {
-                 // Use canvas gradient if has
-                ctx.strokeStyle = stroke.canvasGradient ? stroke.canvasGradient : stroke;
-            }
-            this.opacity != null && (ctx.globalAlpha = this.opacity);
-        },
-
-        /**
-         * Extend from other style
-         * @param {zrender/graphic/Style} otherStyle
-         * @param {boolean} overwrite
-         */
-        extendFrom: function (otherStyle, overwrite) {
-            if (otherStyle) {
-                var target = this;
-                for (var name in otherStyle) {
-                    if (otherStyle.hasOwnProperty(name)
-                        && (overwrite || ! target.hasOwnProperty(name))
-                    ) {
-                        target[name] = otherStyle[name];
-                    }
-                }
-            }
-        },
-
-        /**
-         * Batch setting style with a given object
-         * @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;
-        }
-    };
-
-    var styleProto = Style.prototype;
-    var name;
-    var i;
-    for (i = 0; i < STYLE_LIST_COMMON.length; i++) {
-        name = STYLE_LIST_COMMON[i];
-        if (!(name in styleProto)) {
-            styleProto[name] = null;
-        }
-    }
-
-    return Style;
-});
-/**
- * Mixin for drawing text in a element bounding rect
- * @module zrender/mixin/RectText
- */
-
-define('zrender/graphic/mixin/RectText',['require','../../contain/text','../../core/BoundingRect'],function (require) {
-
-    var textContain = require('../../contain/text');
-    var BoundingRect = require('../../core/BoundingRect');
-
-    var tmpRect = new BoundingRect();
-
-    var RectText = function () {};
-
-    function parsePercent(value, maxValue) {
-        if (typeof value === 'string') {
-            if (value.lastIndexOf('%') >= 0) {
-                return parseFloat(value) / 100 * maxValue;
-            }
-            return parseFloat(value);
-        }
-        return value;
-    }
-
-    function setTransform(ctx, m) {
-        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
-    }
-
-    RectText.prototype = {
-
-        constructor: RectText,
-
-        /**
-         * Draw text in a rect with specified position.
-         * @param  {CanvasRenderingContext} ctx
-         * @param  {Object} rect Displayable rect
-         * @return {Object} textRect Alternative precalculated text bounding rect
-         */
-        drawRectText: function (ctx, rect, textRect) {
-            var style = this.style;
-            var text = style.text;
-            // Convert to string
-            text != null && (text += '');
-            if (!text) {
-                return;
-            }
-            var x;
-            var y;
-            var textPosition = style.textPosition;
-            var distance = style.textDistance;
-            var align = style.textAlign;
-            var font = style.textFont || style.font;
-            var baseline = style.textBaseline;
-
-            textRect = textRect || textContain.getBoundingRect(text, font, align, baseline);
-
-            // Transform rect to view space
-            var transform = this.transform;
-            var invTransform = this.invTransform;
-            if (transform) {
-                tmpRect.copy(rect);
-                tmpRect.applyTransform(transform);
-                rect = tmpRect;
-                // Transform back
-                setTransform(ctx, invTransform);
-            }
-
-            // Text position represented by coord
-            if (textPosition instanceof Array) {
-                // Percent
-                x = rect.x + parsePercent(textPosition[0], rect.width);
-                y = rect.y + parsePercent(textPosition[1], rect.height);
-                align = align || 'left';
-                baseline = baseline || 'top';
-            }
-            else {
-                var res = textContain.adjustTextPositionOnRect(
-                    textPosition, rect, textRect, distance
-                );
-                x = res.x;
-                y = res.y;
-                // Default align and baseline when has textPosition
-                align = align || res.textAlign;
-                baseline = baseline || res.textBaseline;
-            }
-
-            ctx.textAlign = align;
-            ctx.textBaseline = baseline;
-
-            var textFill = style.textFill;
-            var textStroke = style.textStroke;
-            textFill && (ctx.fillStyle = textFill);
-            textStroke && (ctx.strokeStyle = textStroke);
-            ctx.font = font;
-
-            // Text shadow
-            ctx.shadowColor = style.textShadowColor;
-            ctx.shadowBlur = style.textShadowBlur;
-            ctx.shadowOffsetX = style.textShadowOffsetX;
-            ctx.shadowOffsetY = style.textShadowOffsetY;
-
-            var textLines = text.split('\n');
-            for (var i = 0; i < textLines.length; i++) {
-                textFill && ctx.fillText(textLines[i], x, y);
-                textStroke && ctx.strokeText(textLines[i], x, y);
-                y += textRect.lineHeight;
-            }
-
-            // Transform again
-            transform && setTransform(ctx, transform);
-        }
-    };
-
-    return RectText;
-});
-/**
- * 可绘制的图形基类
- * Base class of all displayable graphic objects
- * @module zrender/graphic/Displayable
- */
-
-define('zrender/graphic/Displayable',['require','../core/util','./Style','../Element','./mixin/RectText'],function (require) {
-
-    var zrUtil = require('../core/util');
-
-    var Style = require('./Style');
-
-    var Element = require('../Element');
-    var RectText = require('./mixin/RectText');
-    // var Stateful = require('./mixin/Stateful');
-
-    /**
-     * @alias module:zrender/graphic/Displayable
-     * @extends module:zrender/Element
-     * @extends module:zrender/graphic/mixin/RectText
-     */
-    function Displayable(opts) {
-
-        opts = opts || {};
-
-        Element.call(this, opts);
-
-        // Extend properties
-        for (var name in opts) {
-            if (
-                opts.hasOwnProperty(name) &&
-                name !== 'style'
-            ) {
-                this[name] = opts[name];
-            }
-        }
-
-        /**
-         * @type {module:zrender/graphic/Style}
-         */
-        this.style = new Style(opts.style);
-
-        this._rect = null;
-        // Shapes for cascade clipping.
-        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时不绘制图形,但是仍能触发鼠标事件
-         * If ignore drawing of the displayable object. Mouse event will still be triggered
-         * @name module:/zrender/graphic/Displayable#invisible
-         * @type {boolean}
-         * @default false
-         */
-        invisible: false,
-
-        /**
-         * @name module:/zrender/graphic/Displayable#z
-         * @type {number}
-         * @default 0
-         */
-        z: 0,
-
-        /**
-         * @name module:/zrender/graphic/Displayable#z
-         * @type {number}
-         * @default 0
-         */
-        z2: 0,
-
-        /**
-         * z层level,决定绘画在哪层canvas中
-         * @name module:/zrender/graphic/Displayable#zlevel
-         * @type {number}
-         * @default 0
-         */
-        zlevel: 0,
-
-        /**
-         * 是否可拖拽
-         * @name module:/zrender/graphic/Displayable#draggable
-         * @type {boolean}
-         * @default false
-         */
-        draggable: false,
-
-        /**
-         * 是否正在拖拽
-         * @name module:/zrender/graphic/Displayable#draggable
-         * @type {boolean}
-         * @default false
-         */
-        dragging: false,
-
-        /**
-         * 是否相应鼠标事件
-         * @name module:/zrender/graphic/Displayable#silent
-         * @type {boolean}
-         * @default false
-         */
-        silent: false,
-
-        /**
-         * If enable culling
-         * @type {boolean}
-         * @default false
-         */
-        culling: false,
-
-        /**
-         * Mouse cursor when hovered
-         * @name module:/zrender/graphic/Displayable#cursor
-         * @type {string}
-         */
-        cursor: 'pointer',
-
-        /**
-         * If hover area is bounding rect
-         * @name module:/zrender/graphic/Displayable#rectHover
-         * @type {string}
-         */
-        rectHover: false,
-
-        beforeBrush: function (ctx) {},
-
-        afterBrush: function (ctx) {},
-
-        /**
-         * 图形绘制方法
-         * @param {Canvas2DRenderingContext} ctx
-         */
-        // Interface
-        brush: function (ctx) {},
-
-        /**
-         * 获取最小包围盒
-         * @return {module:zrender/core/BoundingRect}
-         */
-        // Interface
-        getBoundingRect: function () {},
-
-        /**
-         * 判断坐标 x, y 是否在图形上
-         * If displayable element contain coord x, y
-         * @param  {number} x
-         * @param  {number} y
-         * @return {boolean}
-         */
-        contain: function (x, y) {
-            return this.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) {
-            var coord = this.transformCoordToLocal(x, y);
-            var rect = this.getBoundingRect();
-            return rect.contain(coord[0], coord[1]);
-        },
-
-        /**
-         * 标记图形元素为脏,并且在下一帧重绘
-         * Mark displayable element dirty and refresh next frame
-         */
-        dirty: function () {
-            this.__dirty = 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
-        //     );
-        // },
-        /**
-         * Alias for animate('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();
-            return this;
-        }
-    };
-
-    zrUtil.inherits(Displayable, Element);
-
-    zrUtil.mixin(Displayable, RectText);
-    // zrUtil.mixin(Displayable, Stateful);
-
-    return Displayable;
-});
-/**
- * 曲线辅助模块
- * @module zrender/core/curve
- * @author pissang(https://www.github.com/pissang)
- */
-define('zrender/core/curve',['require','./vector'],function(require) {
-
-
-
-    var vec2 = require('./vector');
-    var v2Create = vec2.create;
-    var v2DistSquare = vec2.distSquare;
-    var mathPow = Math.pow;
-    var mathSqrt = Math.sqrt;
-
-    var EPSILON = 1e-4;
-
-    var THREE_SQRT = mathSqrt(3);
-    var ONE_THIRD = 1 / 3;
-
-    // 临时变量
-    var _v0 = v2Create();
-    var _v1 = v2Create();
-    var _v2 = v2Create();
-    // var _v3 = vec2.create();
-
-    function isAroundZero(val) {
-        return val > -EPSILON && val < EPSILON;
-    }
-    function isNotAroundZero(val) {
-        return val > EPSILON || val < -EPSILON;
-    }
-    /**
-     * 计算三次贝塞尔值
-     * @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);
-    }
-
-    /**
-     * 计算三次贝塞尔导数值
-     * @memberOf module: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
-        );
-    }
-
-    /**
-     * 计算三次贝塞尔方程根,使用盛金公式
-     * @memberOf module: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) {
-        // Evaluate roots of cubic functions
-        var a = p3 + 3 * (p1 - p2) - p0;
-        var b = 3 * (p2 - p1 * 2 + p0);
-        var c = 3 * (p1  - p0);
-        var d = p0 - val;
-
-        var A = b * b - 3 * a * c;
-        var B = b * c - 9 * a * d;
-        var C = c * c - 3 * b * d;
-
-        var n = 0;
-
-        if (isAroundZero(A) && isAroundZero(B)) {
-            if (isAroundZero(b)) {
-                roots[0] = 0;
-            }
-            else {
-                var t1 = -c / b;  //t1, t2, t3, b is not zero
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-            }
-        }
-        else {
-            var disc = B * B - 4 * A * C;
-
-            if (isAroundZero(disc)) {
-                var K = B / A;
-                var t1 = -b / a + K;  // t1, a is not zero
-                var t2 = -K / 2;  // t2, t3
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-                if (t2 >= 0 && t2 <= 1) {
-                    roots[n++] = t2;
-                }
-            }
-            else if (disc > 0) {
-                var discSqrt = mathSqrt(disc);
-                var Y1 = A * b + 1.5 * a * (-B + discSqrt);
-                var Y2 = A * b + 1.5 * a * (-B - discSqrt);
-                if (Y1 < 0) {
-                    Y1 = -mathPow(-Y1, ONE_THIRD);
-                }
-                else {
-                    Y1 = mathPow(Y1, ONE_THIRD);
-                }
-                if (Y2 < 0) {
-                    Y2 = -mathPow(-Y2, ONE_THIRD);
-                }
-                else {
-                    Y2 = mathPow(Y2, ONE_THIRD);
-                }
-                var t1 = (-b - (Y1 + Y2)) / (3 * a);
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-            }
-            else {
-                var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A));
-                var theta = Math.acos(T) / 3;
-                var ASqrt = mathSqrt(A);
-                var tmp = Math.cos(theta);
-
-                var t1 = (-b - 2 * ASqrt * tmp) / (3 * a);
-                var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a);
-                var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a);
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-                if (t2 >= 0 && t2 <= 1) {
-                    roots[n++] = t2;
-                }
-                if (t3 >= 0 && t3 <= 1) {
-                    roots[n++] = t3;
-                }
-            }
-        }
-        return n;
-    }
-
-    /**
-     * 计算三次贝塞尔方程极限值的位置
-     * @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(b)) {
-                var t1 = -c / b;
-                if (t1 >= 0 && t1 <=1) {
-                    extrema[n++] = t1;
-                }
-            }
-        }
-        else {
-            var disc = b * b - 4 * a * c;
-            if (isAroundZero(disc)) {
-                extrema[0] = -b / (2 * a);
-            }
-            else if (disc > 0) {
-                var discSqrt = mathSqrt(disc);
-                var t1 = (-b + discSqrt) / (2 * a);
-                var t2 = (-b - discSqrt) / (2 * a);
-                if (t1 >= 0 && t1 <= 1) {
-                    extrema[n++] = t1;
-                }
-                if (t2 >= 0 && t2 <= 1) {
-                    extrema[n++] = t2;
-                }
-            }
-        }
-        return n;
-    }
-
-    /**
-     * 细分三次贝塞尔曲线
-     * @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;
-        // Seg0
-        out[0] = p0;
-        out[1] = p01;
-        out[2] = p012;
-        out[3] = p0123;
-        // Seg1
-        out[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}
-     */
-    function cubicProjectPoint(
-        x0, y0, x1, y1, x2, y2, x3, y3,
-        x, y, out
-    ) {
-        // http://pomax.github.io/bezierinfo/#projections
-        var t;
-        var interval = 0.005;
-        var d = Infinity;
-        var prev;
-        var next;
-        var d1;
-        var d2;
-
-        _v0[0] = x;
-        _v0[1] = y;
-
-        // 先粗略估计一下可能的最小距离的 t 值
-        // PENDING
-        for (var _t = 0; _t < 1; _t += 0.05) {
-            _v1[0] = cubicAt(x0, x1, x2, x3, _t);
-            _v1[1] = cubicAt(y0, y1, y2, y3, _t);
-            d1 = v2DistSquare(_v0, _v1);
-            if (d1 < d) {
-                t = _t;
-                d = d1;
-            }
-        }
-        d = Infinity;
-
-        // At most 32 iteration
-        for (var i = 0; i < 32; i++) {
-            if (interval < EPSILON) {
-                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 = v2DistSquare(_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 = v2DistSquare(_v2, _v0);
-
-                if (next <= 1 && d2 < d) {
-                    t = next;
-                    d = d2;
-                }
-                else {
-                    interval *= 0.5;
-                }
-            }
-        }
-        // t
-        if (out) {
-            out[0] = cubicAt(x0, x1, x2, x3, t);
-            out[1] = cubicAt(y0, y1, y2, y3, t);
-        }
-        // console.log(interval, i);
-        return mathSqrt(d);
-    }
-
-    /**
-     * 计算二次方贝塞尔值
-     * @param  {number} p0
-     * @param  {number} p1
-     * @param  {number} p2
-     * @param  {number} t
-     * @return {number}
-     */
-    function quadraticAt(p0, p1, p2, t) {
-        var onet = 1 - t;
-        return onet * (onet * p0 + 2 * t * p1) + t * t * p2;
-    }
-
-    /**
-     * 计算二次方贝塞尔导数值
-     * @param  {number} p0
-     * @param  {number} p1
-     * @param  {number} p2
-     * @param  {number} t
-     * @return {number}
-     */
-    function quadraticDerivativeAt(p0, p1, p2, t) {
-        return 2 * ((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} 有效根数目
-     */
-    function quadraticRootAt(p0, p1, p2, val, roots) {
-        var a = p0 - 2 * p1 + p2;
-        var b = 2 * (p1 - p0);
-        var c = p0 - val;
-
-        var n = 0;
-        if (isAroundZero(a)) {
-            if (isNotAroundZero(b)) {
-                var t1 = -c / b;
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-            }
-        }
-        else {
-            var disc = b * b - 4 * a * c;
-            if (isAroundZero(disc)) {
-                var t1 = -b / (2 * a);
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-            }
-            else if (disc > 0) {
-                var discSqrt = mathSqrt(disc);
-                var t1 = (-b + discSqrt) / (2 * a);
-                var t2 = (-b - discSqrt) / (2 * a);
-                if (t1 >= 0 && t1 <= 1) {
-                    roots[n++] = t1;
-                }
-                if (t2 >= 0 && t2 <= 1) {
-                    roots[n++] = t2;
-                }
-            }
-        }
-        return n;
-    }
-
-    /**
-     * 计算二次贝塞尔方程极限值
-     * @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) {
-            // p1 is center of p0 and p2
-            return 0.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;
-
-        // Seg0
-        out[0] = p0;
-        out[1] = p01;
-        out[2] = p012;
-
-        // Seg1
-        out[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}
-     */
-    function quadraticProjectPoint(
-        x0, y0, x1, y1, x2, y2,
-        x, y, out
-    ) {
-        // http://pomax.github.io/bezierinfo/#projections
-        var t;
-        var interval = 0.005;
-        var d = Infinity;
-
-        _v0[0] = x;
-        _v0[1] = y;
-
-        // 先粗略估计一下可能的最小距离的 t 值
-        // PENDING
-        for (var _t = 0; _t < 1; _t += 0.05) {
-            _v1[0] = quadraticAt(x0, x1, x2, _t);
-            _v1[1] = quadraticAt(y0, y1, y2, _t);
-            var d1 = v2DistSquare(_v0, _v1);
-            if (d1 < d) {
-                t = _t;
-                d = d1;
-            }
-        }
-        d = Infinity;
-
-        // At most 32 iteration
-        for (var i = 0; i < 32; i++) {
-            if (interval < EPSILON) {
-                break;
-            }
-            var prev = t - interval;
-            var next = t + interval;
-            // t - interval
-            _v1[0] = quadraticAt(x0, x1, x2, prev);
-            _v1[1] = quadraticAt(y0, y1, y2, prev);
-
-            var d1 = v2DistSquare(_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);
-                var d2 = v2DistSquare(_v2, _v0);
-                if (next <= 1 && d2 < d) {
-                    t = next;
-                    d = d2;
-                }
-                else {
-                    interval *= 0.5;
-                }
-            }
-        }
-        // t
-        if (out) {
-            out[0] = quadraticAt(x0, x1, x2, t);
-            out[1] = quadraticAt(y0, y1, y2, t);
-        }
-        // console.log(interval, i);
-        return mathSqrt(d);
-    }
-
-    return {
-
-        cubicAt: cubicAt,
-
-        cubicDerivativeAt: cubicDerivativeAt,
-
-        cubicRootAt: cubicRootAt,
-
-        cubicExtrema: cubicExtrema,
-
-        cubicSubdivide: cubicSubdivide,
-
-        cubicProjectPoint: cubicProjectPoint,
-
-        quadraticAt: quadraticAt,
-
-        quadraticDerivativeAt: quadraticDerivativeAt,
-
-        quadraticRootAt: quadraticRootAt,
-
-        quadraticExtremum: quadraticExtremum,
-
-        quadraticSubdivide: quadraticSubdivide,
-
-        quadraticProjectPoint: quadraticProjectPoint
-    };
-});
-/**
- * @author Yi Shen(https://github.com/pissang)
- */
-define('zrender/core/bbox',['require','./vector','./curve'],function (require) {
-
-    var vec2 = require('./vector');
-    var curve = require('./curve');
-
-    var bbox = {};
-    var mathMin = Math.min;
-    var mathMax = Math.max;
-    var mathSin = Math.sin;
-    var mathCos = Math.cos;
-
-    var start = vec2.create();
-    var end = vec2.create();
-    var extremity = vec2.create();
-
-    var PI2 = Math.PI * 2;
-    /**
-     * 从顶点数组中计算出最小包围盒,写入`min`和`max`中
-     * @module zrender/core/bbox
-     * @param {Array<Object>} points 顶点数组
-     * @param {number} min
-     * @param {number} max
-     */
-    bbox.fromPoints = function(points, min, max) {
-        if (points.length === 0) {
-            return;
-        }
-        var p = points[0];
-        var left = p[0];
-        var right = p[0];
-        var top = p[1];
-        var bottom = p[1];
-        var i;
-
-        for (i = 1; i < points.length; i++) {
-            p = points[i];
-            left = mathMin(left, p[0]);
-            right = mathMax(right, p[0]);
-            top = mathMin(top, p[1]);
-            bottom = mathMax(bottom, p[1]);
-        }
-
-        min[0] = left;
-        min[1] = top;
-        max[0] = right;
-        max[1] = bottom;
-    };
-
-    /**
-     * @memberOf module:zrender/core/bbox
-     * @param {number} x0
-     * @param {number} y0
-     * @param {number} x1
-     * @param {number} y1
-     * @param {Array.<number>} min
-     * @param {Array.<number>} max
-     */
-    bbox.fromLine = function (x0, y0, x1, y1, min, max) {
-        min[0] = mathMin(x0, x1);
-        min[1] = mathMin(y0, y1);
-        max[0] = mathMax(x0, x1);
-        max[1] = mathMax(y0, y1);
-    };
-
-    /**
-     * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入`min`和`max`中
-     * @memberOf module: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
-     */
-    bbox.fromCubic = function(
-        x0, y0, x1, y1, x2, y2, x3, y3, min, max
-    ) {
-        var xDim = [];
-        var yDim = [];
-        var cubicExtrema = curve.cubicExtrema;
-        var cubicAt = curve.cubicAt;
-        var left, right, top, bottom;
-        var i;
-        var n = cubicExtrema(x0, x1, x2, x3, xDim);
-
-        for (i = 0; i < n; i++) {
-            xDim[i] = cubicAt(x0, x1, x2, x3, xDim[i]);
-        }
-        n = cubicExtrema(y0, y1, y2, y3, yDim);
-        for (i = 0; i < n; i++) {
-            yDim[i] = cubicAt(y0, y1, y2, y3, yDim[i]);
-        }
-
-        xDim.push(x0, x3);
-        yDim.push(y0, y3);
-
-        left = mathMin.apply(null, xDim);
-        right = mathMax.apply(null, xDim);
-        top = mathMin.apply(null, yDim);
-        bottom = mathMax.apply(null, yDim);
-
-        min[0] = left;
-        min[1] = top;
-        max[0] = right;
-        max[1] = bottom;
-    };
-
-    /**
-     * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入`min`和`max`中
-     * @memberOf module: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
-     */
-    bbox.fromQuadratic = function(x0, y0, x1, y1, x2, y2, min, max) {
-        var quadraticExtremum = curve.quadraticExtremum;
-        var quadraticAt = curve.quadraticAt;
-        // Find extremities, where derivative in x dim or y dim is zero
-        var tx =
-            mathMax(
-                mathMin(quadraticExtremum(x0, x1, x2), 1), 0
-            );
-        var ty =
-            mathMax(
-                mathMin(quadraticExtremum(y0, y1, y2), 1), 0
-            );
-
-        var x = quadraticAt(x0, x1, x2, tx);
-        var y = quadraticAt(y0, y1, y2, ty);
-
-        min[0] = mathMin(x0, x2, x);
-        min[1] = mathMin(y0, y2, y);
-        max[0] = mathMax(x0, x2, x);
-        max[1] = mathMax(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
-     */
-    bbox.fromArc = function (
-        x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max
-    ) {
-        var vec2Min = vec2.min;
-        var vec2Max = vec2.max;
-
-        if (Math.abs(startAngle - endAngle) % PI2 < 1e-4) {
-            // Is a circle
-            min[0] = x - rx;
-            min[1] = y - ry;
-            max[0] = x + rx;
-            max[1] = y + ry;
-            return;
-        }
-
-        start[0] = mathCos(startAngle) * rx + x;
-        start[1] = mathSin(startAngle) * ry + y;
-
-        end[0] = mathCos(endAngle) * rx + x;
-        end[1] = mathSin(endAngle) * ry + y;
-
-        vec2Min(min, start, end);
-        vec2Max(max, 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;
-        }
-        else if (startAngle < endAngle && anticlockwise) {
-            startAngle += PI2;
-        }
-        if (anticlockwise) {
-            var tmp = endAngle;
-            endAngle = startAngle;
-            startAngle = tmp;
-        }
-
-        // var number = 0;
-        // var step = (anticlockwise ? -Math.PI : Math.PI) / 2;
-        for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
-            if (angle > startAngle) {
-                extremity[0] = mathCos(angle) * rx + x;
-                extremity[1] = mathSin(angle) * ry + y;
-
-                vec2Min(min, extremity, min);
-                vec2Max(max, extremity, max);
-            }
-        }
-    };
-
-    return bbox;
-});
-
-/**
- * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中
- * 可以用于 isInsidePath 判断以及获取boundingRect
- *
- * @module zrender/core/PathProxy
- * @author Yi Shen (http://www.github.com/pissang)
- */
-
- // TODO getTotalLength, getPointAtLength
-define('zrender/core/PathProxy',['require','./curve','./vector','./bbox','./BoundingRect'],function (require) {
-
-    var curve = require('./curve');
-    var vec2 = require('./vector');
-    var bbox = require('./bbox');
-    var BoundingRect = require('./BoundingRect');
-
-    var CMD = {
-        M: 1,
-        L: 2,
-        C: 3,
-        Q: 4,
-        A: 5,
-        Z: 6,
-        // Rect
-        R: 7
-    };
-
-    var min = [];
-    var max = [];
-    var min2 = [];
-    var max2 = [];
-    var mathMin = Math.min;
-    var mathMax = Math.max;
-    var mathCos = Math.cos;
-    var mathSin = Math.sin;
-    var mathSqrt = Math.sqrt;
-
-    var hasTypedArray = typeof Float32Array != 'undefined';
-
-    /**
-     * @alias module:zrender/core/PathProxy
-     * @constructor
-     */
-    var PathProxy = function () {
-
-        /**
-         * Path data. Stored as flat array
-         * @type {Array.<Object>}
-         */
-        this.data = [];
-
-        this._len = 0;
-
-        this._ctx = null;
-
-        this._xi = 0;
-        this._yi = 0;
-
-        this._x0 = 0;
-        this._y0 = 0;
-    };
-
-    /**
-     * 快速计算Path包围盒(并不是最小包围盒)
-     * @return {Object}
-     */
-    PathProxy.prototype = {
-
-        constructor: PathProxy,
-
-        _lineDash: null,
-
-        _dashOffset: 0,
-
-        _dashIdx: 0,
-
-        _dashSum: 0,
-
-        getContext: function () {
-            return this._ctx;
-        },
-
-        /**
-         * @param  {CanvasRenderingContext2D} ctx
-         * @return {module:zrender/core/PathProxy}
-         */
-        beginPath: function (ctx) {
-            this._ctx = ctx;
-
-            ctx && ctx.beginPath();
-
-            // Reset
-            this._len = 0;
-
-            if (this._lineDash) {
-                this._lineDash = null;
-
-                this._dashOffset = 0;
-            }
-
-            return this;
-        },
-
-        /**
-         * @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;
-
-            return this;
-        },
-
-        /**
-         * @param  {number} x
-         * @param  {number} y
-         * @return {module:zrender/core/PathProxy}
-         */
-        lineTo: function (x, y) {
-            this.addData(CMD.L, x, y);
-            if (this._ctx) {
-                this._needsDash() ? this._dashedLineTo(x, y)
-                    : this._ctx.lineTo(x, y);
-            }
-            this._xi = x;
-            this._yi = y;
-            return this;
-        },
-
-        /**
-         * @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(endAngle) * r + cx;
-            this._xi = mathSin(endAngle) * r + cx;
-            return this;
-        },
-
-        // TODO
-        arcTo: function (x1, y1, x2, y2, radius) {
-            if (this._ctx) {
-                this._ctx.arcTo(x1, y1, x2, y2, radius);
-            }
-            return this;
-        },
-
-        // TODO
-        rect: function (x, y, w, h) {
-            this._ctx && this._ctx.rect(x, y, w, h);
-            this.addData(CMD.R, x, y, w, h);
-            return this;
-        },
-
-        /**
-         * @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();
-        },
-
-        /**
-         * 必须在其它绘制命令前调用
-         * Must be invoked before all other path drawing methods
-         * @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;
-        },
-
-        /**
-         * 必须在其它绘制命令前调用
-         * Must be invoked before all other path drawing methods
-         * @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 = data.length;
-
-            if (! (this.data && this.data.length == len) && hasTypedArray) {
-                this.data = new Float32Array(len);
-            }
-
-            for (var i = 0; i < len; i++) {
-                this.data[i] = data[i];
-            }
-
-            this._len = len;
-        },
-
-        /**
-         * 添加子路径
-         * @param {module:zrender/core/PathProxy|Array.<module:zrender/core/PathProxy>} path
-         */
-        appendPath: function (path) {
-            if (!(path instanceof Array)) {
-                path = [path];
-            }
-            var len = path.length;
-            var appendSize = 0;
-            var offset = this._len;
-            for (var i = 0; i < len; i++) {
-                appendSize += path[i].len();
-            }
-            if (hasTypedArray && (this.data instanceof Float32Array)) {
-                this.data = new Float32Array(offset + appendSize);
-            }
-            for (var i = 0; i < len; i++) {
-                var appendPathData = path[i].data;
-                for (var k = 0; k < appendPathData.length; k++) {
-                    this.data[offset++] = appendPathData[k];
-                }
-            }
-            this._len = offset;
-        },
-
-        /**
-         * 填充 Path 数据。
-         * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。
-         */
-        addData: function (cmd) {
-            var data = this.data;
-            if (this._len + arguments.length > data.length) {
-                // 因为之前的数组已经转换成静态的 Float32Array
-                // 所以不够用时需要扩展一个新的动态数组
-                this._expandData();
-                data = this.data;
-            }
-            for (var i = 0; i < arguments.length; i++) {
-                data[this._len++] = arguments[i];
-            }
-
-            this._prevCmd = cmd;
-        },
-
-        _expandData: function () {
-            // Only if data is Float32Array
-            if (! (this.data instanceof Array)) {
-                var newData = [];
-                for (var i = 0; i < this._len; i++) {
-                    newData[i] = this.data[i];
-                }
-                this.data = newData;
-            }
-        },
-
-        /**
-         * If needs js implemented dashed line
-         * @return {boolean}
-         * @private
-         */
-        _needsDash: function () {
-            return this._lineDash;
-        },
-
-        _dashedLineTo: function (x1, y1) {
-            var dashSum = this._dashSum;
-            var offset = this._dashOffset;
-            var lineDash = this._lineDash;
-            var ctx = this._ctx;
-
-            var x0 = this._xi;
-            var y0 = this._yi;
-            var dx = x1 - x0;
-            var dy = y1 - y0;
-            var dist = mathSqrt(dx * dx + dy * dy);
-            var x = x0;
-            var y = y0;
-            var dash;
-            var nDash = lineDash.length;
-            var idx;
-            dx /= dist;
-            dy /= dist;
-
-            if (offset < 0) {
-                // Convert to positive offset
-                offset = dashSum + offset;
-            }
-            offset %= dashSum;
-            x -= offset * dx;
-            y -= offset * dy;
-
-            while ((dx >= 0 && x <= x1) || (dx < 0 && x > x1)) {
-                idx = this._dashIdx;
-                dash = lineDash[idx];
-                x += dx * dash;
-                y += dy * dash;
-                this._dashIdx = (idx + 1) % nDash;
-                // Skip positive offset
-                if ((dx > 0 && x < x0) || (dx < 0 && x > x0)) {
-                    continue;
-                }
-                ctx[idx % 2 ? 'moveTo' : 'lineTo'](
-                    dx >= 0 ? mathMin(x, x1) : mathMax(x, x1),
-                    dy >= 0 ? mathMin(y, y1) : mathMax(y, y1)
-                );
-            }
-            // Offset for next lineTo
-            dx = x - x1;
-            dy = y - y1;
-            this._dashOffset = -mathSqrt(dx * dx + dy * dy);
-        },
-
-        // Not accurate dashed line to
-        _dashedBezierTo: function (x1, y1, x2, y2, x3, y3) {
-            var dashSum = this._dashSum;
-            var offset = this._dashOffset;
-            var lineDash = this._lineDash;
-            var ctx = this._ctx;
-
-            var x0 = this._xi;
-            var y0 = this._yi;
-            var t;
-            var dx;
-            var dy;
-            var cubicAt = curve.cubicAt;
-            var bezierLen = 0;
-            var idx = this._dashIdx;
-            var nDash = lineDash.length;
-
-            var x;
-            var y;
-
-            var tmpLen = 0;
-
-            if (offset < 0) {
-                // Convert to positive offset
-                offset = dashSum + offset;
-            }
-            offset %= dashSum;
-            // Bezier approx length
-            for (t = 0; t < 1; t += 0.1) {
-                dx = cubicAt(x0, x1, x2, x3, t + 0.1)
-                    - cubicAt(x0, x1, x2, x3, t);
-                dy = cubicAt(y0, y1, y2, y3, t + 0.1)
-                    - cubicAt(y0, y1, y2, y3, t);
-                bezierLen += mathSqrt(dx * dx + dy * dy);
-            }
-
-            // Find idx after add offset
-            for (; idx < nDash; idx++) {
-                tmpLen += lineDash[idx];
-                if (tmpLen > offset) {
-                    break;
-                }
-            }
-            t = (tmpLen - offset) / bezierLen;
-
-            while (t <= 1) {
-
-                x = cubicAt(x0, x1, x2, x3, t);
-                y = cubicAt(y0, y1, y2, y3, t);
-
-                // Use line to approximate dashed bezier
-                // Bad result if dash is long
-                idx % 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(dx * dx + dy * dy);
-        },
-
-        _dashedQuadraticTo: function (x1, y1, x2, y2) {
-            // Convert quadratic to cubic using degree elevation
-            var x3 = x2;
-            var y3 = y2;
-            x2 = (x2 + 2 * x1) / 3;
-            y2 = (y2 + 2 * y1) / 3;
-            x1 = (this._xi + 2 * x1) / 3;
-            y1 = (this._yi + 2 * y1) / 3;
-
-            this._dashedBezierTo(x1, y1, x2, y2, x3, y3);
-        },
-
-        /**
-         * 转成静态的 Float32Array 减少堆内存占用
-         * Convert dynamic array to static Float32Array
-         * @return {[type]} [description]
-         */
-        toStatic: function () {
-            this.data.length = this._len;
-            if (hasTypedArray && (this.data instanceof Array)) {
-                this.data = new Float32Array(this.data);
-            }
-        },
-
-        /**
-         * @return {module:zrender/core/BoundingRect}
-         */
-        getBoundingRect: function () {
-            min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE;
-            max[0] = max[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) {
-                    case CMD.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;
-                    case CMD.L:
-                        bbox.fromLine(xi, yi, data[i], data[i + 1], min2, max2);
-                        xi = data[i++];
-                        yi = data[i++];
-                        break;
-                    case CMD.C:
-                        bbox.fromCubic(
-                            xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
-                            min2, max2
-                        );
-                        xi = data[i++];
-                        yi = data[i++];
... 41638 lines suppressed ...

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org