1&&(S=M>0?Math.min(S,d):Math.max(S,d),A=N>0?Math.min(A,f):Math.max(A,f));this.addPolyline(F,i,a,!1)},addLine:function(e,t,r,n){this.addPolyline([e,t],r,n,!1)},addPolyline:function(e,t,r,n){if(e.length){this._itemVertexOffsets.push(this._vertexOffset);var a="number"!=typeof e[0],o=this.attributes.position,s=this.attributes.color,u=this.attributes.offset,h=this.attributes.normal,l=this.indices;null==r&&(r=1);for(var c,d=this._vertexOffset,f=a?e.length:e.length/2,p=f,_=[],m=[],g=[],v=i.create(),y=i.create(),x=i.create(),T=i.create(),b=0;b1&&(o.copy(d,d-1),s.copy(d,d-1),d++);else{var S;if(b0){i.sub(v,_,g),i.sub(y,m,_),i.normalize(v,v),i.normalize(y,y),i.add(T,v,y),i.normalize(T,T);var A=r/2*Math.min(1/i.dot(v,T),2);x[0]=-T[1],x[1]=T[0],S=A}else i.sub(v,m,_),i.normalize(v,v),x[0]=-v[1],x[1]=v[0],S=r/2}else i.sub(v,_,g),i.normalize(v,v),x[0]=-v[1],x[1]=v[0],S=r/2;h.set(d,x),h.set(d+1,x),u.set(d,S),u.set(d+1,-S),i.copy(g,_),o.set(d,_),o.set(d+1,_),s.set(d,c),s.set(d+1,c),d+=2}if(this.useNativeLine)s.set(d,c),o.set(d,_),d++;else if(b>0){var M=3*this._faceOffset,l=this.indices;l[M]=d-4,l[M+1]=d-3,l[M+2]=d-2,l[M+3]=d-3,l[M+4]=d-1,l[M+5]=d-2,this._faceOffset+=2}}this._vertexOffset=d}},setItemColor:function(e,t){for(var r=this._itemVertexOffsets[e],n=e65535?new Uint32Array(3*n):new Uint16Array(3*n))},getQuadVertexCount:function(){return 4},getQuadTriangleCount:function(){return 2},addQuad:function(){var e=i.create(),t=i.create(),r=i.create(),n=[0,3,1,3,2,1];return function(a,o){var s=this.attributes.position,u=this.attributes.normal,h=this.attributes.color;i.sub(e,a[1],a[0]),i.sub(t,a[2],a[1]),i.cross(r,e,t),i.normalize(r,r);for(var l=0;l<4;l++)s.set(this._vertexOffset+l,a[l]),h.set(this._vertexOffset+l,o),u.set(this._vertexOffset+l,r);for(var c=3*this._faceOffset,l=0;l<6;l++)this.indices[c+l]=n[l]+this._vertexOffset;this._vertexOffset+=4,this._faceOffset+=2}}()});a.util.defaults(s.prototype,o),e.exports=s},function(e,t,r){var n=r(0),i=r(15),a=r(32),o=[0,1,2,0,2,3],s=i.extend(function(){return{attributes:{position:new i.Attribute("position","float",3,"POSITION"),texcoord:new i.Attribute("texcoord","float",2,"TEXCOORD_0"),offset:new i.Attribute("offset","float",2),color:new i.Attribute("color","float",4,"COLOR")}}},{resetOffset:function(){this._vertexOffset=0,this._faceOffset=0},setSpriteCount:function(e){this._spriteCount=e;var t=4*e,r=2*e;this.vertexCount!==t&&(this.attributes.position.init(t),this.attributes.offset.init(t),this.attributes.color.init(t)),this.triangleCount!==r&&(this.indices=t>65535?new Uint32Array(3*r):new Uint16Array(3*r))},setSpriteAlign:function(e,t,r,n,i){null==r&&(r="left"),null==n&&(n="top");var a,o,s,u;switch(i=i||0,r){case"left":a=i,s=t[0]+i;break;case"center":case"middle":a=-t[0]/2,s=t[0]/2;break;case"right":a=-t[0]-i,s=-i}switch(n){case"bottom":o=i,u=t[1]+i;break;case"middle":o=-t[1]/2,u=t[1]/2;break;case"top":o=-t[1]-i,u=-i}var h=4*e,l=this.attributes.offset;l.set(h,[a,u]),l.set(h+1,[s,u]),l.set(h+2,[s,o]),l.set(h+3,[a,o])},addSprite:function(e,t,r,n,i,a){var s=this._vertexOffset;this.setSprite(this._vertexOffset/4,e,t,r,n,i,a);for(var u=0;u=2e4},doSortVertices:function(e,t){var r=this.indices,i=n.create();if(!r){r=this.indices=this.vertexCount>65535?new Uint32Array(this.vertexCount):new Uint16Array(this.vertexCount);for(var a=0;a.05);else for(var a=0;a<3;a++)this._progressiveQuickSort(3*t+a);this.dirtyIndices()},_simpleSort:function(e){function t(e,t){return r[t]-r[e]}var r=this._zList,n=this.indices;e?Array.prototype.sort.call(n,t):i.sort(n,t,0,n.length-1)},_progressiveQuickSort:function(e){var t=this._zList,r=this.indices;this._quickSort=this._quickSort||new i,this._quickSort.step(r,function(e,r){return t[r]-t[e]},e)}}},function(e,t){e.exports="@export ecgl.color.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\n@import ecgl.common.uv.header\n\nattribute vec2 texcoord : TEXCOORD_0;\nattribute vec3 position: POSITION;\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nuniform float percent : 1.0;\n#endif\n\nvoid main()\n{\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n#else\n vec3 pos = position;\n#endif\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n @import ecgl.common.uv.main\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n\n}\n\n@end\n\n@export ecgl.color.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n\nuniform sampler2D diffuseMap;\nuniform sampler2D detailMap;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n@import ecgl.common.layers.header\n\n@import ecgl.common.uv.fragmentHeader\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import qtek.util.srgb\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color);\n#else\n gl_FragColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n gl_FragColor *= v_Color;\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n gl_FragColor *= albedoTexel;\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n\n}\n@end"},function(e,t){e.exports="\n@export ecgl.common.transformUniforms\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform mat4 worldInverseTranspose : WORLDINVERSETRANSPOSE;\nuniform mat4 world : WORLD;\n@end\n\n@export ecgl.common.attributes\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\nattribute vec3 normal : NORMAL;\n@end\n\n@export ecgl.common.uv.header\nuniform vec2 uvRepeat : [1.0, 1.0];\nuniform vec2 uvOffset : [0.0, 0.0];\nuniform vec2 detailUvRepeat : [1.0, 1.0];\nuniform vec2 detailUvOffset : [0.0, 0.0];\n\nvarying vec2 v_Texcoord;\nvarying vec2 v_DetailTexcoord;\n@end\n\n@export ecgl.common.uv.main\nv_Texcoord = texcoord * uvRepeat + uvOffset;\nv_DetailTexcoord = texcoord * detailUvRepeat + detailUvOffset;\n@end\n\n@export ecgl.common.uv.fragmentHeader\nvarying vec2 v_Texcoord;\nvarying vec2 v_DetailTexcoord;\n@end\n\n\n@export ecgl.common.albedo.main\n\n vec4 albedoTexel = vec4(1.0);\n#ifdef DIFFUSEMAP_ENABLED\n albedoTexel = texture2D(diffuseMap, v_Texcoord);\n #ifdef SRGB_DECODE\n albedoTexel = sRGBToLinear(albedoTexel);\n #endif\n#endif\n\n#ifdef DETAILMAP_ENABLED\n vec4 detailTexel = texture2D(detailMap, v_DetailTexcoord);\n #ifdef SRGB_DECODE\n detailTexel = sRGBToLinear(detailTexel);\n #endif\n albedoTexel.rgb = mix(albedoTexel.rgb, detailTexel.rgb, detailTexel.a);\n albedoTexel.a = detailTexel.a + (1.0 - detailTexel.a) * albedoTexel.a;\n#endif\n\n@end\n\n@export ecgl.common.wireframe.vertexHeader\n\n#ifdef WIREFRAME_QUAD\nattribute vec4 barycentric;\nvarying vec4 v_Barycentric;\n#elif defined(WIREFRAME_TRIANGLE)\nattribute vec3 barycentric;\nvarying vec3 v_Barycentric;\n#endif\n\n@end\n\n@export ecgl.common.wireframe.vertexMain\n\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\n v_Barycentric = barycentric;\n#endif\n\n@end\n\n\n@export ecgl.common.wireframe.fragmentHeader\n\nuniform float wireframeLineWidth : 1;\nuniform vec4 wireframeLineColor: [0, 0, 0, 0.5];\n\n#ifdef WIREFRAME_QUAD\nvarying vec4 v_Barycentric;\nfloat edgeFactor () {\n vec4 d = fwidth(v_Barycentric);\n vec4 a4 = smoothstep(vec4(0.0), d * wireframeLineWidth, v_Barycentric);\n return min(min(min(a4.x, a4.y), a4.z), a4.w);\n}\n#elif defined(WIREFRAME_TRIANGLE)\nvarying vec3 v_Barycentric;\nfloat edgeFactor () {\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * wireframeLineWidth, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n#endif\n\n@end\n\n\n@export ecgl.common.wireframe.fragmentMain\n\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\n if (wireframeLineWidth > 0.) {\n vec4 lineColor = wireframeLineColor;\n#ifdef SRGB_DECODE\n lineColor = sRGBToLinear(lineColor);\n#endif\n\n gl_FragColor.rgb = mix(gl_FragColor.rgb, lineColor.rgb, (1.0 - edgeFactor()) * lineColor.a);\n }\n#endif\n@end\n\n\n\n\n@export ecgl.common.bumpMap.header\n\n#ifdef BUMPMAP_ENABLED\nuniform sampler2D bumpMap;\nuniform float bumpScale : 1.0;\n\n\nvec3 bumpNormal(vec3 surfPos, vec3 surfNormal, vec3 baseNormal)\n{\n vec2 dSTdx = dFdx(v_Texcoord);\n vec2 dSTdy = dFdy(v_Texcoord);\n\n float Hll = bumpScale * texture2D(bumpMap, v_Texcoord).x;\n float dHx = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdx).x - Hll;\n float dHy = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdy).x - Hll;\n\n vec3 vSigmaX = dFdx(surfPos);\n vec3 vSigmaY = dFdy(surfPos);\n vec3 vN = surfNormal;\n\n vec3 R1 = cross(vSigmaY, vN);\n vec3 R2 = cross(vN, vSigmaX);\n\n float fDet = dot(vSigmaX, R1);\n\n vec3 vGrad = sign(fDet) * (dHx * R1 + dHy * R2);\n return normalize(abs(fDet) * baseNormal - vGrad);\n\n}\n#endif\n\n@end\n\n@export ecgl.common.normalMap.vertexHeader\n\n#ifdef NORMALMAP_ENABLED\nattribute vec4 tangent : TANGENT;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@end\n\n@export ecgl.common.normalMap.vertexMain\n\n#ifdef NORMALMAP_ENABLED\n if (dot(tangent, tangent) > 0.0) {\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\n }\n#endif\n\n@end\n\n\n@export ecgl.common.normalMap.fragmentHeader\n\n#ifdef NORMALMAP_ENABLED\nuniform sampler2D normalMap;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@end\n\n@export ecgl.common.normalMap.fragmentMain\n#ifdef NORMALMAP_ENABLED\n if (dot(v_Tangent, v_Tangent) > 0.0) {\n vec3 normalTexel = texture2D(normalMap, v_DetailTexcoord).xyz;\n if (dot(normalTexel, normalTexel) > 0.0) { N = normalTexel * 2.0 - 1.0;\n mat3 tbn = mat3(v_Tangent, v_Bitangent, v_Normal);\n N = normalize(tbn * N);\n }\n }\n#endif\n@end\n\n\n\n@export ecgl.common.vertexAnimation.header\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nattribute vec3 prevNormal;\nuniform float percent;\n#endif\n\n@end\n\n@export ecgl.common.vertexAnimation.main\n\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n vec3 norm = mix(prevNormal, normal, percent);\n#else\n vec3 pos = position;\n vec3 norm = normal;\n#endif\n\n@end\n\n\n@export ecgl.common.ssaoMap.header\n#ifdef SSAOMAP_ENABLED\nuniform sampler2D ssaoMap;\nuniform vec4 viewport : VIEWPORT;\n#endif\n@end\n\n@export ecgl.common.ssaoMap.main\n float ao = 1.0;\n#ifdef SSAOMAP_ENABLED\n ao = texture2D(ssaoMap, (gl_FragCoord.xy - viewport.xy) / viewport.zw).r;\n#endif\n@end\n\n\n\n\n@export ecgl.common.diffuseLayer.header\n\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\nuniform float layerDiffuseIntensity[LAYER_DIFFUSEMAP_COUNT];\nuniform sampler2D layerDiffuseMap[LAYER_DIFFUSEMAP_COUNT];\n#endif\n\n@end\n\n@export ecgl.common.emissiveLayer.header\n\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\nuniform float layerEmissionIntensity[LAYER_EMISSIVEMAP_COUNT];\nuniform sampler2D layerEmissiveMap[LAYER_EMISSIVEMAP_COUNT];\n#endif\n\n@end\n\n@export ecgl.common.layers.header\n@import ecgl.common.diffuseLayer.header\n@import ecgl.common.emissiveLayer.header\n@end\n\n@export ecgl.common.diffuseLayer.main\n\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\n for (int _idx_ = 0; _idx_ < LAYER_DIFFUSEMAP_COUNT; _idx_++) {{\n float intensity = layerDiffuseIntensity[_idx_];\n vec4 texel2 = texture2D(layerDiffuseMap[_idx_], v_Texcoord);\n #ifdef SRGB_DECODE\n texel2 = sRGBToLinear(texel2);\n #endif\n albedoTexel.rgb = mix(albedoTexel.rgb, texel2.rgb * intensity, texel2.a);\n albedoTexel.a = texel2.a + (1.0 - texel2.a) * albedoTexel.a;\n }}\n#endif\n\n@end\n\n@export ecgl.common.emissiveLayer.main\n\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\n for (int _idx_ = 0; _idx_ < LAYER_EMISSIVEMAP_COUNT; _idx_++)\n {{\n vec4 texel2 = texture2D(layerEmissiveMap[_idx_], v_Texcoord) * layerEmissionIntensity[_idx_];\n #ifdef SRGB_DECODE\n texel2 = sRGBToLinear(texel2);\n #endif\n float intensity = layerEmissionIntensity[_idx_];\n gl_FragColor.rgb += texel2.rgb * texel2.a * intensity;\n }}\n#endif\n\n@end\n"},function(e,t){e.exports="\n@export ecgl.displayShadow.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\nvarying vec3 v_WorldPosition;\n\nvarying vec3 v_Normal;\n\nvoid main()\n{\n @import ecgl.common.uv.main\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\n \n v_WorldPosition = (world * vec4(position, 1.0)).xyz;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n\n@end\n\n\n@export ecgl.displayShadow.fragment\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform float roughness: 0.2;\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import qtek.header.directional_light\n#endif\n\n@import ecgl.common.ssaoMap.header\n\n@import qtek.plugin.compute_shadow_map\n\nvoid main()\n{\n float shadow = 1.0;\n\n @import ecgl.common.ssaoMap.main\n\n#if defined(DIRECTIONAL_LIGHT_COUNT) && defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n for (int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++) {\n shadow = min(shadow, shadowContribsDir[i] * 0.5 + 0.5);\n }\n#endif\n\n shadow *= 0.5 + ao * 0.5;\n shadow = clamp(shadow, 0.0, 1.0);\n\n gl_FragColor = vec4(vec3(0.0), 1.0 - shadow);\n}\n\n@end"},function(e,t){e.exports="@export ecgl.hatching.vertex\n\n@import ecgl.realistic.vertex\n\n@end\n\n\n@export ecgl.hatching.fragment\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform vec4 color : [0.0, 0.0, 0.0, 1.0];\nuniform vec4 paperColor : [1.0, 1.0, 1.0, 1.0];\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import qtek.header.ambient_light\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import qtek.header.ambient_sh_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import qtek.header.directional_light\n#endif\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import qtek.util.srgb\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import qtek.plugin.compute_shadow_map\n\nuniform sampler2D hatch1;\nuniform sampler2D hatch2;\nuniform sampler2D hatch3;\nuniform sampler2D hatch4;\nuniform sampler2D hatch5;\nuniform sampler2D hatch6;\n\nfloat shade(in float tone) {\n vec4 c = vec4(1. ,1., 1., 1.);\n float step = 1. / 6.;\n vec2 uv = v_DetailTexcoord;\n if (tone <= step / 2.0) {\n c = mix(vec4(0.), texture2D(hatch6, uv), 12. * tone);\n }\n else if (tone <= step) {\n c = mix(texture2D(hatch6, uv), texture2D(hatch5, uv), 6. * tone);\n }\n if(tone > step && tone <= 2. * step){\n c = mix(texture2D(hatch5, uv), texture2D(hatch4, uv) , 6. * (tone - step));\n }\n if(tone > 2. * step && tone <= 3. * step){\n c = mix(texture2D(hatch4, uv), texture2D(hatch3, uv), 6. * (tone - 2. * step));\n }\n if(tone > 3. * step && tone <= 4. * step){\n c = mix(texture2D(hatch3, uv), texture2D(hatch2, uv), 6. * (tone - 3. * step));\n }\n if(tone > 4. * step && tone <= 5. * step){\n c = mix(texture2D(hatch2, uv), texture2D(hatch1, uv), 6. * (tone - 4. * step));\n }\n if(tone > 5. * step){\n c = mix(texture2D(hatch1, uv), vec4(1.), 6. * (tone - 5. * step));\n }\n\n return c.r;\n}\n\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n vec4 inkColor = sRGBToLinear(color);\n#else\n vec4 inkColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n inkColor *= sRGBToLinear(v_Color);\n #else\n inkColor *= v_Color;\n #endif\n#endif\n\n vec3 N = v_Normal;\n#ifdef DOUBLE_SIDE\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float tone = 0.0;\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n \n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\n {\n tone += dot(ambientLightColor[i], w) * ambientFactor * ao;\n }\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n tone += dot(calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_], w) * ao;\n }}\n#endif\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\n {\n vec3 lightDirection = -directionalLightDirection[i];\n float lightTone = dot(directionalLightColor[i], w);\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[i];\n }\n#endif\n\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\n\n tone += lightTone * clamp(ndl, 0.0, 1.0);\n }\n#endif\n\n gl_FragColor = mix(inkColor, paperColor, shade(clamp(tone, 0.0, 1.0)));\n }\n@end\n"},function(e,t){e.exports="@export ecgl.labels.vertex\n\nattribute vec3 position: POSITION;\nattribute vec2 texcoord: TEXCOORD_0;\nattribute vec2 offset;\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\n\nvarying vec2 v_Texcoord;\n\nvoid main()\n{\n vec4 proj = worldViewProjection * vec4(position, 1.0);\n\n vec2 screen = (proj.xy / abs(proj.w) + 1.0) * 0.5 * viewport.zw;\n\n screen += offset;\n\n proj.xy = (screen / viewport.zw - 0.5) * 2.0 * abs(proj.w);\n gl_Position = proj;\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n v_Texcoord = texcoord;\n}\n@end\n\n\n@export ecgl.labels.fragment\n\nuniform vec3 color : [1.0, 1.0, 1.0];\nuniform float alpha : 1.0;\nuniform sampler2D textureAtlas;\nuniform vec2 uvScale: [1.0, 1.0];\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\nvarying float v_Miter;\n\nvarying vec2 v_Texcoord;\n\nvoid main()\n{\n gl_FragColor = vec4(color, alpha) * texture2D(textureAtlas, v_Texcoord * uvScale);\n#ifdef VERTEX_COLOR\n gl_FragColor *= v_Color;\n#endif\n}\n\n@end"},function(e,t){e.exports="/**\n * http: */\n\n@export ecgl.lambert.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n\n@import ecgl.common.attributes\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.vertexAnimation.header\n\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nvoid main()\n{\n @import ecgl.common.uv.main\n\n @import ecgl.common.vertexAnimation.main\n\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n}\n\n@end\n\n\n@export ecgl.lambert.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform sampler2D diffuseMap;\nuniform sampler2D detailMap;\n\n@import ecgl.common.layers.header\n\nuniform float emissionIntensity: 1.0;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import qtek.header.ambient_light\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import qtek.header.ambient_sh_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import qtek.header.directional_light\n#endif\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import qtek.util.srgb\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import qtek.plugin.compute_shadow_map\n\nvoid main()\n{\n#ifdef SRGB_DECODE\n gl_FragColor = sRGBToLinear(color);\n#else\n gl_FragColor = color;\n#endif\n\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n gl_FragColor *= sRGBToLinear(v_Color);\n #else\n gl_FragColor *= v_Color;\n #endif\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n gl_FragColor *= albedoTexel;\n\n vec3 N = v_Normal;\n#ifdef DOUBLE_SIDE\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n\n vec3 diffuseColor = vec3(0.0, 0.0, 0.0);\n\n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\n {\n diffuseColor += ambientLightColor[i] * ambientFactor * ao;\n }\n#endif\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n diffuseColor += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\n }}\n#endif\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\n {\n vec3 lightDirection = -directionalLightDirection[i];\n vec3 lightColor = directionalLightColor[i];\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[i];\n }\n#endif\n\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\n\n diffuseColor += lightColor * clamp(ndl, 0.0, 1.0);\n }\n#endif\n\n gl_FragColor.rgb *= diffuseColor;\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n}\n\n@end"},function(e,t){e.exports="@export ecgl.lines2D.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec2 position: POSITION;\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n\n#ifdef POSITIONTEXTURE_ENABLED\nuniform sampler2D positionTexture;\n#endif\n\nvoid main()\n{\n gl_Position = worldViewProjection * vec4(position, -10.0, 1.0);\n\n v_Color = a_Color;\n}\n\n@end\n\n@export ecgl.lines2D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\n\nvoid main()\n{\n gl_FragColor = color * v_Color;\n}\n@end\n\n\n@export ecgl.meshLines2D.vertex\n\nattribute vec2 position: POSITION;\nattribute vec2 normal;\nattribute float offset;\nattribute vec4 a_Color : COLOR;\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform vec4 viewport : VIEWPORT;\n\nvarying vec4 v_Color;\nvarying float v_Miter;\n\nvoid main()\n{\n vec4 p2 = worldViewProjection * vec4(position + normal, -10.0, 1.0);\n gl_Position = worldViewProjection * vec4(position, -10.0, 1.0);\n\n p2.xy /= p2.w;\n gl_Position.xy /= gl_Position.w;\n\n vec2 N = normalize(p2.xy - gl_Position.xy);\n gl_Position.xy += N * offset / viewport.zw * 2.0;\n\n gl_Position.xy *= gl_Position.w;\n\n v_Color = a_Color;\n}\n@end\n\n\n@export ecgl.meshLines2D.fragment\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nvarying vec4 v_Color;\nvarying float v_Miter;\n\nvoid main()\n{\n gl_FragColor = color * v_Color;\n}\n\n@end"},function(e,t){e.exports="@export ecgl.normal.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\n@import ecgl.common.normalMap.vertexHeader\n\n@import ecgl.common.vertexAnimation.header\n\nvoid main()\n{\n\n @import ecgl.common.vertexAnimation.main\n\n @import ecgl.common.uv.main\n\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n @import ecgl.common.normalMap.vertexMain\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n}\n\n\n@end\n\n\n@export ecgl.normal.fragment\n\n#define ROUGHNESS_CHANEL 0\n\nuniform bool useBumpMap;\nuniform bool useRoughnessMap;\nuniform bool doubleSide;\nuniform float roughness;\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n@import ecgl.common.normalMap.fragmentHeader\n@import ecgl.common.bumpMap.header\n\nuniform sampler2D roughnessMap;\n\nvoid main()\n{\n vec3 N = v_Normal;\n \n bool flipNormal = false;\n if (doubleSide) {\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n\n if (dot(N, V) < 0.0) {\n flipNormal = true;\n }\n }\n\n @import ecgl.common.normalMap.fragmentMain\n\n if (useBumpMap) {\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n }\n\n float g = 1.0 - roughness;\n\n if (useRoughnessMap) {\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\n }\n\n if (flipNormal) {\n N = -N;\n }\n\n gl_FragColor.rgb = (N.xyz + 1.0) * 0.5;\n gl_FragColor.a = g;\n}\n@end"},function(e,t){e.exports="@export ecgl.realistic.vertex\n\n@import ecgl.common.transformUniforms\n\n@import ecgl.common.uv.header\n\n@import ecgl.common.attributes\n\n\n@import ecgl.common.wireframe.vertexHeader\n\n#ifdef VERTEX_COLOR\nattribute vec4 a_Color : COLOR;\nvarying vec4 v_Color;\n#endif\n\n#ifdef NORMALMAP_ENABLED\nattribute vec4 tangent : TANGENT;\nvarying vec3 v_Tangent;\nvarying vec3 v_Bitangent;\n#endif\n\n@import ecgl.common.vertexAnimation.header\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nvoid main()\n{\n\n @import ecgl.common.uv.main\n\n @import ecgl.common.vertexAnimation.main\n\n gl_Position = worldViewProjection * vec4(pos, 1.0);\n\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\n\n#ifdef VERTEX_COLOR\n v_Color = a_Color;\n#endif\n\n#ifdef NORMALMAP_ENABLED\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\n#endif\n\n @import ecgl.common.wireframe.vertexMain\n\n}\n\n@end\n\n\n\n@export ecgl.realistic.fragment\n\n#define LAYER_DIFFUSEMAP_COUNT 0\n#define LAYER_EMISSIVEMAP_COUNT 0\n#define PI 3.14159265358979\n#define ROUGHNESS_CHANEL 0\n#define METALNESS_CHANEL 1\n\n#define NORMAL_UP_AXIS 1\n#define NORMAL_FRONT_AXIS 2\n\n#ifdef VERTEX_COLOR\nvarying vec4 v_Color;\n#endif\n\n@import ecgl.common.uv.fragmentHeader\n\nvarying vec3 v_Normal;\nvarying vec3 v_WorldPosition;\n\nuniform sampler2D diffuseMap;\n\nuniform sampler2D detailMap;\nuniform sampler2D metalnessMap;\nuniform sampler2D roughnessMap;\n\n@import ecgl.common.layers.header\n\nuniform float emissionIntensity: 1.0;\n\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\n\nuniform float metalness : 0.0;\nuniform float roughness : 0.5;\n\nuniform mat4 viewInverse : VIEWINVERSE;\n\n#ifdef AMBIENT_LIGHT_COUNT\n@import qtek.header.ambient_light\n#endif\n\n#ifdef AMBIENT_SH_LIGHT_COUNT\n@import qtek.header.ambient_sh_light\n#endif\n\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\n@import qtek.header.ambient_cubemap_light\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n@import qtek.header.directional_light\n#endif\n\n@import ecgl.common.normalMap.fragmentHeader\n\n@import ecgl.common.ssaoMap.header\n\n@import ecgl.common.bumpMap.header\n\n@import qtek.util.srgb\n\n@import qtek.util.rgbm\n\n@import ecgl.common.wireframe.fragmentHeader\n\n@import qtek.plugin.compute_shadow_map\n\nvec3 F_Schlick(float ndv, vec3 spec) {\n return spec + (1.0 - spec) * pow(1.0 - ndv, 5.0);\n}\n\nfloat D_Phong(float g, float ndh) {\n float a = pow(8192.0, g);\n return (a + 2.0) / 8.0 * pow(ndh, a);\n}\n\nvoid main()\n{\n vec4 albedoColor = color;\n\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(eyePos - v_WorldPosition);\n#ifdef VERTEX_COLOR\n #ifdef SRGB_DECODE\n albedoColor *= sRGBToLinear(v_Color);\n #else\n albedoColor *= v_Color;\n #endif\n#endif\n\n @import ecgl.common.albedo.main\n\n @import ecgl.common.diffuseLayer.main\n\n albedoColor *= albedoTexel;\n\n float m = metalness;\n\n#ifdef METALNESSMAP_ENABLED\n float m2 = texture2D(metalnessMap, v_DetailTexcoord)[METALNESS_CHANEL];\n m = clamp(m2 + (m - 0.5) * 2.0, 0.0, 1.0);\n#endif\n\n vec3 baseColor = albedoColor.rgb;\n albedoColor.rgb = baseColor * (1.0 - m);\n vec3 specFactor = mix(vec3(0.04), baseColor, m);\n\n float g = 1.0 - roughness;\n\n#ifdef ROUGHNESSMAP_ENABLED\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\n#endif\n\n vec3 N = v_Normal;\n\n#ifdef DOUBLE_SIDE\n if (dot(N, V) < 0.0) {\n N = -N;\n }\n#endif\n\n float ambientFactor = 1.0;\n\n#ifdef BUMPMAP_ENABLED\n N = bumpNormal(v_WorldPosition, v_Normal, N);\n ambientFactor = dot(v_Normal, N);\n#endif\n\n@import ecgl.common.normalMap.fragmentMain\n\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\n\n vec3 diffuseTerm = vec3(0.0);\n vec3 specularTerm = vec3(0.0);\n\n float ndv = clamp(dot(N, V), 0.0, 1.0);\n vec3 fresnelTerm = F_Schlick(ndv, specFactor);\n\n @import ecgl.common.ssaoMap.main\n\n#ifdef AMBIENT_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_LIGHT_COUNT; _idx_++)\n {{\n diffuseTerm += ambientLightColor[_idx_] * ambientFactor * ao;\n }}\n#endif\n\n#ifdef AMBIENT_SH_LIGHT_COUNT\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\n {{\n diffuseTerm += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\n }}\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_COUNT\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\n if(shadowEnabled)\n {\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\n }\n#endif\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++)\n {{\n vec3 L = -directionalLightDirection[_idx_];\n vec3 lc = directionalLightColor[_idx_];\n\n vec3 H = normalize(L + V);\n float ndl = clamp(dot(N, normalize(L)), 0.0, 1.0);\n float ndh = clamp(dot(N, H), 0.0, 1.0);\n\n float shadowContrib = 1.0;\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n if (shadowEnabled)\n {\n shadowContrib = shadowContribsDir[_idx_];\n }\n#endif\n\n vec3 li = lc * ndl * shadowContrib;\n\n diffuseTerm += li;\n specularTerm += li * fresnelTerm * D_Phong(g, ndh);\n }}\n#endif\n\n\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\n vec3 L = reflect(-V, N);\n L = vec3(L.x, L[NORMAL_UP_AXIS], L[NORMAL_FRONT_AXIS]);\n float rough2 = clamp(1.0 - g, 0.0, 1.0);\n float bias2 = rough2 * 5.0;\n vec2 brdfParam2 = texture2D(ambientCubemapLightBRDFLookup[0], vec2(rough2, ndv)).xy;\n vec3 envWeight2 = specFactor * brdfParam2.x + brdfParam2.y;\n vec3 envTexel2;\n for(int _idx_ = 0; _idx_ < AMBIENT_CUBEMAP_LIGHT_COUNT; _idx_++)\n {{\n envTexel2 = RGBMDecode(textureCubeLodEXT(ambientCubemapLightCubemap[_idx_], L, bias2), 51.5);\n specularTerm += ambientCubemapLightColor[_idx_] * envTexel2 * envWeight2 * ao;\n }}\n#endif\n\n gl_FragColor.rgb = albedoColor.rgb * diffuseTerm + specularTerm;\n gl_FragColor.a = albedoColor.a;\n\n#ifdef SRGB_ENCODE\n gl_FragColor = linearTosRGB(gl_FragColor);\n#endif\n\n @import ecgl.common.emissiveLayer.main\n\n @import ecgl.common.wireframe.fragmentMain\n}\n\n@end"},function(e,t){e.exports="@export ecgl.sm.depth.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position : POSITION;\n\n#ifdef VERTEX_ANIMATION\nattribute vec3 prevPosition;\nuniform float percent : 1.0;\n#endif\n\nvarying vec4 v_ViewPosition;\n\nvoid main(){\n\n#ifdef VERTEX_ANIMATION\n vec3 pos = mix(prevPosition, position, percent);\n#else\n vec3 pos = position;\n#endif\n\n v_ViewPosition = worldViewProjection * vec4(pos, 1.0);\n gl_Position = v_ViewPosition;\n\n}\n@end\n\n\n\n@export ecgl.sm.depth.fragment\n\n@import qtek.sm.depth.fragment\n\n@end"},function(e,t,r){function n(e,t,r){var t=t||document.createElement("canvas");t.width=e,t.height=e;var n=t.getContext("2d");return r&&r(n),t}function i(e,t,r,n){o.util.isArray(t)||(t=[t,t]);var i=s.getMarginByStyle(r,n),a=t[0]+i.left+i.right,u=t[1]+i.top+i.bottom,h=o.helper.createSymbol(e,0,0,t[0],t[1]),l=Math.max(a,u);h.position=[i.left,i.top],a>u?h.position[1]+=(l-u)/2:h.position[0]+=(l-a)/2;var c=h.getBoundingRect();return h.position[0]-=c.x,h.position[1]-=c.y,h.setStyle(r),h.update(),h.__size=l,h}function a(e,t,r){function n(e){return e<128?1:-1}for(var i=t.width,a=t.height,o=e.canvas.width,s=e.canvas.height,u=i/o,h=a/s,l=e.createImageData(o,s),c=0;c=0&&e.call(t,r[i],i)},u.eachEdge=function(e,t){for(var r=this.edges,n=r.length,i=0;i=0&&r[i].node1.dataIndex>=0&&r[i].node2.dataIndex>=0&&e.call(t,r[i],i)},u.breadthFirstTraverse=function(e,t,r,a){if(t instanceof i||(t=this._nodesMap[n(t)]),t){for(var o="out"===r?"outEdges":"in"===r?"inEdges":"edges",s=0;s=0&&r.node2.dataIndex>=0});for(var i=0,a=n.length;i=0&&this[e][t].setItemVisual(this.dataIndex,r,n)},getVisual:function(r,n){return this[e][t].getItemVisual(this.dataIndex,r,n)},setLayout:function(r,n){this.dataIndex>=0&&this[e][t].setItemLayout(this.dataIndex,r,n)},getLayout:function(){return this[e][t].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[e][t].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[e][t].getRawIndex(this.dataIndex)}}};o.mixin(i,h("hostGraph","data")),o.mixin(a,h("hostGraph","edgeData")),s.Node=i,s.Edge=a,e.exports=s},function(e,t,r){function n(e){var t=e.mainData,r=e.datas;r||(r={main:t},e.datasAttr={main:"data"}),e.datas=e.mainData=null,h(t,r,e),d(r,function(r){d(t.TRANSFERABLE_METHODS,function(t){r.wrapMethod(t,c.curry(i,e))})}),t.wrapMethod("cloneShallow",c.curry(o,e)),d(t.CHANGABLE_METHODS,function(r){t.wrapMethod(r,c.curry(a,e))}),c.assert(r[t.dataType]===t)}function i(e,t){if(u(this)){var r=c.extend({},this[f]);r[this.dataType]=t,h(t,r,e)}else l(t,this.dataType,this[p],e);return t}function a(e,t){return e.struct&&e.struct.update(this),t}function o(e,t){return d(t[f],function(r,n){r!==t&&l(r.cloneShallow(),n,t,e)}),t}function s(e){var t=this[p];return null==e||null==t?t:t[f][e]}function u(e){return e[p]===e}function h(e,t,r){e[f]={},d(t,function(t,n){l(t,n,e,r)})}function l(e,t,r,n){r[f][t]=e,e[p]=r,e.dataType=t,n.struct&&(e[n.structAttr]=n.struct,n.struct[n.datasAttr[t]]=e),e.getLinkedData=s}var c=r(14),d=c.each,f="\0__link_datas",p="\0__link_mainData";e.exports=n},function(e,t,r){var n=r(14),i=r(67),a=r(235),o={};o.addCommas=function(e){return isNaN(e)?"-":(e=(e+"").split("."),e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:""))},o.toCamelCase=function(e,t){return e=(e||"").toLowerCase().replace(/-(.)/g,function(e,t){return t.toUpperCase()}),t&&e&&(e=e.charAt(0).toUpperCase()+e.slice(1)),e},o.normalizeCssArray=function(e){var t=e.length;return"number"==typeof e?[e,e,e,e]:2===t?[e[0],e[1],e[0],e[1]]:3===t?[e[0],e[1],e[2],e[1]]:e};var s=o.encodeHTML=function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")},u=["a","b","c","d","e","f","g"],h=function(e,t){return"{"+e+(null==t?"":t)+"}"};o.formatTpl=function(e,t,r){n.isArray(t)||(t=[t]);var i=t.length;if(!i)return"";for(var a=t[0].$vars||[],o=0;o':""};var l=function(e){return e<10?"0"+e:e};o.formatTime=function(e,t,r){"week"!==e&&"month"!==e&&"quarter"!==e&&"half-year"!==e&&"year"!==e||(e="MM-dd\nyyyy");var n=i.parseDate(t),a=r?"UTC":"",o=n["get"+a+"FullYear"](),s=n["get"+a+"Month"]()+1,u=n["get"+a+"Date"](),h=n["get"+a+"Hours"](),c=n["get"+a+"Minutes"](),d=n["get"+a+"Seconds"]();return e=e.replace("MM",l(s)).toLowerCase().replace("yyyy",o).replace("yy",o%100).replace("dd",l(u)).replace("d",u).replace("hh",l(h)).replace("h",h).replace("mm",l(c)).replace("m",c).replace("ss",l(d)).replace("s",d)},o.capitalFirst=function(e){return e?e.charAt(0).toUpperCase()+e.substr(1):e},o.truncateText=a.truncateText,e.exports=o},function(e,t,r){"use strict";function n(e){var t;switch(e){case"byte":t=d.Int8Array;break;case"ubyte":t=d.Uint8Array;break;case"short":t=d.Int16Array;break;case"ushort":t=d.Uint16Array;break;default:t=d.Float32Array}return t}function i(e,t,r,n){this.name=e,this.type=t,this.size=r,n&&(this.semantic=n)}function a(e,t,r,n){switch(i.call(this,e,t,r,n),this.value=null,r){case 1:this.get=function(e){return this.value[e]},this.set=function(e,t){this.value[e]=t},this.copy=function(e,t){this.value[e]=this.value[e]};break;case 2:this.get=function(e,t){var r=this.value;return t[0]=r[2*e],t[1]=r[2*e+1],t},this.set=function(e,t){var r=this.value;r[2*e]=t[0],r[2*e+1]=t[1]},this.copy=function(e,t){var r=this.value;t*=2,e*=2,r[e]=r[t],r[e+1]=r[t+1]};break;case 3:this.get=function(e,t){var r=3*e,n=this.value;return t[0]=n[r],t[1]=n[r+1],t[2]=n[r+2],t},this.set=function(e,t){var r=3*e,n=this.value;n[r]=t[0],n[r+1]=t[1],n[r+2]=t[2]},this.copy=function(e,t){var r=this.value;t*=3,e*=3,r[e]=r[t],r[e+1]=r[t+1],r[e+2]=r[t+2]};break;case 4:this.get=function(e,t){var r=this.value,n=4*e;return t[0]=r[n],t[1]=r[n+1],t[2]=r[n+2],t[3]=r[n+3],t},this.set=function(e,t){var r=this.value,n=4*e;r[n]=t[0],r[n+1]=t[1],r[n+2]=t[2],r[n+3]=t[3]},this.copy=function(e,t){var r=this.value;t*=4,e*=4,r[e]=r[t],r[e+1]=r[t+1],r[e+2]=r[t+2],r[e+3]=r[t+3]}}}function o(e,t,r,n,i){this.name=e,this.type=t,this.buffer=r,this.size=n,this.semantic=i,this.symbol="",this.needsRemove=!1}function s(e){this.buffer=e,this.count=0}function u(){console.warn("Geometry doesn't implement this method, use StaticGeometry instead")}var h=r(8),l=r(10),c=r(45),d=r(20);i.prototype.clone=function(e){var t=new this.constructor(this.name,this.type,this.size,this.semantic);return e&&console.warn("todo"),t},a.prototype.constructor=new i,a.prototype.init=function(e){if(!this.value||this.value.length!=e*this.size){var t=n(this.type);this.value=new t(e*this.size)}},a.prototype.fromArray=function(e){var t,r=n(this.type);if(e[0]&&e[0].length){var i=0,a=this.size;t=new r(e.length*a);for(var o=0;o0){var t=this.outputs[e];t.keepLastFrame?(this._prevOutputTextures[e]&&this._compositor.releaseTexture(this._prevOutputTextures[e]),this._prevOutputTextures[e]=this._outputTextures[e]):this._compositor.releaseTexture(this._outputTextures[e])}}});e.exports=a},function(e,t,r){"use strict";var n=r(8),i=r(36),a=n.extend(function(){return{nodes:[]}},{dirty:function(){this._dirty=!0},addNode:function(e){this.nodes.indexOf(e)>=0||(this.nodes.push(e),this._dirty=!0)},removeNode:function(e){"string"==typeof e&&(e=this.getNodeByName(e));var t=this.nodes.indexOf(e);t>=0&&(this.nodes.splice(t,1),this._dirty=!0)},getNodeByName:function(e){for(var t=0;t=t.COLOR_ATTACHMENT0&&l<=t.COLOR_ATTACHMENT0+8&&d.push(l);c.drawBuffersEXT(d)}e.saveClear(),e.clearBit=a.DEPTH_BUFFER_BIT|a.COLOR_BUFFER_BIT,r=e.render(this.scene,this.camera,!this.autoUpdateScene,this.preZ),e.restoreClear(),n.unbind(e)}else r=e.render(this.scene,this.camera,!this.autoUpdateScene,this.preZ);this.trigger("afterrender",r),this._rendering=!1,this._rendered=!0}});e.exports=s},function(e,t,r){"use strict";var n=r(36),i=n.extend(function(){return{texture:null,outputs:{color:{}}}},function(){},{getOutput:function(e,t){return this.texture},beforeFrame:function(){},afterFrame:function(){}});e.exports=i},function(e,t,r){"use strict";function n(e,t,r){"object"==typeof t&&(r=t,t=null);var n,o=this;if(!(e instanceof Function)){n=[];for(var s in e)e.hasOwnProperty(s)&&n.push(s)}var u=function(t){if(o.apply(this,arguments),e instanceof Function?i(this,e.call(this,t)):a(this,e,n),this.constructor===u)for(var r=u.__initializers__,s=0;s0&&(d.define("vertex","SKINNING"),d.define("vertex","JOINT_COUNT",h)),s&&d.define("both","SHADOW_TRANSPARENT"),o.useSkinMatricesTexture&&d.define("vertex","USE_SKIN_MATRICES_TEXTURE"),this._depthShaders[a]=d),c||(c=new p({shader:d}),this._depthMaterials[i]=c),o.material=c,this.softShadow===A.VSM?d.define("fragment","USE_VSM"):d.undefine("fragment","USE_VSM"),c.setUniform("bias",t),c.setUniform("slopeScale",r),s&&c.set("shadowTransparentMap",u))}},_bindDistanceMaterial:function(e,t){for(var r=t.getWorldPosition()._array,n=0;n0&&(o.shader.define("vertex","SKINNING"),o.shader.define("vertex","JOINT_COUNT",a)),this._distanceMaterials[a]=o),i.material=o,this.softShadow===A.VSM?o.shader.define("fragment","USE_VSM"):o.shader.undefine("fragment","USE_VSM")),o.set("lightPosition",r),o.set("range",t.range)}},saveMaterial:function(e){for(var t=0;t1&&(m=v,v.shadowCascade>4)){console.warn("Support at most 4 cascade");continue}this.renderDirectionalLightShadow(e,t,r,v,this._opaqueCasters,p,l,h)}else v instanceof c?this.renderSpotLightShadow(e,v,this._opaqueCasters,u,s):v instanceof f&&this.renderPointLightShadow(e,v,this._opaqueCasters,_);this._shadowMapNumber[v.type]++}this.restoreMaterial(this._opaqueCasters);var y=p.slice(),x=p.slice();y.pop(),x.shift(),y.reverse(),x.reverse(),l.reverse();for(var T=s.map(i),b=h.map(i),w={},g=0;g0&&(A.fragmentDefines[L]=C,M=!0)}M&&A.dirty(),m?A.define("fragment","SHADOW_CASCADE",m.shadowCascade):A.undefine("fragment","SHADOW_CASCADE"),w[A.__GUID__]=!0}s.length>0&&(S.setUniform("spotLightShadowMaps",s),S.setUniform("spotLightMatrices",u),S.setUniform("spotLightShadowMapSizes",T)),h.length>0&&(S.setUniform("directionalLightShadowMaps",h),m&&(S.setUniform("shadowCascadeClipsNear",y),S.setUniform("shadowCascadeClipsFar",x)),S.setUniform("directionalLightMatrices",l),S.setUniform("directionalLightShadowMapSizes",b)),_.length>0&&S.setUniform("pointLightShadowMaps",_)}}},renderDirectionalLightShadow:function(){var e=new s,t=new u,r=new o,n=new u,i=new u,a=new u,l=new u;return function(o,s,c,d,f,p,_,m){var g=d.shadowBias;this._bindDepthMaterial(f,g,d.shadowSlopeScale),f.sort(h.opaqueSortFunc);var v=Math.min(-s.viewBoundingBoxLastFrame.min.z,c.far),x=Math.max(-s.viewBoundingBoxLastFrame.max.z,c.near),T=this._getDirectionalLightCamera(d,s,c),b=a._array;l.copy(T.projectionMatrix),E.invert(i._array,T.worldTransform._array),E.multiply(i._array,i._array,c.worldTransform._array),E.multiply(b,l._array,i._array);for(var w=[],S=c instanceof y,M=(c.near+c.far)/(c.near-c.far),N=2*c.near*c.far/(c.near-c.far),C=0;C<=d.shadowCascade;C++){var L=x*Math.pow(v/x,C/d.shadowCascade),D=x+(v-x)*C/d.shadowCascade,I=L*d.cascadeSplitLogFactor+D*(1-d.cascadeSplitLogFactor);w.push(I),p.push(-(-I*M+N)/-I)}var R=this._getTexture(d,d.shadowCascade);m.push(R);var P=o.viewport,O=o.gl;this._frameBuffer.attach(R),this._frameBuffer.bind(o),O.clear(O.COLOR_BUFFER_BIT|O.DEPTH_BUFFER_BIT);for(var C=0;C 0.01)\n {\n gl_FragColor.rgb = gl_FragColor.rgb * mix(lineColor, vec3(1.0), edgeFactor(lineWidth));\n }\n\n#ifdef GAMMA_ENCODE\n gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1 / 2.2));\n#endif\n\n#ifdef ALPHA_TEST\n if (gl_FragColor.a < ALPHA_TEST_THRESHOLD) {\n discard;\n }\n#endif\n\n gl_FragColor = encodeHDR(gl_FragColor);\n\n}\n\n@end"},function(e,t){e.exports="@export qtek.compositor.blend\n#ifdef TEXTURE1_ENABLED\nuniform sampler2D texture1;\nuniform float weight1 : 1.0;\n#endif\n#ifdef TEXTURE2_ENABLED\nuniform sampler2D texture2;\nuniform float weight2 : 1.0;\n#endif\n#ifdef TEXTURE3_ENABLED\nuniform sampler2D texture3;\nuniform float weight3 : 1.0;\n#endif\n#ifdef TEXTURE4_ENABLED\nuniform sampler2D texture4;\nuniform float weight4 : 1.0;\n#endif\n#ifdef TEXTURE5_ENABLED\nuniform sampler2D texture5;\nuniform float weight5 : 1.0;\n#endif\n#ifdef TEXTURE6_ENABLED\nuniform sampler2D texture6;\nuniform float weight6 : 1.0;\n#endif\n\nvarying vec2 v_Texcoord;\n\n@import qtek.util.rgbm\n\nvoid main()\n{\n vec4 tex = vec4(0.0);\n#ifdef TEXTURE1_ENABLED\n tex += decodeHDR(texture2D(texture1, v_Texcoord)) * weight1;\n#endif\n#ifdef TEXTURE2_ENABLED\n tex += decodeHDR(texture2D(texture2, v_Texcoord)) * weight2;\n#endif\n#ifdef TEXTURE3_ENABLED\n tex += decodeHDR(texture2D(texture3, v_Texcoord)) * weight3;\n#endif\n#ifdef TEXTURE4_ENABLED\n tex += decodeHDR(texture2D(texture4, v_Texcoord)) * weight4;\n#endif\n#ifdef TEXTURE5_ENABLED\n tex += decodeHDR(texture2D(texture5, v_Texcoord)) * weight5;\n#endif\n#ifdef TEXTURE6_ENABLED\n tex += decodeHDR(texture2D(texture6, v_Texcoord)) * weight6;\n#endif\n\n gl_FragColor = encodeHDR(tex);\n}\n@end"},function(e,t){e.exports="@export qtek.compositor.kernel.gaussian_9\nfloat gaussianKernel[9];\ngaussianKernel[0] = 0.07;\ngaussianKernel[1] = 0.09;\ngaussianKernel[2] = 0.12;\ngaussianKernel[3] = 0.14;\ngaussianKernel[4] = 0.16;\ngaussianKernel[5] = 0.14;\ngaussianKernel[6] = 0.12;\ngaussianKernel[7] = 0.09;\ngaussianKernel[8] = 0.07;\n@end\n\n@export qtek.compositor.kernel.gaussian_13\n\nfloat gaussianKernel[13];\n\ngaussianKernel[0] = 0.02;\ngaussianKernel[1] = 0.03;\ngaussianKernel[2] = 0.06;\ngaussianKernel[3] = 0.08;\ngaussianKernel[4] = 0.11;\ngaussianKernel[5] = 0.13;\ngaussianKernel[6] = 0.14;\ngaussianKernel[7] = 0.13;\ngaussianKernel[8] = 0.11;\ngaussianKernel[9] = 0.08;\ngaussianKernel[10] = 0.06;\ngaussianKernel[11] = 0.03;\ngaussianKernel[12] = 0.02;\n\n@end\n\n\n@export qtek.compositor.gaussian_blur\n\nuniform sampler2D texture; varying vec2 v_Texcoord;\n\nuniform float blurSize : 2.0;\nuniform vec2 textureSize : [512.0, 512.0];\nuniform float blurDir : 0.0;\n\n@import qtek.util.rgbm\n@import qtek.util.clamp_sample\n\nvoid main (void)\n{\n @import qtek.compositor.kernel.gaussian_9\n\n vec2 off = blurSize / textureSize;\n off *= vec2(1.0 - blurDir, blurDir);\n\n vec4 sum = vec4(0.0);\n float weightAll = 0.0;\n\n for (int i = 0; i < 9; i++) {\n float w = gaussianKernel[i];\n vec4 texel = decodeHDR(clampSample(texture, v_Texcoord + float(i - 4) * off));\n sum += texel * w;\n weightAll += w;\n }\n gl_FragColor = encodeHDR(sum / max(weightAll, 0.01));\n}\n\n@end\n"},function(e,t){e.exports="@export qtek.compositor.bright\n\nuniform sampler2D texture;\n\nuniform float threshold : 1;\nuniform float scale : 1.0;\n\nuniform vec2 textureSize: [512, 512];\n\nvarying vec2 v_Texcoord;\n\nconst vec3 lumWeight = vec3(0.2125, 0.7154, 0.0721);\n\n@import qtek.util.rgbm\n\n\nvec4 median(vec4 a, vec4 b, vec4 c)\n{\n return a + b + c - min(min(a, b), c) - max(max(a, b), c);\n}\n\nvoid main()\n{\n vec4 texel = decodeHDR(texture2D(texture, v_Texcoord));\n\n#ifdef ANTI_FLICKER\n vec3 d = 1.0 / textureSize.xyx * vec3(1.0, 1.0, 0.0);\n\n vec4 s1 = decodeHDR(texture2D(texture, v_Texcoord - d.xz));\n vec4 s2 = decodeHDR(texture2D(texture, v_Texcoord + d.xz));\n vec4 s3 = decodeHDR(texture2D(texture, v_Texcoord - d.zy));\n vec4 s4 = decodeHDR(texture2D(texture, v_Texcoord + d.zy));\n texel = median(median(texel, s1, s2), s3, s4);\n\n#endif\n\n float lum = dot(texel.rgb , lumWeight);\n vec4 color;\n if (lum > threshold && texel.a > 0.0)\n {\n color = vec4(texel.rgb * scale, texel.a * scale);\n }\n else\n {\n color = vec4(0.0);\n }\n\n gl_FragColor = encodeHDR(color);\n}\n@end\n"},function(e,t){e.exports="@export qtek.compositor.downsample\n\nuniform sampler2D texture;\nuniform vec2 textureSize : [512, 512];\n\nvarying vec2 v_Texcoord;\n\n@import qtek.util.rgbm\nfloat brightness(vec3 c)\n{\n return max(max(c.r, c.g), c.b);\n}\n\n@import qtek.util.clamp_sample\n\nvoid main()\n{\n vec4 d = vec4(-1.0, -1.0, 1.0, 1.0) / textureSize.xyxy;\n\n#ifdef ANTI_FLICKER\n vec3 s1 = decodeHDR(clampSample(texture, v_Texcoord + d.xy)).rgb;\n vec3 s2 = decodeHDR(clampSample(texture, v_Texcoord + d.zy)).rgb;\n vec3 s3 = decodeHDR(clampSample(texture, v_Texcoord + d.xw)).rgb;\n vec3 s4 = decodeHDR(clampSample(texture, v_Texcoord + d.zw)).rgb;\n\n float s1w = 1.0 / (brightness(s1) + 1.0);\n float s2w = 1.0 / (brightness(s2) + 1.0);\n float s3w = 1.0 / (brightness(s3) + 1.0);\n float s4w = 1.0 / (brightness(s4) + 1.0);\n float oneDivideSum = 1.0 / (s1w + s2w + s3w + s4w);\n\n vec4 color = vec4(\n (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * oneDivideSum,\n 1.0\n );\n#else\n vec4 color = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\n color *= 0.25;\n#endif\n\n gl_FragColor = encodeHDR(color);\n}\n\n@end"},function(e,t){e.exports="@export qtek.compositor.fxaa\n\nuniform sampler2D texture;\nuniform vec4 viewport : VIEWPORT;\n\nvarying vec2 v_Texcoord;\n\n#define FXAA_REDUCE_MIN (1.0/128.0)\n#define FXAA_REDUCE_MUL (1.0/8.0)\n#define FXAA_SPAN_MAX 8.0\n\n@import qtek.util.rgbm\n\nvoid main()\n{\n vec2 resolution = 1.0 / viewport.zw;\n vec3 rgbNW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ) ).xyz;\n vec3 rgbNE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ) ).xyz;\n vec3 rgbSW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ) ).xyz;\n vec3 rgbSE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ) ).xyz;\n vec4 rgbaM = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution ) );\n vec3 rgbM = rgbaM.xyz;\n float opacity = rgbaM.w;\n\n vec3 luma = vec3( 0.299, 0.587, 0.114 );\n\n float lumaNW = dot( rgbNW, luma );\n float lumaNE = dot( rgbNE, luma );\n float lumaSW = dot( rgbSW, luma );\n float lumaSE = dot( rgbSE, luma );\n float lumaM = dot( rgbM, luma );\n float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );\n float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );\n\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );\n\n float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );\n dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * resolution;\n\n vec3 rgbA = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ) ).xyz;\n rgbA += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ) ).xyz;\n rgbA *= 0.5;\n\n vec3 rgbB = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * -0.5 ) ).xyz;\n rgbB += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * 0.5 ) ).xyz;\n rgbB *= 0.25;\n rgbB += rgbA * 0.5;\n\n float lumaB = dot( rgbB, luma );\n\n if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) )\n {\n gl_FragColor = vec4( rgbA, opacity );\n\n }\n else {\n\n gl_FragColor = vec4( rgbB, opacity );\n\n }\n}\n\n@end"},function(e,t){e.exports="@export qtek.compositor.hdr.composite\n\nuniform sampler2D texture;\n#ifdef BLOOM_ENABLED\nuniform sampler2D bloom;\n#endif\n#ifdef LENSFLARE_ENABLED\nuniform sampler2D lensflare;\nuniform sampler2D lensdirt;\n#endif\n\n#ifdef LUM_ENABLED\nuniform sampler2D lum;\n#endif\n\n#ifdef LUT_ENABLED\nuniform sampler2D lut;\n#endif\n\n#ifdef COLOR_CORRECTION\nuniform float brightness : 0.0;\nuniform float contrast : 1.0;\nuniform float saturation : 1.0;\n#endif\n\n#ifdef VIGNETTE\nuniform float vignetteDarkness: 1.0;\nuniform float vignetteOffset: 1.0;\n#endif\n\nuniform float exposure : 1.0;\nuniform float bloomIntensity : 0.25;\nuniform float lensflareIntensity : 1;\n\nvarying vec2 v_Texcoord;\n\n\n@import qtek.util.srgb\n\n\n\n\nvec3 ACESToneMapping(vec3 color)\n{\n const float A = 2.51;\n const float B = 0.03;\n const float C = 2.43;\n const float D = 0.59;\n const float E = 0.14;\n return (color * (A * color + B)) / (color * (C * color + D) + E);\n}\n\nfloat eyeAdaption(float fLum)\n{\n return mix(0.2, fLum, 0.5);\n}\n\n#ifdef LUT_ENABLED\nvec3 lutTransform(vec3 color) {\n float blueColor = color.b * 63.0;\n\n vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\n vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\n vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\n\n vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\n\n vec4 newColor1 = texture2D(lut, texPos1);\n vec4 newColor2 = texture2D(lut, texPos2);\n\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n return newColor.rgb;\n}\n#endif\n\n@import qtek.util.rgbm\n\nvoid main()\n{\n vec4 texel = vec4(0.0);\n vec4 originalTexel = vec4(0.0);\n#ifdef TEXTURE_ENABLED\n texel = decodeHDR(texture2D(texture, v_Texcoord));\n originalTexel = texel;\n#endif\n\n#ifdef BLOOM_ENABLED\n vec4 bloomTexel = decodeHDR(texture2D(bloom, v_Texcoord));\n texel.rgb += bloomTexel.rgb * bloomIntensity;\n texel.a += bloomTexel.a * bloomIntensity;\n#endif\n\n#ifdef LENSFLARE_ENABLED\n texel += decodeHDR(texture2D(lensflare, v_Texcoord)) * texture2D(lensdirt, v_Texcoord) * lensflareIntensity;\n#endif\n\n texel.a = min(texel.a, 1.0);\n\n#ifdef LUM_ENABLED\n float fLum = texture2D(lum, vec2(0.5, 0.5)).r;\n float adaptedLumDest = 3.0 / (max(0.1, 1.0 + 10.0*eyeAdaption(fLum)));\n float exposureBias = adaptedLumDest * exposure;\n#else\n float exposureBias = exposure;\n#endif\n texel.rgb *= exposureBias;\n\n texel.rgb = ACESToneMapping(texel.rgb);\n texel = linearTosRGB(texel);\n\n#ifdef LUT_ENABLED\n texel.rgb = lutTransform(clamp(texel.rgb,vec3(0.0),vec3(1.0)));\n#endif\n\n#ifdef COLOR_CORRECTION\n texel.rgb = clamp(texel.rgb + vec3(brightness), 0.0, 1.0);\n texel.rgb = clamp((texel.rgb - vec3(0.5))*contrast+vec3(0.5), 0.0, 1.0);\n float lum = dot(texel.rgb, vec3(0.2125, 0.7154, 0.0721));\n texel.rgb = mix(vec3(lum), texel.rgb, saturation);\n#endif\n\n#ifdef VIGNETTE\n vec2 uv = (v_Texcoord - vec2(0.5)) * vec2(vignetteOffset);\n texel.rgb = mix(texel.rgb, vec3(1.0 - vignetteDarkness), dot(uv, uv));\n#endif\n\n gl_FragColor = encodeHDR(texel);\n\n#ifdef DEBUG\n #if DEBUG == 1\n gl_FragColor = encodeHDR(decodeHDR(texture2D(texture, v_Texcoord)));\n #elif DEBUG == 2\n gl_FragColor = encodeHDR(decodeHDR(texture2D(bloom, v_Texcoord)) * bloomIntensity);\n #elif DEBUG == 3\n gl_FragColor = encodeHDR(decodeHDR(texture2D(lensflare, v_Texcoord) * lensflareIntensity));\n #endif\n#endif\n\n if (originalTexel.a <= 0.01) {\n gl_FragColor.a = dot(gl_FragColor.rgb, vec3(0.2125, 0.7154, 0.0721));\n }\n #ifdef PREMULTIPLY_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n}\n\n@end"},function(e,t){e.exports="\n@export qtek.compositor.lut\n\nvarying vec2 v_Texcoord;\n\nuniform sampler2D texture;\nuniform sampler2D lookup;\n\nvoid main()\n{\n\n vec4 tex = texture2D(texture, v_Texcoord);\n\n float blueColor = tex.b * 63.0;\n\n vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\n vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\n vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\n\n vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\n\n vec4 newColor1 = texture2D(lookup, texPos1);\n vec4 newColor2 = texture2D(lookup, texPos2);\n\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n gl_FragColor = vec4(newColor.rgb, tex.w);\n}\n\n@end"},function(e,t){e.exports="@export qtek.compositor.output\n\n#define OUTPUT_ALPHA\n\nvarying vec2 v_Texcoord;\n\nuniform sampler2D texture;\n\n@import qtek.util.rgbm\n\nvoid main()\n{\n vec4 tex = decodeHDR(texture2D(texture, v_Texcoord));\n\n gl_FragColor.rgb = tex.rgb;\n\n#ifdef OUTPUT_ALPHA\n gl_FragColor.a = tex.a;\n#else\n gl_FragColor.a = 1.0;\n#endif\n\n gl_FragColor = encodeHDR(gl_FragColor);\n\n #ifdef PREMULTIPLY_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n}\n\n@end"},function(e,t){e.exports="\n@export qtek.compositor.upsample\n\n#define HIGH_QUALITY\n\nuniform sampler2D texture;\nuniform vec2 textureSize : [512, 512];\n\nuniform float sampleScale: 0.5;\n\nvarying vec2 v_Texcoord;\n\n@import qtek.util.rgbm\n\n@import qtek.util.clamp_sample\n\nvoid main()\n{\n\n#ifdef HIGH_QUALITY\n vec4 d = vec4(1.0, 1.0, -1.0, 0.0) / textureSize.xyxy * sampleScale;\n\n vec4 s;\n s = decodeHDR(clampSample(texture, v_Texcoord - d.xy));\n s += decodeHDR(clampSample(texture, v_Texcoord - d.wy)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord - d.zy));\n\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord )) * 4.0;\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw)) * 2.0;\n\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.wy)) * 2.0;\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n\n gl_FragColor = encodeHDR(s / 16.0);\n#else\n vec4 d = vec4(-1.0, -1.0, +1.0, +1.0) / textureSize.xyxy;\n\n vec4 s;\n s = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\n\n gl_FragColor = encodeHDR(s / 4.0);\n#endif\n}\n\n@end"},function(e,t){e.exports="\n@export qtek.compositor.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position : POSITION;\nattribute vec2 texcoord : TEXCOORD_0;\n\nvarying vec2 v_Texcoord;\n\nvoid main()\n{\n v_Texcoord = texcoord;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n\n@end"},function(e,t){e.exports="vec3 calcAmbientSHLight(int idx, vec3 N) {\n int offset = 9 * idx;\n\n return ambientSHLightCoefficients[0]\n + ambientSHLightCoefficients[1] * N.x\n + ambientSHLightCoefficients[2] * N.y\n + ambientSHLightCoefficients[3] * N.z\n + ambientSHLightCoefficients[4] * N.x * N.z\n + ambientSHLightCoefficients[5] * N.z * N.y\n + ambientSHLightCoefficients[6] * N.y * N.x\n + ambientSHLightCoefficients[7] * (3.0 * N.z * N.z - 1.0)\n + ambientSHLightCoefficients[8] * (N.x * N.x - N.y * N.y);\n}"},function(e,t,r){var n=":unconfigurable;";e.exports=["@export qtek.header.directional_light","uniform vec3 directionalLightDirection[DIRECTIONAL_LIGHT_COUNT]"+n,"uniform vec3 directionalLightColor[DIRECTIONAL_LIGHT_COUNT]"+n,"@end","@export qtek.header.ambient_light","uniform vec3 ambientLightColor[AMBIENT_LIGHT_COUNT]"+n,"@end","@export qtek.header.ambient_sh_light","uniform vec3 ambientSHLightColor[AMBIENT_SH_LIGHT_COUNT]"+n,"uniform vec3 ambientSHLightCoefficients[AMBIENT_SH_LIGHT_COUNT * 9]"+n,r(218),"@end","@export qtek.header.ambient_cubemap_light","uniform vec3 ambientCubemapLightColor[AMBIENT_CUBEMAP_LIGHT_COUNT]"+n,"uniform samplerCube ambientCubemapLightCubemap[AMBIENT_CUBEMAP_LIGHT_COUNT]"+n,"uniform sampler2D ambientCubemapLightBRDFLookup[AMBIENT_CUBEMAP_LIGHT_COUNT]"+n,"@end","@export qtek.header.point_light","uniform vec3 pointLightPosition[POINT_LIGHT_COUNT]"+n,"uniform float pointLightRange[POINT_LIGHT_COUNT]"+n,"uniform vec3 pointLightColor[POINT_LIGHT_COUNT]"+n,"@end","@export qtek.header.spot_light","uniform vec3 spotLightPosition[SPOT_LIGHT_COUNT]"+n,"uniform vec3 spotLightDirection[SPOT_LIGHT_COUNT]"+n,"uniform float spotLightRange[SPOT_LIGHT_COUNT]"+n,"uniform float spotLightUmbraAngleCosine[SPOT_LIGHT_COUNT]"+n,"uniform float spotLightPenumbraAngleCosine[SPOT_LIGHT_COUNT]"+n,"uniform float spotLightFalloffFactor[SPOT_LIGHT_COUNT]"+n,"uniform vec3 spotLightColor[SPOT_LIGHT_COUNT]"+n,"@end"].join("\n")},function(e,t){e.exports="@export qtek.sm.depth.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position : POSITION;\n\n#ifdef SHADOW_TRANSPARENT\nattribute vec2 texcoord : TEXCOORD_0;\n#endif\n\n@import qtek.chunk.skinning_header\n\nvarying vec4 v_ViewPosition;\n\n#ifdef SHADOW_TRANSPARENT\nvarying vec2 v_Texcoord;\n#endif\n\nvoid main(){\n\n vec3 skinnedPosition = position;\n\n#ifdef SKINNING\n\n @import qtek.chunk.skin_matrix\n\n skinnedPosition = (skinMatrixWS * vec4(position, 1.0)).xyz;\n#endif\n\n v_ViewPosition = worldViewProjection * vec4(skinnedPosition, 1.0);\n gl_Position = v_ViewPosition;\n\n#ifdef SHADOW_TRANSPARENT\n v_Texcoord = texcoord;\n#endif\n}\n@end\n\n@export qtek.sm.depth.fragment\n\nvarying vec4 v_ViewPosition;\n\n#ifdef SHADOW_TRANSPARENT\nvarying vec2 v_Texcoord;\n#endif\n\nuniform float bias : 0.001;\nuniform float slopeScale : 1.0;\n\n#ifdef SHADOW_TRANSPARENT\nuniform sampler2D transparentMap;\n#endif\n\n@import qtek.util.encode_float\n\nvoid main(){\n float depth = v_ViewPosition.z / v_ViewPosition.w;\n \n#ifdef USE_VSM\n depth = depth * 0.5 + 0.5;\n float moment1 = depth;\n float moment2 = depth * depth;\n\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n moment2 += 0.25*(dx*dx+dy*dy);\n\n gl_FragColor = vec4(moment1, moment2, 0.0, 1.0);\n#else\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n depth += sqrt(dx*dx + dy*dy) * slopeScale + bias;\n\n#ifdef SHADOW_TRANSPARENT\n if (texture2D(transparentMap, v_Texcoord).a <= 0.1) {\n gl_FragColor = encodeFloat(0.9999);\n return;\n }\n#endif\n\n gl_FragColor = encodeFloat(depth * 0.5 + 0.5);\n#endif\n}\n@end\n\n@export qtek.sm.debug_depth\n\nuniform sampler2D depthMap;\nvarying vec2 v_Texcoord;\n\n@import qtek.util.decode_float\n\nvoid main() {\n vec4 tex = texture2D(depthMap, v_Texcoord);\n#ifdef USE_VSM\n gl_FragColor = vec4(tex.rgb, 1.0);\n#else\n float depth = decodeFloat(tex);\n gl_FragColor = vec4(depth, depth, depth, 1.0);\n#endif\n}\n\n@end\n\n\n@export qtek.sm.distance.vertex\n\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\nuniform mat4 world : WORLD;\n\nattribute vec3 position : POSITION;\n\n@import qtek.chunk.skinning_header\n\nvarying vec3 v_WorldPosition;\n\nvoid main (){\n\n vec3 skinnedPosition = position;\n#ifdef SKINNING\n @import qtek.chunk.skin_matrix\n\n skinnedPosition = (skinMatrixWS * vec4(position, 1.0)).xyz;\n#endif\n\n gl_Position = worldViewProjection * vec4(skinnedPosition , 1.0);\n v_WorldPosition = (world * vec4(skinnedPosition, 1.0)).xyz;\n}\n\n@end\n\n@export qtek.sm.distance.fragment\n\nuniform vec3 lightPosition;\nuniform float range : 100;\n\nvarying vec3 v_WorldPosition;\n\n@import qtek.util.encode_float\n\nvoid main(){\n float dist = distance(lightPosition, v_WorldPosition);\n#ifdef USE_VSM\n gl_FragColor = vec4(dist, dist * dist, 0.0, 0.0);\n#else\n dist = dist / range;\n gl_FragColor = encodeFloat(dist);\n#endif\n}\n@end\n\n@export qtek.plugin.shadow_map_common\n\n@import qtek.util.decode_float\n\nfloat tapShadowMap(sampler2D map, vec2 uv, float z){\n vec4 tex = texture2D(map, uv);\n return step(z, decodeFloat(tex) * 2.0 - 1.0);\n}\n\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize, vec2 scale) {\n\n float shadowContrib = tapShadowMap(map, uv, z);\n vec2 offset = vec2(1.0 / textureSize) * scale;\n#ifdef PCF_KERNEL_SIZE\n for (int _idx_ = 0; _idx_ < PCF_KERNEL_SIZE; _idx_++) {{\n shadowContrib += tapShadowMap(map, uv + offset * pcfKernel[_idx_], z);\n }}\n\n return shadowContrib / float(PCF_KERNEL_SIZE + 1);\n#else\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, 0.0), z);\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, 0.0), z);\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, -offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, -offset.y), z);\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, -offset.y), z);\n\n return shadowContrib / 9.0;\n#endif\n}\n\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize) {\n return pcf(map, uv, z, textureSize, vec2(1.0));\n}\n\nfloat chebyshevUpperBound(vec2 moments, float z){\n float p = 0.0;\n z = z * 0.5 + 0.5;\n if (z <= moments.x) {\n p = 1.0;\n }\n float variance = moments.y - moments.x * moments.x;\n variance = max(variance, 0.0000001);\n float mD = moments.x - z;\n float pMax = variance / (variance + mD * mD);\n pMax = clamp((pMax-0.4)/(1.0-0.4), 0.0, 1.0);\n return max(p, pMax);\n}\nfloat computeShadowContrib(\n sampler2D map, mat4 lightVPM, vec3 position, float textureSize, vec2 scale, vec2 offset\n) {\n\n vec4 posInLightSpace = lightVPM * vec4(position, 1.0);\n posInLightSpace.xyz /= posInLightSpace.w;\n float z = posInLightSpace.z;\n if(all(greaterThan(posInLightSpace.xyz, vec3(-0.99, -0.99, -1.0))) &&\n all(lessThan(posInLightSpace.xyz, vec3(0.99, 0.99, 1.0)))){\n vec2 uv = (posInLightSpace.xy+1.0) / 2.0;\n\n #ifdef USE_VSM\n vec2 moments = texture2D(map, uv * scale + offset).xy;\n return chebyshevUpperBound(moments, z);\n #else\n return pcf(map, uv * scale + offset, z, textureSize, scale);\n #endif\n }\n return 1.0;\n}\n\nfloat computeShadowContrib(sampler2D map, mat4 lightVPM, vec3 position, float textureSize) {\n return computeShadowContrib(map, lightVPM, position, textureSize, vec2(1.0), vec2(0.0));\n}\n\nfloat computeShadowContribOmni(samplerCube map, vec3 direction, float range)\n{\n float dist = length(direction);\n vec4 shadowTex = textureCube(map, direction);\n\n#ifdef USE_VSM\n vec2 moments = shadowTex.xy;\n float variance = moments.y - moments.x * moments.x;\n float mD = moments.x - dist;\n float p = variance / (variance + mD * mD);\n if(moments.x + 0.001 < dist){\n return clamp(p, 0.0, 1.0);\n }else{\n return 1.0;\n }\n#else\n return step(dist, (decodeFloat(shadowTex) + 0.0002) * range);\n#endif\n}\n\n@end\n\n\n\n@export qtek.plugin.compute_shadow_map\n\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT) || defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT) || defined(POINT_LIGHT_SHADOWMAP_COUNT)\n\n#ifdef SPOT_LIGHT_SHADOWMAP_COUNT\nuniform sampler2D spotLightShadowMaps[SPOT_LIGHT_SHADOWMAP_COUNT];\nuniform mat4 spotLightMatrices[SPOT_LIGHT_SHADOWMAP_COUNT];\nuniform float spotLightShadowMapSizes[SPOT_LIGHT_SHADOWMAP_COUNT];\n#endif\n\n#ifdef DIRECTIONAL_LIGHT_SHADOWMAP_COUNT\n#if defined(SHADOW_CASCADE)\nuniform sampler2D directionalLightShadowMaps[1];\nuniform mat4 directionalLightMatrices[SHADOW_CASCADE];\nuniform float directionalLightShadowMapSizes[1];\nuniform float shadowCascadeClipsNear[SHADOW_CASCADE];\nuniform float shadowCascadeClipsFar[SHADOW_CASCADE];\n#else\nuniform sampler2D directionalLightShadowMaps[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT];\nuniform mat4 directionalLightMatrices[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT];\nuniform float directionalLightShadowMapSizes[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT];\n#endif\n#endif\n\n#ifdef POINT_LIGHT_SHADOWMAP_COUNT\nuniform samplerCube pointLightShadowMaps[POINT_LIGHT_SHADOWMAP_COUNT];\nuniform float pointLightShadowMapSizes[POINT_LIGHT_SHADOWMAP_COUNT];\n#endif\n\nuniform bool shadowEnabled : true;\n\n#ifdef PCF_KERNEL_SIZE\nuniform vec2 pcfKernel[PCF_KERNEL_SIZE];\n#endif\n\n@import qtek.plugin.shadow_map_common\n\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT)\n\nvoid computeShadowOfSpotLights(vec3 position, inout float shadowContribs[SPOT_LIGHT_COUNT] ) {\n float shadowContrib;\n for(int _idx_ = 0; _idx_ < SPOT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n shadowContrib = computeShadowContrib(\n spotLightShadowMaps[_idx_], spotLightMatrices[_idx_], position,\n spotLightShadowMapSizes[_idx_]\n );\n shadowContribs[_idx_] = shadowContrib;\n }}\n for(int _idx_ = SPOT_LIGHT_SHADOWMAP_COUNT; _idx_ < SPOT_LIGHT_COUNT; _idx_++){{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n\n#endif\n\n\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\n\n#ifdef SHADOW_CASCADE\n\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\n float depth = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far)\n / (gl_DepthRange.far - gl_DepthRange.near);\n\n float shadowContrib;\n shadowContribs[0] = 1.0;\n\n for (int _idx_ = 0; _idx_ < SHADOW_CASCADE; _idx_++) {{\n if (\n depth >= shadowCascadeClipsNear[_idx_] &&\n depth <= shadowCascadeClipsFar[_idx_]\n ) {\n shadowContrib = computeShadowContrib(\n directionalLightShadowMaps[0], directionalLightMatrices[_idx_], position,\n directionalLightShadowMapSizes[0],\n vec2(1.0 / float(SHADOW_CASCADE), 1.0),\n vec2(float(_idx_) / float(SHADOW_CASCADE), 0.0)\n );\n shadowContribs[0] = shadowContrib;\n }\n }}\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n\n#else\n\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\n float shadowContrib;\n\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n shadowContrib = computeShadowContrib(\n directionalLightShadowMaps[_idx_], directionalLightMatrices[_idx_], position,\n directionalLightShadowMapSizes[_idx_]\n );\n shadowContribs[_idx_] = shadowContrib;\n }}\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n#endif\n\n#endif\n\n\n#if defined(POINT_LIGHT_SHADOWMAP_COUNT)\n\nvoid computeShadowOfPointLights(vec3 position, inout float shadowContribs[POINT_LIGHT_COUNT] ){\n vec3 lightPosition;\n vec3 direction;\n for(int _idx_ = 0; _idx_ < POINT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\n lightPosition = pointLightPosition[_idx_];\n direction = position - lightPosition;\n shadowContribs[_idx_] = computeShadowContribOmni(pointLightShadowMaps[_idx_], direction, pointLightRange[_idx_]);\n }}\n for(int _idx_ = POINT_LIGHT_SHADOWMAP_COUNT; _idx_ < POINT_LIGHT_COUNT; _idx_++) {{\n shadowContribs[_idx_] = 1.0;\n }}\n}\n\n#endif\n\n#endif\n\n@end"},function(e,t){e.exports="@export qtek.skybox.vertex\n\nuniform mat4 world : WORLD;\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\n\nattribute vec3 position : POSITION;\n\nvarying vec3 v_WorldPosition;\n\nvoid main()\n{\n v_WorldPosition = (world * vec4(position, 1.0)).xyz;\n gl_Position = worldViewProjection * vec4(position, 1.0);\n}\n\n@end\n\n@export qtek.skybox.fragment\n\nuniform mat4 viewInverse : VIEWINVERSE;\nuniform samplerCube environmentMap;\nuniform float lod: 0.0;\n\nvarying vec3 v_WorldPosition;\n\n@import qtek.util.rgbm\n\nvoid main()\n{\n vec3 eyePos = viewInverse[3].xyz;\n vec3 viewDirection = normalize(v_WorldPosition - eyePos);\n\n vec3 tex = decodeHDR(textureCubeLodEXT(environmentMap, viewDirection, lod)).rgb;\n\n#ifdef SRGB_DECODE\n tex.rgb = pow(tex.rgb, vec3(2.2));\n#endif\n\n gl_FragColor = encodeHDR(vec4(tex, 1.0));\n}\n@end"},function(e,t){e.exports="\n@export qtek.util.rand\nhighp float rand(vec2 uv) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot(uv.xy, vec2(a,b)), sn = mod(dt, 3.141592653589793);\n return fract(sin(sn) * c);\n}\n@end\n\n@export qtek.util.calculate_attenuation\n\nuniform float attenuationFactor : 5.0;\n\nfloat lightAttenuation(float dist, float range)\n{\n float attenuation = 1.0;\n attenuation = dist*dist/(range*range+1.0);\n float att_s = attenuationFactor;\n attenuation = 1.0/(attenuation*att_s+1.0);\n att_s = 1.0/(att_s+1.0);\n attenuation = attenuation - att_s;\n attenuation /= 1.0 - att_s;\n return clamp(attenuation, 0.0, 1.0);\n}\n\n@end\n\n@export qtek.util.edge_factor\n\nfloat edgeFactor(float width)\n{\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * width, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n\n@end\n\n@export qtek.util.encode_float\nvec4 encodeFloat(const in float depth)\n{\n \n \n const vec4 bitShifts = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n vec4 res = fract(depth * bitShifts);\n res -= res.xxyz * bit_mask;\n\n return res;\n}\n@end\n\n@export qtek.util.decode_float\nfloat decodeFloat(const in vec4 color)\n{\n \n \n const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\n return dot(color, bitShifts);\n}\n@end\n\n\n@export qtek.util.float\n@import qtek.util.encode_float\n@import qtek.util.decode_float\n@end\n\n\n\n@export qtek.util.rgbm_decode\nvec3 RGBMDecode(vec4 rgbm, float range) {\n return range * rgbm.rgb * rgbm.a;\n }\n@end\n\n@export qtek.util.rgbm_encode\nvec4 RGBMEncode(vec3 color, float range) {\n if (dot(color, color) == 0.0) {\n return vec4(0.0);\n }\n vec4 rgbm;\n color /= range;\n rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);\n rgbm.a = ceil(rgbm.a * 255.0) / 255.0;\n rgbm.rgb = color / rgbm.a;\n return rgbm;\n}\n@end\n\n@export qtek.util.rgbm\n@import qtek.util.rgbm_decode\n@import qtek.util.rgbm_encode\n\nvec4 decodeHDR(vec4 color)\n{\n#if defined(RGBM_DECODE) || defined(RGBM)\n return vec4(RGBMDecode(color, 51.5), 1.0);\n#else\n return color;\n#endif\n}\n\nvec4 encodeHDR(vec4 color)\n{\n#if defined(RGBM_ENCODE) || defined(RGBM)\n return RGBMEncode(color.xyz, 51.5);\n#else\n return color;\n#endif\n}\n\n@end\n\n\n@export qtek.util.srgb\n\nvec4 sRGBToLinear(in vec4 value) {\n return vec4(mix(pow(value.rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)), value.rgb * 0.0773993808, vec3(lessThanEqual(value.rgb, vec3(0.04045)))), value.w);\n}\n\nvec4 linearTosRGB(in vec4 value) {\n return vec4(mix(pow(value.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), value.rgb * 12.92, vec3(lessThanEqual(value.rgb, vec3(0.0031308)))), value.w);\n}\n@end\n\n\n@export qtek.chunk.skinning_header\n#ifdef SKINNING\nattribute vec3 weight : WEIGHT;\nattribute vec4 joint : JOINT;\n\n#ifdef USE_SKIN_MATRICES_TEXTURE\nuniform sampler2D skinMatricesTexture;\nuniform float skinMatricesTextureSize: unconfigurable;\nmat4 getSkinMatrix(float idx) {\n float j = idx * 4.0;\n float x = mod(j, skinMatricesTextureSize);\n float y = floor(j / skinMatricesTextureSize) + 0.5;\n vec2 scale = vec2(skinMatricesTextureSize);\n\n return mat4(\n texture2D(skinMatricesTexture, vec2(x + 0.5, y) / scale),\n texture2D(skinMatricesTexture, vec2(x + 1.5, y) / scale),\n texture2D(skinMatricesTexture, vec2(x + 2.5, y) / scale),\n texture2D(skinMatricesTexture, vec2(x + 3.5, y) / scale)\n );\n}\n#else\nuniform mat4 skinMatrix[JOINT_COUNT] : SKIN_MATRIX;\nmat4 getSkinMatrix(float idx) {\n return skinMatrix[int(idx)];\n}\n#endif\n\n#endif\n\n@end\n\n@export qtek.chunk.skin_matrix\n\nmat4 skinMatrixWS;\nif (joint.x >= 0.0)\n{\n skinMatrixWS = getSkinMatrix(joint.x) * weight.x;\n}\nif (joint.y >= 0.0)\n{\n skinMatrixWS += getSkinMatrix(joint.y) * weight.y;\n}\nif (joint.z >= 0.0)\n{\n skinMatrixWS += getSkinMatrix(joint.z) * weight.z;\n}\nif (joint.w >= 0.0)\n{\n skinMatrixWS += getSkinMatrix(joint.w) * (1.0-weight.x-weight.y-weight.z);\n}\n@end\n\n\n\n@export qtek.util.parallax_correct\n\nvec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) {\n vec3 first = (boxMax - pos) / dir;\n vec3 second = (boxMin - pos) / dir;\n\n vec3 further = max(first, second);\n float dist = min(further.x, min(further.y, further.z));\n\n vec3 fixedPos = pos + dir * dist;\n vec3 boxCenter = (boxMax + boxMin) * 0.5;\n\n return normalize(fixedPos - boxCenter);\n}\n\n@end\n\n\n\n@export qtek.util.clamp_sample\nvec4 clampSample(const in sampler2D texture, const in vec2 coord)\n{\n#ifdef STEREO\n float eye = step(0.5, coord.x) * 0.5;\n vec2 coordClamped = clamp(coord, vec2(eye, 0.0), vec2(0.5 + eye, 1.0));\n#else\n vec2 coordClamped = clamp(coord, vec2(0.0), vec2(1.0));\n#endif\n return texture2D(texture, coordClamped);\n}\n@end"},function(e,t,r){var n=r(4),i=r(22),a=r(6),o=r(11),s=r(12),u=r(19),h=r(7),l=r(57),c=r(35),d=r(59),f=r(20),p=r(46),_=r(227),m=r(228),g={},v=["px","nx","py","ny","pz","nz"];g.prefilterEnvironmentMap=function(e,t,r,s,_){_&&s||(s=g.generateNormalDistribution(),_=g.integrateBRDF(e,s)),r=r||{};var y=r.width||64,x=r.height||64,T=r.type||t.type,b=new i({width:y,height:x,type:T,flipY:!1,mipmaps:[]});b.isPowerOfTwo()||console.warn("Width and height must be power of two to enable mipmap.");var w=Math.min(y,x),E=Math.log(w)/Math.log(2)+1,S=new u({shader:new h({vertex:h.source("qtek.skybox.vertex"),fragment:m})});S.set("normalDistribution",s),r.encodeRGBM&&S.shader.define("fragment","RGBM_ENCODE"),r.decodeRGBM&&S.shader.define("fragment","RGBM_DECODE");var A,M=new c;if(t instanceof n){var N=new i({width:y,height:x,type:T===a.FLOAT?a.HALF_FLOAT:T});p.panoramaToCubeMap(e,t,N,{encodeRGBM:r.decodeRGBM}),t=N}A=new l({scene:M,material:S}),A.material.set("environmentMap",t);var C=new d({texture:b});r.encodeRGBM&&(T=b.type=a.UNSIGNED_BYTE);for(var L=new n({width:y,height:x,type:T}),D=new o({depthBuffer:!1}),I=f[T===a.UNSIGNED_BYTE?"Uint8Array":"Float32Array"],R=0;R>>16)>>>0;u=((1431655765&u)<<1|(2863311530&u)>>>1)>>>0,u=((858993459&u)<<2|(3435973836&u)>>>2)>>>0,u=((252645135&u)<<4|(4042322160&u)>>>4)>>>0,u=(((16711935&u)<<8|(4278255360&u)>>>8)>>>0)/4294967296;for(var h=0;h0){var i=Math.pow(2,e[3]-128-8+n);t[r+0]=e[0]*i,t[r+1]=e[1]*i,t[r+2]=e[2]*i}else t[r+0]=0,t[r+1]=0,t[r+2]=0;return t[r+3]=1,t}function i(e,t,r){for(var n="",i=t;i0;)if(e[o][0]=t[r++],e[o][1]=t[r++],e[o][2]=t[r++],e[o][3]=t[r++],1===e[o][0]&&1===e[o][1]&&1===e[o][2]){for(var u=e[o][3]<>>0;u>0;u--)a(e[o-1],e[o]),o++,s--;i+=8}else o++,s--,i=0;return r}function s(e,t,r,n){if(nd)return o(e,t,r,n);var i=t[r++];if(2!=i)return o(e,t,r-1,n);if(e[0][1]=t[r++],e[0][2]=t[r++],i=t[r++],(e[0][2]<<8>>>0|i)>>>0!==n)return null;for(var i=0;i<4;i++)for(var a=0;a128){s=(127&s)>>>0;for(var u=t[r++];s--;)e[a++][i]=u}else for(;s--;)e[a++][i]=t[r++]}return r}var u=r(6),h=r(4),l=String.fromCharCode,c=8,d=32767,f={parseRGBE:function(e,t,r){null==r&&(r=0);var a=new Uint8Array(e),o=a.length;if("#?"===i(a,0,2)){for(var c=2;c=o)){c+=2;for(var d="";c 0.0) {\n float G = G_Smith(roughness, NoV, NoL);\n float G_Vis = G * VoH / (NoH * NoV);\n float Fc = pow(1.0 - VoH, 5.0);\n A += (1.0 - Fc) * G_Vis;\n B += Fc * G_Vis;\n }\n }\n\n gl_FragColor = vec4(vec2(A, B) / fSampleNumber, 0.0, 1.0);\n}\n"},function(e,t){e.exports="#define SAMPLE_NUMBER 1024\n#define PI 3.14159265358979\n\nuniform mat4 viewInverse : VIEWINVERSE;\nuniform samplerCube environmentMap;\nuniform sampler2D normalDistribution;\n\nuniform float roughness : 0.5;\n\nvarying vec2 v_Texcoord;\nvarying vec3 v_WorldPosition;\n\nconst float fSampleNumber = float(SAMPLE_NUMBER);\n\n@import qtek.util.rgbm\n\nvec3 importanceSampleNormal(float i, float roughness, vec3 N) {\n vec3 H = texture2D(normalDistribution, vec2(roughness, i)).rgb;\n\n vec3 upVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n vec3 tangentX = normalize(cross(upVector, N));\n vec3 tangentY = cross(N, tangentX);\n return tangentX * H.x + tangentY * H.y + N * H.z;\n}\n\nvoid main() {\n\n vec3 eyePos = viewInverse[3].xyz;\n vec3 V = normalize(v_WorldPosition - eyePos);\n\n vec3 N = V;\n vec3 R = V;\n\n vec3 prefilteredColor = vec3(0.0);\n float totalWeight = 0.0;\n\n\n for (int i = 0; i < SAMPLE_NUMBER; i++) {\n vec3 H = importanceSampleNormal(float(i) / fSampleNumber, roughness, N);\n vec3 L = reflect(-V, H);\n\n float NoL = clamp(dot(N, L), 0.0, 1.0);\n if (NoL > 0.0) {\n prefilteredColor += decodeHDR(textureCube(environmentMap, L)).rgb * NoL;\n totalWeight += NoL;\n }\n }\n\n gl_FragColor = encodeHDR(vec4(prefilteredColor / totalWeight, 1.0));\n}\n"},function(e,t){e.exports="uniform samplerCube environmentMap;\n\nvarying vec2 v_Texcoord;\n\n#define TEXTURE_SIZE 16\n\nmat3 front = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 1.0, 0.0,\n 0.0, 0.0, 1.0\n);\n\nmat3 back = mat3(\n -1.0, 0.0, 0.0,\n 0.0, 1.0, 0.0,\n 0.0, 0.0, -1.0\n);\n\nmat3 left = mat3(\n 0.0, 0.0, -1.0,\n 0.0, 1.0, 0.0,\n 1.0, 0.0, 0.0\n);\n\nmat3 right = mat3(\n 0.0, 0.0, 1.0,\n 0.0, 1.0, 0.0,\n -1.0, 0.0, 0.0\n);\n\nmat3 up = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 0.0, 1.0,\n 0.0, -1.0, 0.0\n);\n\nmat3 down = mat3(\n 1.0, 0.0, 0.0,\n 0.0, 0.0, -1.0,\n 0.0, 1.0, 0.0\n);\n\n\nfloat harmonics(vec3 normal){\n int index = int(gl_FragCoord.x);\n\n float x = normal.x;\n float y = normal.y;\n float z = normal.z;\n\n if(index==0){\n return 1.0;\n }\n else if(index==1){\n return x;\n }\n else if(index==2){\n return y;\n }\n else if(index==3){\n return z;\n }\n else if(index==4){\n return x*z;\n }\n else if(index==5){\n return y*z;\n }\n else if(index==6){\n return x*y;\n }\n else if(index==7){\n return 3.0*z*z - 1.0;\n }\n else{\n return x*x - y*y;\n }\n}\n\nvec3 sampleSide(mat3 rot)\n{\n\n vec3 result = vec3(0.0);\n float divider = 0.0;\n for (int i = 0; i < TEXTURE_SIZE * TEXTURE_SIZE; i++) {\n float x = mod(float(i), float(TEXTURE_SIZE));\n float y = float(i / TEXTURE_SIZE);\n\n vec2 sidecoord = ((vec2(x, y) + vec2(0.5, 0.5)) / vec2(TEXTURE_SIZE)) * 2.0 - 1.0;\n vec3 normal = normalize(vec3(sidecoord, -1.0));\n vec3 fetchNormal = rot * normal;\n vec3 texel = textureCube(environmentMap, fetchNormal).rgb;\n\n result += harmonics(fetchNormal) * texel * -normal.z;\n\n divider += -normal.z;\n }\n\n return result / divider;\n}\n\nvoid main()\n{\n vec3 result = (\n sampleSide(front) +\n sampleSide(back) +\n sampleSide(left) +\n sampleSide(right) +\n sampleSide(up) +\n sampleSide(down)\n ) / 6.0;\n gl_FragColor = vec4(result, 1.0);\n}"},function(e,t){e.exports="0.4.1"},function(e,t,r){function n(e,t){return e[t]}function i(e,t,r){e[t]=r}function a(e,t,r){return(t-e)*r+e}function o(e,t,r){return r>.5?t:e}function s(e,t,r,n,i){var o=e.length;if(1==i)for(var s=0;si)e.length=i;else for(var a=n;a=0&&!(M[r]<=t);r--);r=Math.min(r,x-2)}else{for(r=k;rt);r++);r=Math.min(r-1,x-2)}k=r,H=t;var n=M[r+1]-M[r];if(0!==n)if(F=(t-M[r])/n,v)if(U=N[r],B=N[0===r?r:r-1],z=N[r>x-2?x-1:r+1],G=N[r>x-3?x-1:r+2],w)l(B,U,z,G,F,F*F,F*F*F,d(e,i),A);else{var u;if(E)u=l(B,U,z,G,F,F*F,F*F*F,V,1),u=f(V);else{if(S)return o(U,z,F);u=c(B,U,z,G,F,F*F,F*F*F)}_(e,i,u)}else if(w)s(N[r],N[r+1],F,d(e,i),A);else{var u;if(E)s(N[r],N[r+1],F,V,1),u=f(V);else{if(S)return o(N[r],N[r+1],F);u=a(N[r],N[r+1],F)}_(e,i,u)}},q=new m({target:e._target,life:T,loop:e._loop,delay:e._delay,onframe:W,ondestroy:r});return t&&"spline"!==t&&(q.easing=t),q}}}var m=r(232),g=r(238),v=r(14),y=v.isArrayLike,x=Array.prototype.slice,T=function(e,t,r,a){this._tracks={},this._target=e,this._loop=t||!1,this._getter=r||n,this._setter=a||i,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};T.prototype={when:function(e,t){var r=this._tracks;for(var n in t)if(t.hasOwnProperty(n)){if(!r[n]){r[n]=[];var i=this._getter(this._target,n);if(null==i)continue;0!==e&&r[n].push({time:0,value:d(i)})}r[n].push({time:e,value:t[n]})}return this},during:function(e){return this._onframeList.push(e),this},pause:function(){for(var e=0;et+s&&o>n+s||oe+s&&a>r+s||al&&(h=0,u={}),h++,u[r]=i,i}function i(e,t,r,i){var a=((e||"")+"").split("\n").length,o=n(e,t),s=n("国",t),u=a*s,h=new d(0,0,o,u);switch(h.lineHeight=s,i){case"bottom":case"alphabetic":h.y-=s;break;case"middle":h.y-=s/2}switch(r){case"end":case"right":h.x-=h.width;break;case"center":h.x-=h.width/2}return h}function a(e,t,r,n){var i=t.x,a=t.y,o=t.height,s=t.width,u=r.height,h=r.lineHeight,l=o/2-u/2+h,c="left";switch(e){case"left":i-=n,a+=l,c="right";break;case"right":i+=n+s,a+=l,c="left";break;case"top":i+=s/2,a-=n+u-h,c="center";break;case"bottom":i+=s/2,a+=o+n+h,c="center";break;case"inside":i+=s/2,a+=l,c="center";break;case"insideLeft":i+=n,a+=l,c="left";break;case"insideRight":i+=s-n,a+=l,c="right";break;case"insideTop":i+=s/2,a+=n+h,c="center";break;case"insideBottom":i+=s/2,a+=o-u-n+h,c="center";break;case"insideTopLeft":i+=n,a+=n+h,c="left";break;case"insideTopRight":i+=s-n,a+=n+h,c="right";break;case"insideBottomLeft":i+=n,a+=o-u-n+h;break;case"insideBottomRight":i+=s-n,a+=o-u-n+h,c="right"}return{x:i,y:a,textAlign:c,textBaseline:"alphabetic"}}function o(e,t,r,i,a){if(!t)return"";a=a||{},i=f(i,"...");for(var o=f(a.maxIterations,2),u=f(a.minChar,0),h=n("国",r),l=n("a",r),c=f(a.placeholder,""),d=t=Math.max(0,t-1),p=0;p=l;p++)d-=l;var _=n(i);_>d&&(i="",_=0),d=t-_;for(var m=(e+"").split("\n"),p=0,g=m.length;p=o){v+=i;break}var T=0===x?s(v,d,l,h):y>0?Math.floor(v.length*d/y):0;v=v.substr(0,T),y=n(v,r)}""===v&&(v=c),m[p]=v}}return m.join("\n")}function s(e,t,r,n){for(var i=0,a=0,o=e.length;a255?255:e}function i(e){return e=Math.round(e),e<0?0:e>360?360:e}function a(e){return e<0?0:e>1?1:e}function o(e){return n(e.length&&"%"===e.charAt(e.length-1)?parseFloat(e)/100*255:parseInt(e,10))}function s(e){return a(e.length&&"%"===e.charAt(e.length-1)?parseFloat(e)/100:parseFloat(e))}function u(e,t,r){return r<0?r+=1:r>1&&(r-=1),6*r<1?e+(t-e)*r*6:2*r<1?t:3*r<2?e+(t-e)*(2/3-r)*6:e}function h(e,t,r){return e+(t-e)*r}function l(e,t,r,n,i){return e[0]=t,e[1]=r,e[2]=n,e[3]=i,e}function c(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e}function d(e,t){A&&c(A,t),A=S.put(e,A||t.slice())}function f(e,t){if(e){t=t||[];var r=S.get(e);if(r)return c(t,r);e+="";var n=e.replace(/ /g,"").toLowerCase();if(n in E)return c(t,E[n]),d(e,t),t;if("#"!==n.charAt(0)){var i=n.indexOf("("),a=n.indexOf(")");if(-1!==i&&a+1===n.length){var u=n.substr(0,i),h=n.substr(i+1,a-(i+1)).split(","),f=1;switch(u){case"rgba":if(4!==h.length)return void l(t,0,0,0,1);f=s(h.pop());case"rgb":return 3!==h.length?void l(t,0,0,0,1):(l(t,o(h[0]),o(h[1]),o(h[2]),f),d(e,t),t);case"hsla":return 4!==h.length?void l(t,0,0,0,1):(h[3]=s(h[3]),p(h,t),d(e,t),t);case"hsl":return 3!==h.length?void l(t,0,0,0,1):(p(h,t),d(e,t),t);default:return}}l(t,0,0,0,1)}else{if(4===n.length){var _=parseInt(n.substr(1),16);return _>=0&&_<=4095?(l(t,(3840&_)>>4|(3840&_)>>8,240&_|(240&_)>>4,15&_|(15&_)<<4,1),d(e,t),t):void l(t,0,0,0,1)}if(7===n.length){var _=parseInt(n.substr(1),16);return _>=0&&_<=16777215?(l(t,(16711680&_)>>16,(65280&_)>>8,255&_,1),d(e,t),t):void l(t,0,0,0,1)}}}}function p(e,t){var r=(parseFloat(e[0])%360+360)%360/360,i=s(e[1]),a=s(e[2]),o=a<=.5?a*(i+1):a+i-a*i,h=2*a-o;return t=t||[],l(t,n(255*u(h,o,r+1/3)),n(255*u(h,o,r)),n(255*u(h,o,r-1/3)),1),4===e.length&&(t[3]=e[3]),t}function _(e){if(e){var t,r,n=e[0]/255,i=e[1]/255,a=e[2]/255,o=Math.min(n,i,a),s=Math.max(n,i,a),u=s-o,h=(s+o)/2;if(0===u)t=0,r=0;else{r=h<.5?u/(s+o):u/(2-s-o);var l=((s-n)/6+u/2)/u,c=((s-i)/6+u/2)/u,d=((s-a)/6+u/2)/u;n===s?t=d-c:i===s?t=1/3+l-d:a===s&&(t=2/3+c-l),t<0&&(t+=1),t>1&&(t-=1)}var f=[360*t,r,h];return null!=e[3]&&f.push(e[3]),f}}function m(e,t){var r=f(e);if(r){for(var n=0;n<3;n++)r[n]=t<0?r[n]*(1-t)|0:(255-r[n])*t+r[n]|0;return b(r,4===r.length?"rgba":"rgb")}}function g(e,t){var r=f(e);if(r)return((1<<24)+(r[0]<<16)+(r[1]<<8)+ +r[2]).toString(16).slice(1)}function v(e,t,r){if(t&&t.length&&e>=0&&e<=1){r=r||[];var i=e*(t.length-1),o=Math.floor(i),s=Math.ceil(i),u=t[o],l=t[s],c=i-o;return r[0]=n(h(u[0],l[0],c)),r[1]=n(h(u[1],l[1],c)),r[2]=n(h(u[2],l[2],c)),r[3]=a(h(u[3],l[3],c)),r}}function y(e,t,r){if(t&&t.length&&e>=0&&e<=1){var i=e*(t.length-1),o=Math.floor(i),s=Math.ceil(i),u=f(t[o]),l=f(t[s]),c=i-o,d=b([n(h(u[0],l[0],c)),n(h(u[1],l[1],c)),n(h(u[2],l[2],c)),a(h(u[3],l[3],c))],"rgba");return r?{color:d,leftIndex:o,rightIndex:s,value:i}:d}}function x(e,t,r,n){if(e=f(e))return e=_(e),null!=t&&(e[0]=i(t)),null!=r&&(e[1]=s(r)),null!=n&&(e[2]=s(n)),b(p(e),"rgba")}function T(e,t){if((e=f(e))&&null!=t)return e[3]=a(t),b(e,"rgba")}function b(e,t){if(e&&e.length){var r=e[0]+","+e[1]+","+e[2];return"rgba"!==t&&"hsva"!==t&&"hsla"!==t||(r+=","+e[3]),t+"("+r+")"}}var w=r(84),E={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]},S=new w(20),A=null;e.exports={parse:f,lift:m,toHex:g,fastMapToColor:v,mapToColor:y,modifyHSL:x,modifyAlpha:T,stringify:b}}])});
\ No newline at end of file
diff --git a/智慧气象/气象预报大数据平台/js/echarts.js b/智慧气象/气象预报大数据平台/js/echarts.js
new file mode 100644
index 0000000..6a43247
--- /dev/null
+++ b/智慧气象/气象预报大数据平台/js/echarts.js
@@ -0,0 +1,75108 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["echarts"] = factory();
+ else
+ root["echarts"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Export echarts as CommonJS module
+ */
+ module.exports = __webpack_require__(1);
+
+ // Import all charts and components
+ __webpack_require__(113);
+ __webpack_require__(139);
+ __webpack_require__(146);
+ __webpack_require__(155);
+ __webpack_require__(159);
+
+ __webpack_require__(169);
+ __webpack_require__(193);
+ __webpack_require__(205);
+ __webpack_require__(226);
+ __webpack_require__(230);
+ __webpack_require__(234);
+ __webpack_require__(251);
+ __webpack_require__(257);
+ __webpack_require__(264);
+ __webpack_require__(270);
+ __webpack_require__(274);
+ __webpack_require__(283);
+ __webpack_require__(287);
+ __webpack_require__(290);
+ __webpack_require__(313);
+
+ __webpack_require__(319);
+ __webpack_require__(320);
+ __webpack_require__(321);
+ __webpack_require__(327);
+ __webpack_require__(298);
+ __webpack_require__(331);
+ __webpack_require__(344);
+ __webpack_require__(235);
+ __webpack_require__(291);
+ __webpack_require__(347);
+ __webpack_require__(358);
+
+ __webpack_require__(362);
+
+ __webpack_require__(363);
+ __webpack_require__(376);
+
+ __webpack_require__(391);
+ __webpack_require__(397);
+ __webpack_require__(400);
+
+ __webpack_require__(403);
+ __webpack_require__(412);
+
+ __webpack_require__(424);
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // Enable DEV mode when using source code without build. which has no __DEV__ variable
+ // In build process 'typeof __DEV__' will be replace with 'boolean'
+ // So this code will be removed or disabled anyway after built.
+ if (false) {
+ // In browser
+ if (typeof window !== 'undefined') {
+ window.__DEV__ = true;
+ }
+ // In node
+ else if (typeof global !== 'undefined') {
+ global.__DEV__ = true;
+ }
+ }
+
+ /*!
+ * ECharts, a javascript interactive chart library.
+ *
+ * Copyright (c) 2015, Baidu Inc.
+ * All rights reserved.
+ *
+ * LICENSE
+ * https://github.com/ecomfe/echarts/blob/master/LICENSE.txt
+ */
+
+ /**
+ * @module echarts
+ */
+
+
+ var env = __webpack_require__(2);
+
+ var GlobalModel = __webpack_require__(3);
+ var ExtensionAPI = __webpack_require__(75);
+ var CoordinateSystemManager = __webpack_require__(76);
+ var OptionManager = __webpack_require__(77);
+
+ var ComponentModel = __webpack_require__(69);
+ var SeriesModel = __webpack_require__(78);
+
+ var ComponentView = __webpack_require__(79);
+ var ChartView = __webpack_require__(80);
+ var graphic = __webpack_require__(18);
+ var modelUtil = __webpack_require__(5);
+ var throttle = __webpack_require__(81);
+
+ var zrender = __webpack_require__(82);
+ var zrUtil = __webpack_require__(4);
+ var colorTool = __webpack_require__(31);
+ var Eventful = __webpack_require__(25);
+ var timsort = __webpack_require__(86);
+
+ var each = zrUtil.each;
+ var parseClassType = ComponentModel.parseClassType;
+
+ var PRIORITY_PROCESSOR_FILTER = 1000;
+ var PRIORITY_PROCESSOR_STATISTIC = 5000;
+
+
+ var PRIORITY_VISUAL_LAYOUT = 1000;
+ var PRIORITY_VISUAL_GLOBAL = 2000;
+ var PRIORITY_VISUAL_CHART = 3000;
+ var PRIORITY_VISUAL_COMPONENT = 4000;
+ // FIXME
+ // necessary?
+ var PRIORITY_VISUAL_BRUSH = 5000;
+
+ // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
+ // where they must not be invoked nestedly, except the only case: invoke
+ // dispatchAction with updateMethod "none" in main process.
+ // This flag is used to carry out this rule.
+ // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
+ var IN_MAIN_PROCESS = '__flagInMainProcess';
+ var HAS_GRADIENT_OR_PATTERN_BG = '__hasGradientOrPatternBg';
+ var OPTION_UPDATED = '__optionUpdated';
+ var ACTION_REG = /^[a-zA-Z0-9_]+$/;
+
+ function createRegisterEventWithLowercaseName(method) {
+ return function (eventName, handler, context) {
+ // Event name is all lowercase
+ eventName = eventName && eventName.toLowerCase();
+ Eventful.prototype[method].call(this, eventName, handler, context);
+ };
+ }
+
+ /**
+ * @module echarts~MessageCenter
+ */
+ function MessageCenter() {
+ Eventful.call(this);
+ }
+ MessageCenter.prototype.on = createRegisterEventWithLowercaseName('on');
+ MessageCenter.prototype.off = createRegisterEventWithLowercaseName('off');
+ MessageCenter.prototype.one = createRegisterEventWithLowercaseName('one');
+ zrUtil.mixin(MessageCenter, Eventful);
+
+ /**
+ * @module echarts~ECharts
+ */
+ function ECharts(dom, theme, opts) {
+ opts = opts || {};
+
+ // Get theme by name
+ if (typeof theme === 'string') {
+ theme = themeStorage[theme];
+ }
+
+ /**
+ * @type {string}
+ */
+ this.id;
+ /**
+ * Group id
+ * @type {string}
+ */
+ this.group;
+ /**
+ * @type {HTMLDomElement}
+ * @private
+ */
+ this._dom = dom;
+ /**
+ * @type {module:zrender/ZRender}
+ * @private
+ */
+ var zr = this._zr = zrender.init(dom, {
+ renderer: opts.renderer || 'canvas',
+ devicePixelRatio: opts.devicePixelRatio,
+ width: opts.width,
+ height: opts.height
+ });
+
+ /**
+ * Expect 60 pfs.
+ * @type {Function}
+ * @private
+ */
+ this._throttledZrFlush = throttle.throttle(zrUtil.bind(zr.flush, zr), 17);
+
+ /**
+ * @type {Object}
+ * @private
+ */
+ this._theme = zrUtil.clone(theme);
+
+ /**
+ * @type {Array.}
+ * @private
+ */
+ this._chartsViews = [];
+
+ /**
+ * @type {Object.}
+ * @private
+ */
+ this._chartsMap = {};
+
+ /**
+ * @type {Array.}
+ * @private
+ */
+ this._componentsViews = [];
+
+ /**
+ * @type {Object.}
+ * @private
+ */
+ this._componentsMap = {};
+
+ /**
+ * @type {module:echarts/CoordinateSystem}
+ * @private
+ */
+ this._coordSysMgr = new CoordinateSystemManager();
+
+ /**
+ * @type {module:echarts/ExtensionAPI}
+ * @private
+ */
+ this._api = createExtensionAPI(this);
+
+ Eventful.call(this);
+
+ /**
+ * @type {module:echarts~MessageCenter}
+ * @private
+ */
+ this._messageCenter = new MessageCenter();
+
+ // Init mouse events
+ this._initEvents();
+
+ // In case some people write `window.onresize = chart.resize`
+ this.resize = zrUtil.bind(this.resize, this);
+
+ // Can't dispatch action during rendering procedure
+ this._pendingActions = [];
+ // Sort on demand
+ function prioritySortFunc(a, b) {
+ return a.prio - b.prio;
+ }
+ timsort(visualFuncs, prioritySortFunc);
+ timsort(dataProcessorFuncs, prioritySortFunc);
+
+ zr.animation.on('frame', this._onframe, this);
+
+ // ECharts instance can be used as value.
+ zrUtil.setAsPrimitive(this);
+ }
+
+ var echartsProto = ECharts.prototype;
+
+ echartsProto._onframe = function () {
+ // Lazy update
+ if (this[OPTION_UPDATED]) {
+ var silent = this[OPTION_UPDATED].silent;
+
+ this[IN_MAIN_PROCESS] = true;
+
+ updateMethods.prepareAndUpdate.call(this);
+
+ this[IN_MAIN_PROCESS] = false;
+
+ this[OPTION_UPDATED] = false;
+
+ flushPendingActions.call(this, silent);
+
+ triggerUpdatedEvent.call(this, silent);
+ }
+ };
+ /**
+ * @return {HTMLDomElement}
+ */
+ echartsProto.getDom = function () {
+ return this._dom;
+ };
+
+ /**
+ * @return {module:zrender~ZRender}
+ */
+ echartsProto.getZr = function () {
+ return this._zr;
+ };
+
+ /**
+ * Usage:
+ * chart.setOption(option, notMerge, lazyUpdate);
+ * chart.setOption(option, {
+ * notMerge: ...,
+ * lazyUpdate: ...,
+ * silent: ...
+ * });
+ *
+ * @param {Object} option
+ * @param {Object|boolean} [opts] opts or notMerge.
+ * @param {boolean} [opts.notMerge=false]
+ * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently.
+ */
+ echartsProto.setOption = function (option, notMerge, lazyUpdate) {
+ if (true) {
+ zrUtil.assert(!this[IN_MAIN_PROCESS], '`setOption` should not be called during main process.');
+ }
+
+ var silent;
+ if (zrUtil.isObject(notMerge)) {
+ lazyUpdate = notMerge.lazyUpdate;
+ silent = notMerge.silent;
+ notMerge = notMerge.notMerge;
+ }
+
+ this[IN_MAIN_PROCESS] = true;
+
+ if (!this._model || notMerge) {
+ var optionManager = new OptionManager(this._api);
+ var theme = this._theme;
+ var ecModel = this._model = new GlobalModel(null, null, theme, optionManager);
+ ecModel.init(null, null, theme, optionManager);
+ }
+
+ this._model.setOption(option, optionPreprocessorFuncs);
+
+ if (lazyUpdate) {
+ this[OPTION_UPDATED] = {silent: silent};
+ this[IN_MAIN_PROCESS] = false;
+ }
+ else {
+ updateMethods.prepareAndUpdate.call(this);
+ // Ensure zr refresh sychronously, and then pixel in canvas can be
+ // fetched after `setOption`.
+ this._zr.flush();
+
+ this[OPTION_UPDATED] = false;
+ this[IN_MAIN_PROCESS] = false;
+
+ flushPendingActions.call(this, silent);
+ triggerUpdatedEvent.call(this, silent);
+ }
+ };
+
+ /**
+ * @DEPRECATED
+ */
+ echartsProto.setTheme = function () {
+ console.log('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
+ };
+
+ /**
+ * @return {module:echarts/model/Global}
+ */
+ echartsProto.getModel = function () {
+ return this._model;
+ };
+
+ /**
+ * @return {Object}
+ */
+ echartsProto.getOption = function () {
+ return this._model && this._model.getOption();
+ };
+
+ /**
+ * @return {number}
+ */
+ echartsProto.getWidth = function () {
+ return this._zr.getWidth();
+ };
+
+ /**
+ * @return {number}
+ */
+ echartsProto.getHeight = function () {
+ return this._zr.getHeight();
+ };
+
+ /**
+ * @return {number}
+ */
+ echartsProto.getDevicePixelRatio = function () {
+ return this._zr.painter.dpr || window.devicePixelRatio || 1;
+ };
+
+ /**
+ * Get canvas which has all thing rendered
+ * @param {Object} opts
+ * @param {string} [opts.backgroundColor]
+ */
+ echartsProto.getRenderedCanvas = function (opts) {
+ if (!env.canvasSupported) {
+ return;
+ }
+ opts = opts || {};
+ opts.pixelRatio = opts.pixelRatio || 1;
+ opts.backgroundColor = opts.backgroundColor
+ || this._model.get('backgroundColor');
+ var zr = this._zr;
+ var list = zr.storage.getDisplayList();
+ // Stop animations
+ zrUtil.each(list, function (el) {
+ el.stopAnimation(true);
+ });
+ return zr.painter.getRenderedCanvas(opts);
+ };
+ /**
+ * @return {string}
+ * @param {Object} opts
+ * @param {string} [opts.type='png']
+ * @param {string} [opts.pixelRatio=1]
+ * @param {string} [opts.backgroundColor]
+ * @param {string} [opts.excludeComponents]
+ */
+ echartsProto.getDataURL = function (opts) {
+ opts = opts || {};
+ var excludeComponents = opts.excludeComponents;
+ var ecModel = this._model;
+ var excludesComponentViews = [];
+ var self = this;
+
+ each(excludeComponents, function (componentType) {
+ ecModel.eachComponent({
+ mainType: componentType
+ }, function (component) {
+ var view = self._componentsMap[component.__viewId];
+ if (!view.group.ignore) {
+ excludesComponentViews.push(view);
+ view.group.ignore = true;
+ }
+ });
+ });
+
+ var url = this.getRenderedCanvas(opts).toDataURL(
+ 'image/' + (opts && opts.type || 'png')
+ );
+
+ each(excludesComponentViews, function (view) {
+ view.group.ignore = false;
+ });
+ return url;
+ };
+
+
+ /**
+ * @return {string}
+ * @param {Object} opts
+ * @param {string} [opts.type='png']
+ * @param {string} [opts.pixelRatio=1]
+ * @param {string} [opts.backgroundColor]
+ */
+ echartsProto.getConnectedDataURL = function (opts) {
+ if (!env.canvasSupported) {
+ return;
+ }
+ var groupId = this.group;
+ var mathMin = Math.min;
+ var mathMax = Math.max;
+ var MAX_NUMBER = Infinity;
+ if (connectedGroups[groupId]) {
+ var left = MAX_NUMBER;
+ var top = MAX_NUMBER;
+ var right = -MAX_NUMBER;
+ var bottom = -MAX_NUMBER;
+ var canvasList = [];
+ var dpr = (opts && opts.pixelRatio) || 1;
+
+ zrUtil.each(instances, function (chart, id) {
+ if (chart.group === groupId) {
+ var canvas = chart.getRenderedCanvas(
+ zrUtil.clone(opts)
+ );
+ var boundingRect = chart.getDom().getBoundingClientRect();
+ left = mathMin(boundingRect.left, left);
+ top = mathMin(boundingRect.top, top);
+ right = mathMax(boundingRect.right, right);
+ bottom = mathMax(boundingRect.bottom, bottom);
+ canvasList.push({
+ dom: canvas,
+ left: boundingRect.left,
+ top: boundingRect.top
+ });
+ }
+ });
+
+ left *= dpr;
+ top *= dpr;
+ right *= dpr;
+ bottom *= dpr;
+ var width = right - left;
+ var height = bottom - top;
+ var targetCanvas = zrUtil.createCanvas();
+ targetCanvas.width = width;
+ targetCanvas.height = height;
+ var zr = zrender.init(targetCanvas);
+
+ each(canvasList, function (item) {
+ var img = new graphic.Image({
+ style: {
+ x: item.left * dpr - left,
+ y: item.top * dpr - top,
+ image: item.dom
+ }
+ });
+ zr.add(img);
+ });
+ zr.refreshImmediately();
+
+ return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
+ }
+ else {
+ return this.getDataURL(opts);
+ }
+ };
+
+ /**
+ * Convert from logical coordinate system to pixel coordinate system.
+ * See CoordinateSystem#convertToPixel.
+ * @param {string|Object} finder
+ * If string, e.g., 'geo', means {geoIndex: 0}.
+ * If Object, could contain some of these properties below:
+ * {
+ * seriesIndex / seriesId / seriesName,
+ * geoIndex / geoId, geoName,
+ * bmapIndex / bmapId / bmapName,
+ * xAxisIndex / xAxisId / xAxisName,
+ * yAxisIndex / yAxisId / yAxisName,
+ * gridIndex / gridId / gridName,
+ * ... (can be extended)
+ * }
+ * @param {Array|number} value
+ * @return {Array|number} result
+ */
+ echartsProto.convertToPixel = zrUtil.curry(doConvertPixel, 'convertToPixel');
+
+ /**
+ * Convert from pixel coordinate system to logical coordinate system.
+ * See CoordinateSystem#convertFromPixel.
+ * @param {string|Object} finder
+ * If string, e.g., 'geo', means {geoIndex: 0}.
+ * If Object, could contain some of these properties below:
+ * {
+ * seriesIndex / seriesId / seriesName,
+ * geoIndex / geoId / geoName,
+ * bmapIndex / bmapId / bmapName,
+ * xAxisIndex / xAxisId / xAxisName,
+ * yAxisIndex / yAxisId / yAxisName
+ * gridIndex / gridId / gridName,
+ * ... (can be extended)
+ * }
+ * @param {Array|number} value
+ * @return {Array|number} result
+ */
+ echartsProto.convertFromPixel = zrUtil.curry(doConvertPixel, 'convertFromPixel');
+
+ function doConvertPixel(methodName, finder, value) {
+ var ecModel = this._model;
+ var coordSysList = this._coordSysMgr.getCoordinateSystems();
+ var result;
+
+ finder = modelUtil.parseFinder(ecModel, finder);
+
+ for (var i = 0; i < coordSysList.length; i++) {
+ var coordSys = coordSysList[i];
+ if (coordSys[methodName]
+ && (result = coordSys[methodName](ecModel, finder, value)) != null
+ ) {
+ return result;
+ }
+ }
+
+ if (true) {
+ console.warn(
+ 'No coordinate system that supports ' + methodName + ' found by the given finder.'
+ );
+ }
+ }
+
+ /**
+ * Is the specified coordinate systems or components contain the given pixel point.
+ * @param {string|Object} finder
+ * If string, e.g., 'geo', means {geoIndex: 0}.
+ * If Object, could contain some of these properties below:
+ * {
+ * seriesIndex / seriesId / seriesName,
+ * geoIndex / geoId / geoName,
+ * bmapIndex / bmapId / bmapName,
+ * xAxisIndex / xAxisId / xAxisName,
+ * yAxisIndex / yAxisId / yAxisName,
+ * gridIndex / gridId / gridName,
+ * ... (can be extended)
+ * }
+ * @param {Array|number} value
+ * @return {boolean} result
+ */
+ echartsProto.containPixel = function (finder, value) {
+ var ecModel = this._model;
+ var result;
+
+ finder = modelUtil.parseFinder(ecModel, finder);
+
+ zrUtil.each(finder, function (models, key) {
+ key.indexOf('Models') >= 0 && zrUtil.each(models, function (model) {
+ var coordSys = model.coordinateSystem;
+ if (coordSys && coordSys.containPoint) {
+ result |= !!coordSys.containPoint(value);
+ }
+ else if (key === 'seriesModels') {
+ var view = this._chartsMap[model.__viewId];
+ if (view && view.containPoint) {
+ result |= view.containPoint(value, model);
+ }
+ else {
+ if (true) {
+ console.warn(key + ': ' + (view
+ ? 'The found component do not support containPoint.'
+ : 'No view mapping to the found component.'
+ ));
+ }
+ }
+ }
+ else {
+ if (true) {
+ console.warn(key + ': containPoint is not supported');
+ }
+ }
+ }, this);
+ }, this);
+
+ return !!result;
+ };
+
+ /**
+ * Get visual from series or data.
+ * @param {string|Object} finder
+ * If string, e.g., 'series', means {seriesIndex: 0}.
+ * If Object, could contain some of these properties below:
+ * {
+ * seriesIndex / seriesId / seriesName,
+ * dataIndex / dataIndexInside
+ * }
+ * If dataIndex is not specified, series visual will be fetched,
+ * but not data item visual.
+ * If all of seriesIndex, seriesId, seriesName are not specified,
+ * visual will be fetched from first series.
+ * @param {string} visualType 'color', 'symbol', 'symbolSize'
+ */
+ echartsProto.getVisual = function (finder, visualType) {
+ var ecModel = this._model;
+
+ finder = modelUtil.parseFinder(ecModel, finder, {defaultMainType: 'series'});
+
+ var seriesModel = finder.seriesModel;
+
+ if (true) {
+ if (!seriesModel) {
+ console.warn('There is no specified seires model');
+ }
+ }
+
+ var data = seriesModel.getData();
+
+ var dataIndexInside = finder.hasOwnProperty('dataIndexInside')
+ ? finder.dataIndexInside
+ : finder.hasOwnProperty('dataIndex')
+ ? data.indexOfRawIndex(finder.dataIndex)
+ : null;
+
+ return dataIndexInside != null
+ ? data.getItemVisual(dataIndexInside, visualType)
+ : data.getVisual(visualType);
+ };
+
+ /**
+ * Get view of corresponding component model
+ * @param {module:echarts/model/Component} componentModel
+ * @return {module:echarts/view/Component}
+ */
+ echartsProto.getViewOfComponentModel = function (componentModel) {
+ return this._componentsMap[componentModel.__viewId];
+ };
+
+ /**
+ * Get view of corresponding series model
+ * @param {module:echarts/model/Series} seriesModel
+ * @return {module:echarts/view/Chart}
+ */
+ echartsProto.getViewOfSeriesModel = function (seriesModel) {
+ return this._chartsMap[seriesModel.__viewId];
+ };
+
+
+ var updateMethods = {
+
+ /**
+ * @param {Object} payload
+ * @private
+ */
+ update: function (payload) {
+ // console.profile && console.profile('update');
+
+ var ecModel = this._model;
+ var api = this._api;
+ var coordSysMgr = this._coordSysMgr;
+ var zr = this._zr;
+ // update before setOption
+ if (!ecModel) {
+ return;
+ }
+
+ // Fixme First time update ?
+ ecModel.restoreData();
+
+ // TODO
+ // Save total ecModel here for undo/redo (after restoring data and before processing data).
+ // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
+
+ // Create new coordinate system each update
+ // In LineView may save the old coordinate system and use it to get the orignal point
+ coordSysMgr.create(this._model, this._api);
+
+ processData.call(this, ecModel, api);
+
+ stackSeriesData.call(this, ecModel);
+
+ coordSysMgr.update(ecModel, api);
+
+ doVisualEncoding.call(this, ecModel, payload);
+
+ doRender.call(this, ecModel, payload);
+
+ // Set background
+ var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
+
+ var painter = zr.painter;
+ // TODO all use clearColor ?
+ if (painter.isSingleCanvas && painter.isSingleCanvas()) {
+ zr.configLayer(0, {
+ clearColor: backgroundColor
+ });
+ }
+ else {
+ // In IE8
+ if (!env.canvasSupported) {
+ var colorArr = colorTool.parse(backgroundColor);
+ backgroundColor = colorTool.stringify(colorArr, 'rgb');
+ if (colorArr[3] === 0) {
+ backgroundColor = 'transparent';
+ }
+ }
+ if (backgroundColor.colorStops || backgroundColor.image) {
+ // Gradient background
+ // FIXME Fixed layer?
+ zr.configLayer(0, {
+ clearColor: backgroundColor
+ });
+ this[HAS_GRADIENT_OR_PATTERN_BG] = true;
+
+ this._dom.style.background = 'transparent';
+ }
+ else {
+ if (this[HAS_GRADIENT_OR_PATTERN_BG]) {
+ zr.configLayer(0, {
+ clearColor: null
+ });
+ }
+ this[HAS_GRADIENT_OR_PATTERN_BG] = false;
+
+ this._dom.style.background = backgroundColor;
+ }
+ }
+
+ each(postUpdateFuncs, function (func) {
+ func(ecModel, api);
+ });
+
+ // console.profile && console.profileEnd('update');
+ },
+
+ /**
+ * @param {Object} payload
+ * @private
+ */
+ updateView: function (payload) {
+ var ecModel = this._model;
+
+ // update before setOption
+ if (!ecModel) {
+ return;
+ }
+
+ ecModel.eachSeries(function (seriesModel) {
+ seriesModel.getData().clearAllVisual();
+ });
+
+ doVisualEncoding.call(this, ecModel, payload);
+
+ invokeUpdateMethod.call(this, 'updateView', ecModel, payload);
+ },
+
+ /**
+ * @param {Object} payload
+ * @private
+ */
+ updateVisual: function (payload) {
+ var ecModel = this._model;
+
+ // update before setOption
+ if (!ecModel) {
+ return;
+ }
+
+ ecModel.eachSeries(function (seriesModel) {
+ seriesModel.getData().clearAllVisual();
+ });
+
+ doVisualEncoding.call(this, ecModel, payload, true);
+
+ invokeUpdateMethod.call(this, 'updateVisual', ecModel, payload);
+ },
+
+ /**
+ * @param {Object} payload
+ * @private
+ */
+ updateLayout: function (payload) {
+ var ecModel = this._model;
+
+ // update before setOption
+ if (!ecModel) {
+ return;
+ }
+
+ doLayout.call(this, ecModel, payload);
+
+ invokeUpdateMethod.call(this, 'updateLayout', ecModel, payload);
+ },
+
+ /**
+ * @param {Object} payload
+ * @private
+ */
+ prepareAndUpdate: function (payload) {
+ var ecModel = this._model;
+
+ prepareView.call(this, 'component', ecModel);
+
+ prepareView.call(this, 'chart', ecModel);
+
+ updateMethods.update.call(this, payload);
+ }
+ };
+
+ /**
+ * @private
+ */
+ function updateDirectly(ecIns, method, payload, mainType, subType) {
+ var ecModel = ecIns._model;
+
+ // broadcast
+ if (!mainType) {
+ each(ecIns._componentsViews.concat(ecIns._chartsViews), callView);
+ return;
+ }
+
+ var query = {};
+ query[mainType + 'Id'] = payload[mainType + 'Id'];
+ query[mainType + 'Index'] = payload[mainType + 'Index'];
+ query[mainType + 'Name'] = payload[mainType + 'Name'];
+
+ var condition = {mainType: mainType, query: query};
+ subType && (condition.subType = subType); // subType may be '' by parseClassType;
+
+ // If dispatchAction before setOption, do nothing.
+ ecModel && ecModel.eachComponent(condition, function (model, index) {
+ callView(ecIns[
+ mainType === 'series' ? '_chartsMap' : '_componentsMap'
+ ][model.__viewId]);
+ }, ecIns);
+
+ function callView(view) {
+ view && view.__alive && view[method] && view[method](
+ view.__model, ecModel, ecIns._api, payload
+ );
+ }
+ }
+
+ /**
+ * Resize the chart
+ * @param {Object} opts
+ * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
+ * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
+ * @param {boolean} [opts.silent=false]
+ */
+ echartsProto.resize = function (opts) {
+ if (true) {
+ zrUtil.assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.');
+ }
+
+ this[IN_MAIN_PROCESS] = true;
+
+ this._zr.resize(opts);
+
+ var optionChanged = this._model && this._model.resetOption('media');
+ var updateMethod = optionChanged ? 'prepareAndUpdate' : 'update';
+
+ updateMethods[updateMethod].call(this);
+
+ // Resize loading effect
+ this._loadingFX && this._loadingFX.resize();
+
+ this[IN_MAIN_PROCESS] = false;
+
+ var silent = opts && opts.silent;
+
+ flushPendingActions.call(this, silent);
+
+ triggerUpdatedEvent.call(this, silent);
+ };
+
+ /**
+ * Show loading effect
+ * @param {string} [name='default']
+ * @param {Object} [cfg]
+ */
+ echartsProto.showLoading = function (name, cfg) {
+ if (zrUtil.isObject(name)) {
+ cfg = name;
+ name = '';
+ }
+ name = name || 'default';
+
+ this.hideLoading();
+ if (!loadingEffects[name]) {
+ if (true) {
+ console.warn('Loading effects ' + name + ' not exists.');
+ }
+ return;
+ }
+ var el = loadingEffects[name](this._api, cfg);
+ var zr = this._zr;
+ this._loadingFX = el;
+
+ zr.add(el);
+ };
+
+ /**
+ * Hide loading effect
+ */
+ echartsProto.hideLoading = function () {
+ this._loadingFX && this._zr.remove(this._loadingFX);
+ this._loadingFX = null;
+ };
+
+ /**
+ * @param {Object} eventObj
+ * @return {Object}
+ */
+ echartsProto.makeActionFromEvent = function (eventObj) {
+ var payload = zrUtil.extend({}, eventObj);
+ payload.type = eventActionMap[eventObj.type];
+ return payload;
+ };
+
+ /**
+ * @pubilc
+ * @param {Object} payload
+ * @param {string} [payload.type] Action type
+ * @param {Object|boolean} [opt] If pass boolean, means opt.silent
+ * @param {boolean} [opt.silent=false] Whether trigger events.
+ * @param {boolean} [opt.flush=undefined]
+ * true: Flush immediately, and then pixel in canvas can be fetched
+ * immediately. Caution: it might affect performance.
+ * false: Not not flush.
+ * undefined: Auto decide whether perform flush.
+ */
+ echartsProto.dispatchAction = function (payload, opt) {
+ if (!zrUtil.isObject(opt)) {
+ opt = {silent: !!opt};
+ }
+
+ if (!actions[payload.type]) {
+ return;
+ }
+
+ // May dispatchAction in rendering procedure
+ if (this[IN_MAIN_PROCESS]) {
+ this._pendingActions.push(payload);
+ return;
+ }
+
+ doDispatchAction.call(this, payload, opt.silent);
+
+ if (opt.flush) {
+ this._zr.flush(true);
+ }
+ else if (opt.flush !== false && env.browser.weChat) {
+ // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
+ // hang when sliding page (on touch event), which cause that zr does not
+ // refresh util user interaction finished, which is not expected.
+ // But `dispatchAction` may be called too frequently when pan on touch
+ // screen, which impacts performance if do not throttle them.
+ this._throttledZrFlush();
+ }
+
+ flushPendingActions.call(this, opt.silent);
+
+ triggerUpdatedEvent.call(this, opt.silent);
+ };
+
+ function doDispatchAction(payload, silent) {
+ var payloadType = payload.type;
+ var escapeConnect = payload.escapeConnect;
+ var actionWrap = actions[payloadType];
+ var actionInfo = actionWrap.actionInfo;
+
+ var cptType = (actionInfo.update || 'update').split(':');
+ var updateMethod = cptType.pop();
+ cptType = cptType[0] != null && parseClassType(cptType[0]);
+
+ this[IN_MAIN_PROCESS] = true;
+
+ var payloads = [payload];
+ var batched = false;
+ // Batch action
+ if (payload.batch) {
+ batched = true;
+ payloads = zrUtil.map(payload.batch, function (item) {
+ item = zrUtil.defaults(zrUtil.extend({}, item), payload);
+ item.batch = null;
+ return item;
+ });
+ }
+
+ var eventObjBatch = [];
+ var eventObj;
+ var isHighDown = payloadType === 'highlight' || payloadType === 'downplay';
+
+ each(payloads, function (batchItem) {
+ // Action can specify the event by return it.
+ eventObj = actionWrap.action(batchItem, this._model, this._api);
+ // Emit event outside
+ eventObj = eventObj || zrUtil.extend({}, batchItem);
+ // Convert type to eventType
+ eventObj.type = actionInfo.event || eventObj.type;
+ eventObjBatch.push(eventObj);
+
+ // light update does not perform data process, layout and visual.
+ if (isHighDown) {
+ // method, payload, mainType, subType
+ updateDirectly(this, updateMethod, batchItem, 'series');
+ }
+ else if (cptType) {
+ updateDirectly(this, updateMethod, batchItem, cptType.main, cptType.sub);
+ }
+ }, this);
+
+ if (updateMethod !== 'none' && !isHighDown && !cptType) {
+ // Still dirty
+ if (this[OPTION_UPDATED]) {
+ // FIXME Pass payload ?
+ updateMethods.prepareAndUpdate.call(this, payload);
+ this[OPTION_UPDATED] = false;
+ }
+ else {
+ updateMethods[updateMethod].call(this, payload);
+ }
+ }
+
+ // Follow the rule of action batch
+ if (batched) {
+ eventObj = {
+ type: actionInfo.event || payloadType,
+ escapeConnect: escapeConnect,
+ batch: eventObjBatch
+ };
+ }
+ else {
+ eventObj = eventObjBatch[0];
+ }
+
+ this[IN_MAIN_PROCESS] = false;
+
+ !silent && this._messageCenter.trigger(eventObj.type, eventObj);
+ }
+
+ function flushPendingActions(silent) {
+ var pendingActions = this._pendingActions;
+ while (pendingActions.length) {
+ var payload = pendingActions.shift();
+ doDispatchAction.call(this, payload, silent);
+ }
+ }
+
+ function triggerUpdatedEvent(silent) {
+ !silent && this.trigger('updated');
+ }
+
+ /**
+ * Register event
+ * @method
+ */
+ echartsProto.on = createRegisterEventWithLowercaseName('on');
+ echartsProto.off = createRegisterEventWithLowercaseName('off');
+ echartsProto.one = createRegisterEventWithLowercaseName('one');
+
+ /**
+ * @param {string} methodName
+ * @private
+ */
+ function invokeUpdateMethod(methodName, ecModel, payload) {
+ var api = this._api;
+
+ // Update all components
+ each(this._componentsViews, function (component) {
+ var componentModel = component.__model;
+ component[methodName](componentModel, ecModel, api, payload);
+
+ updateZ(componentModel, component);
+ }, this);
+
+ // Upate all charts
+ ecModel.eachSeries(function (seriesModel, idx) {
+ var chart = this._chartsMap[seriesModel.__viewId];
+ chart[methodName](seriesModel, ecModel, api, payload);
+
+ updateZ(seriesModel, chart);
+
+ updateProgressiveAndBlend(seriesModel, chart);
+ }, this);
+
+ // If use hover layer
+ updateHoverLayerStatus(this._zr, ecModel);
+
+ // Post render
+ each(postUpdateFuncs, function (func) {
+ func(ecModel, api);
+ });
+ }
+
+ /**
+ * Prepare view instances of charts and components
+ * @param {module:echarts/model/Global} ecModel
+ * @private
+ */
+ function prepareView(type, ecModel) {
+ var isComponent = type === 'component';
+ var viewList = isComponent ? this._componentsViews : this._chartsViews;
+ var viewMap = isComponent ? this._componentsMap : this._chartsMap;
+ var zr = this._zr;
+
+ for (var i = 0; i < viewList.length; i++) {
+ viewList[i].__alive = false;
+ }
+
+ ecModel[isComponent ? 'eachComponent' : 'eachSeries'](function (componentType, model) {
+ if (isComponent) {
+ if (componentType === 'series') {
+ return;
+ }
+ }
+ else {
+ model = componentType;
+ }
+
+ // Consider: id same and type changed.
+ var viewId = '_ec_' + model.id + '_' + model.type;
+ var view = viewMap[viewId];
+ if (!view) {
+ var classType = parseClassType(model.type);
+ var Clazz = isComponent
+ ? ComponentView.getClass(classType.main, classType.sub)
+ : ChartView.getClass(classType.sub);
+ if (Clazz) {
+ view = new Clazz();
+ view.init(ecModel, this._api);
+ viewMap[viewId] = view;
+ viewList.push(view);
+ zr.add(view.group);
+ }
+ else {
+ // Error
+ return;
+ }
+ }
+
+ model.__viewId = view.__id = viewId;
+ view.__alive = true;
+ view.__model = model;
+ view.group.__ecComponentInfo = {
+ mainType: model.mainType,
+ index: model.componentIndex
+ };
+ }, this);
+
+ for (var i = 0; i < viewList.length;) {
+ var view = viewList[i];
+ if (!view.__alive) {
+ zr.remove(view.group);
+ view.dispose(ecModel, this._api);
+ viewList.splice(i, 1);
+ delete viewMap[view.__id];
+ view.__id = view.group.__ecComponentInfo = null;
+ }
+ else {
+ i++;
+ }
+ }
+ }
+
+ /**
+ * Processor data in each series
+ *
+ * @param {module:echarts/model/Global} ecModel
+ * @private
+ */
+ function processData(ecModel, api) {
+ each(dataProcessorFuncs, function (process) {
+ process.func(ecModel, api);
+ });
+ }
+
+ /**
+ * @private
+ */
+ function stackSeriesData(ecModel) {
+ var stackedDataMap = {};
+ ecModel.eachSeries(function (series) {
+ var stack = series.get('stack');
+ var data = series.getData();
+ if (stack && data.type === 'list') {
+ var previousStack = stackedDataMap[stack];
+ // Avoid conflict with Object.prototype
+ if (stackedDataMap.hasOwnProperty(stack) && previousStack) {
+ data.stackedOn = previousStack;
+ }
+ stackedDataMap[stack] = data;
+ }
+ });
+ }
+
+ /**
+ * Layout before each chart render there series, special visual encoding stage
+ *
+ * @param {module:echarts/model/Global} ecModel
+ * @private
+ */
+ function doLayout(ecModel, payload) {
+ var api = this._api;
+ each(visualFuncs, function (visual) {
+ if (visual.isLayout) {
+ visual.func(ecModel, api, payload);
+ }
+ });
+ }
+
+ /**
+ * Encode visual infomation from data after data processing
+ *
+ * @param {module:echarts/model/Global} ecModel
+ * @param {object} layout
+ * @param {boolean} [excludesLayout]
+ * @private
+ */
+ function doVisualEncoding(ecModel, payload, excludesLayout) {
+ var api = this._api;
+ ecModel.clearColorPalette();
+ ecModel.eachSeries(function (seriesModel) {
+ seriesModel.clearColorPalette();
+ });
+ each(visualFuncs, function (visual) {
+ (!excludesLayout || !visual.isLayout)
+ && visual.func(ecModel, api, payload);
+ });
+ }
+
+ /**
+ * Render each chart and component
+ * @private
+ */
+ function doRender(ecModel, payload) {
+ var api = this._api;
+ // Render all components
+ each(this._componentsViews, function (componentView) {
+ var componentModel = componentView.__model;
+ componentView.render(componentModel, ecModel, api, payload);
+
+ updateZ(componentModel, componentView);
+ }, this);
+
+ each(this._chartsViews, function (chart) {
+ chart.__alive = false;
+ }, this);
+
+ // Render all charts
+ ecModel.eachSeries(function (seriesModel, idx) {
+ var chartView = this._chartsMap[seriesModel.__viewId];
+ chartView.__alive = true;
+ chartView.render(seriesModel, ecModel, api, payload);
+
+ chartView.group.silent = !!seriesModel.get('silent');
+
+ updateZ(seriesModel, chartView);
+
+ updateProgressiveAndBlend(seriesModel, chartView);
+
+ }, this);
+
+ // If use hover layer
+ updateHoverLayerStatus(this._zr, ecModel);
+
+ // Remove groups of unrendered charts
+ each(this._chartsViews, function (chart) {
+ if (!chart.__alive) {
+ chart.remove(ecModel, api);
+ }
+ }, this);
+ }
+
+ var MOUSE_EVENT_NAMES = [
+ 'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove',
+ 'mousedown', 'mouseup', 'globalout', 'contextmenu'
+ ];
+ /**
+ * @private
+ */
+ echartsProto._initEvents = function () {
+ each(MOUSE_EVENT_NAMES, function (eveName) {
+ this._zr.on(eveName, function (e) {
+ var ecModel = this.getModel();
+ var el = e.target;
+ var params;
+
+ // no e.target when 'globalout'.
+ if (eveName === 'globalout') {
+ params = {};
+ }
+ else if (el && el.dataIndex != null) {
+ var dataModel = el.dataModel || ecModel.getSeriesByIndex(el.seriesIndex);
+ params = dataModel && dataModel.getDataParams(el.dataIndex, el.dataType) || {};
+ }
+ // If element has custom eventData of components
+ else if (el && el.eventData) {
+ params = zrUtil.extend({}, el.eventData);
+ }
+
+ if (params) {
+ params.event = e;
+ params.type = eveName;
+ this.trigger(eveName, params);
+ }
+
+ }, this);
+ }, this);
+
+ each(eventActionMap, function (actionType, eventType) {
+ this._messageCenter.on(eventType, function (event) {
+ this.trigger(eventType, event);
+ }, this);
+ }, this);
+ };
+
+ /**
+ * @return {boolean}
+ */
+ echartsProto.isDisposed = function () {
+ return this._disposed;
+ };
+
+ /**
+ * Clear
+ */
+ echartsProto.clear = function () {
+ this.setOption({ series: [] }, true);
+ };
+
+ /**
+ * Dispose instance
+ */
+ echartsProto.dispose = function () {
+ if (this._disposed) {
+ if (true) {
+ console.warn('Instance ' + this.id + ' has been disposed');
+ }
+ return;
+ }
+ this._disposed = true;
+
+ var api = this._api;
+ var ecModel = this._model;
+
+ each(this._componentsViews, function (component) {
+ component.dispose(ecModel, api);
+ });
+ each(this._chartsViews, function (chart) {
+ chart.dispose(ecModel, api);
+ });
+
+ // Dispose after all views disposed
+ this._zr.dispose();
+
+ delete instances[this.id];
+ };
+
+ zrUtil.mixin(ECharts, Eventful);
+
+ function updateHoverLayerStatus(zr, ecModel) {
+ var storage = zr.storage;
+ var elCount = 0;
+ storage.traverse(function (el) {
+ if (!el.isGroup) {
+ elCount++;
+ }
+ });
+ if (elCount > ecModel.get('hoverLayerThreshold') && !env.node) {
+ storage.traverse(function (el) {
+ if (!el.isGroup) {
+ el.useHoverLayer = true;
+ }
+ });
+ }
+ }
+
+ /**
+ * Update chart progressive and blend.
+ * @param {module:echarts/model/Series|module:echarts/model/Component} model
+ * @param {module:echarts/view/Component|module:echarts/view/Chart} view
+ */
+ function updateProgressiveAndBlend(seriesModel, chartView) {
+ // Progressive configuration
+ var elCount = 0;
+ chartView.group.traverse(function (el) {
+ if (el.type !== 'group' && !el.ignore) {
+ elCount++;
+ }
+ });
+ var frameDrawNum = +seriesModel.get('progressive');
+ var needProgressive = elCount > seriesModel.get('progressiveThreshold') && frameDrawNum && !env.node;
+ if (needProgressive) {
+ chartView.group.traverse(function (el) {
+ // FIXME marker and other components
+ if (!el.isGroup) {
+ el.progressive = needProgressive ?
+ Math.floor(elCount++ / frameDrawNum) : -1;
+ if (needProgressive) {
+ el.stopAnimation(true);
+ }
+ }
+ });
+ }
+
+ // Blend configration
+ var blendMode = seriesModel.get('blendMode') || null;
+ if (true) {
+ if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
+ console.warn('Only canvas support blendMode');
+ }
+ }
+ chartView.group.traverse(function (el) {
+ // FIXME marker and other components
+ if (!el.isGroup) {
+ el.setStyle('blend', blendMode);
+ }
+ });
+ }
+
+ /**
+ * @param {module:echarts/model/Series|module:echarts/model/Component} model
+ * @param {module:echarts/view/Component|module:echarts/view/Chart} view
+ */
+ function updateZ(model, view) {
+ var z = model.get('z');
+ var zlevel = model.get('zlevel');
+ // Set z and zlevel
+ view.group.traverse(function (el) {
+ if (el.type !== 'group') {
+ z != null && (el.z = z);
+ zlevel != null && (el.zlevel = zlevel);
+ }
+ });
+ }
+
+ function createExtensionAPI(ecInstance) {
+ var coordSysMgr = ecInstance._coordSysMgr;
+ return zrUtil.extend(new ExtensionAPI(ecInstance), {
+ // Inject methods
+ getCoordinateSystems: zrUtil.bind(
+ coordSysMgr.getCoordinateSystems, coordSysMgr
+ ),
+ getComponentByElement: function (el) {
+ while (el) {
+ var modelInfo = el.__ecComponentInfo;
+ if (modelInfo != null) {
+ return ecInstance._model.getComponent(modelInfo.mainType, modelInfo.index);
+ }
+ el = el.parent;
+ }
+ }
+ });
+ }
+
+ /**
+ * @type {Object} key: actionType.
+ * @inner
+ */
+ var actions = {};
+
+ /**
+ * Map eventType to actionType
+ * @type {Object}
+ */
+ var eventActionMap = {};
+
+ /**
+ * Data processor functions of each stage
+ * @type {Array.>}
+ * @inner
+ */
+ var dataProcessorFuncs = [];
+
+ /**
+ * @type {Array.}
+ * @inner
+ */
+ var optionPreprocessorFuncs = [];
+
+ /**
+ * @type {Array.}
+ * @inner
+ */
+ var postUpdateFuncs = [];
+
+ /**
+ * Visual encoding functions of each stage
+ * @type {Array.>}
+ * @inner
+ */
+ var visualFuncs = [];
+ /**
+ * Theme storage
+ * @type {Object.}
+ */
+ var themeStorage = {};
+ /**
+ * Loading effects
+ */
+ var loadingEffects = {};
+
+
+ var instances = {};
+ var connectedGroups = {};
+
+ var idBase = new Date() - 0;
+ var groupIdBase = new Date() - 0;
+ var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
+
+ /**
+ * @alias module:echarts
+ */
+ var echarts = {
+ /**
+ * @type {number}
+ */
+ version: '3.6.2',
+ dependencies: {
+ zrender: '3.5.2'
+ }
+ };
+
+ function enableConnect(chart) {
+ var STATUS_PENDING = 0;
+ var STATUS_UPDATING = 1;
+ var STATUS_UPDATED = 2;
+ var STATUS_KEY = '__connectUpdateStatus';
+
+ function updateConnectedChartsStatus(charts, status) {
+ for (var i = 0; i < charts.length; i++) {
+ var otherChart = charts[i];
+ otherChart[STATUS_KEY] = status;
+ }
+ }
+
+ zrUtil.each(eventActionMap, function (actionType, eventType) {
+ chart._messageCenter.on(eventType, function (event) {
+ if (connectedGroups[chart.group] && chart[STATUS_KEY] !== STATUS_PENDING) {
+ if (event && event.escapeConnect) {
+ return;
+ }
+
+ var action = chart.makeActionFromEvent(event);
+ var otherCharts = [];
+
+ zrUtil.each(instances, function (otherChart) {
+ if (otherChart !== chart && otherChart.group === chart.group) {
+ otherCharts.push(otherChart);
+ }
+ });
+
+ updateConnectedChartsStatus(otherCharts, STATUS_PENDING);
+ each(otherCharts, function (otherChart) {
+ if (otherChart[STATUS_KEY] !== STATUS_UPDATING) {
+ otherChart.dispatchAction(action);
+ }
+ });
+ updateConnectedChartsStatus(otherCharts, STATUS_UPDATED);
+ }
+ });
+ });
+ }
+
+ /**
+ * @param {HTMLDomElement} dom
+ * @param {Object} [theme]
+ * @param {Object} opts
+ * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default
+ * @param {string} [opts.renderer] Currently only 'canvas' is supported.
+ * @param {number} [opts.width] Use clientWidth of the input `dom` by default.
+ * Can be 'auto' (the same as null/undefined)
+ * @param {number} [opts.height] Use clientHeight of the input `dom` by default.
+ * Can be 'auto' (the same as null/undefined)
+ */
+ echarts.init = function (dom, theme, opts) {
+ if (true) {
+ // Check version
+ if ((zrender.version.replace('.', '') - 0) < (echarts.dependencies.zrender.replace('.', '') - 0)) {
+ throw new Error(
+ 'ZRender ' + zrender.version
+ + ' is too old for ECharts ' + echarts.version
+ + '. Current version need ZRender '
+ + echarts.dependencies.zrender + '+'
+ );
+ }
+
+ if (!dom) {
+ throw new Error('Initialize failed: invalid dom.');
+ }
+ }
+
+ var existInstance = echarts.getInstanceByDom(dom);
+ if (existInstance) {
+ if (true) {
+ console.warn('There is a chart instance already initialized on the dom.');
+ }
+ return existInstance;
+ }
+
+ if (true) {
+ if (zrUtil.isDom(dom)
+ && dom.nodeName.toUpperCase() !== 'CANVAS'
+ && (
+ (!dom.clientWidth && (!opts || opts.width == null))
+ || (!dom.clientHeight && (!opts || opts.height == null))
+ )
+ ) {
+ console.warn('Can\'t get dom width or height');
+ }
+ }
+
+ var chart = new ECharts(dom, theme, opts);
+ chart.id = 'ec_' + idBase++;
+ instances[chart.id] = chart;
+
+ if (dom.setAttribute) {
+ dom.setAttribute(DOM_ATTRIBUTE_KEY, chart.id);
+ }
+ else {
+ dom[DOM_ATTRIBUTE_KEY] = chart.id;
+ }
+
+ enableConnect(chart);
+
+ return chart;
+ };
+
+ /**
+ * @return {string|Array.} groupId
+ */
+ echarts.connect = function (groupId) {
+ // Is array of charts
+ if (zrUtil.isArray(groupId)) {
+ var charts = groupId;
+ groupId = null;
+ // If any chart has group
+ zrUtil.each(charts, function (chart) {
+ if (chart.group != null) {
+ groupId = chart.group;
+ }
+ });
+ groupId = groupId || ('g_' + groupIdBase++);
+ zrUtil.each(charts, function (chart) {
+ chart.group = groupId;
+ });
+ }
+ connectedGroups[groupId] = true;
+ return groupId;
+ };
+
+ /**
+ * @DEPRECATED
+ * @return {string} groupId
+ */
+ echarts.disConnect = function (groupId) {
+ connectedGroups[groupId] = false;
+ };
+
+ /**
+ * @return {string} groupId
+ */
+ echarts.disconnect = echarts.disConnect;
+
+ /**
+ * Dispose a chart instance
+ * @param {module:echarts~ECharts|HTMLDomElement|string} chart
+ */
+ echarts.dispose = function (chart) {
+ if (typeof chart === 'string') {
+ chart = instances[chart];
+ }
+ else if (!(chart instanceof ECharts)){
+ // Try to treat as dom
+ chart = echarts.getInstanceByDom(chart);
+ }
+ if ((chart instanceof ECharts) && !chart.isDisposed()) {
+ chart.dispose();
+ }
+ };
+
+ /**
+ * @param {HTMLDomElement} dom
+ * @return {echarts~ECharts}
+ */
+ echarts.getInstanceByDom = function (dom) {
+ var key;
+ if (dom.getAttribute) {
+ key = dom.getAttribute(DOM_ATTRIBUTE_KEY);
+ }
+ else {
+ key = dom[DOM_ATTRIBUTE_KEY];
+ }
+ return instances[key];
+ };
+
+ /**
+ * @param {string} key
+ * @return {echarts~ECharts}
+ */
+ echarts.getInstanceById = function (key) {
+ return instances[key];
+ };
+
+ /**
+ * Register theme
+ */
+ echarts.registerTheme = function (name, theme) {
+ themeStorage[name] = theme;
+ };
+
+ /**
+ * Register option preprocessor
+ * @param {Function} preprocessorFunc
+ */
+ echarts.registerPreprocessor = function (preprocessorFunc) {
+ optionPreprocessorFuncs.push(preprocessorFunc);
+ };
+
+ /**
+ * @param {number} [priority=1000]
+ * @param {Function} processorFunc
+ */
+ echarts.registerProcessor = function (priority, processorFunc) {
+ if (typeof priority === 'function') {
+ processorFunc = priority;
+ priority = PRIORITY_PROCESSOR_FILTER;
+ }
+ if (true) {
+ if (isNaN(priority)) {
+ throw new Error('Unkown processor priority');
+ }
+ }
+ dataProcessorFuncs.push({
+ prio: priority,
+ func: processorFunc
+ });
+ };
+
+ /**
+ * Register postUpdater
+ * @param {Function} postUpdateFunc
+ */
+ echarts.registerPostUpdate = function (postUpdateFunc) {
+ postUpdateFuncs.push(postUpdateFunc);
+ };
+
+ /**
+ * Usage:
+ * registerAction('someAction', 'someEvent', function () { ... });
+ * registerAction('someAction', function () { ... });
+ * registerAction(
+ * {type: 'someAction', event: 'someEvent', update: 'updateView'},
+ * function () { ... }
+ * );
+ *
+ * @param {(string|Object)} actionInfo
+ * @param {string} actionInfo.type
+ * @param {string} [actionInfo.event]
+ * @param {string} [actionInfo.update]
+ * @param {string} [eventName]
+ * @param {Function} action
+ */
+ echarts.registerAction = function (actionInfo, eventName, action) {
+ if (typeof eventName === 'function') {
+ action = eventName;
+ eventName = '';
+ }
+ var actionType = zrUtil.isObject(actionInfo)
+ ? actionInfo.type
+ : ([actionInfo, actionInfo = {
+ event: eventName
+ }][0]);
+
+ // Event name is all lowercase
+ actionInfo.event = (actionInfo.event || actionType).toLowerCase();
+ eventName = actionInfo.event;
+
+ // Validate action type and event name.
+ zrUtil.assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));
+
+ if (!actions[actionType]) {
+ actions[actionType] = {action: action, actionInfo: actionInfo};
+ }
+ eventActionMap[eventName] = actionType;
+ };
+
+ /**
+ * @param {string} type
+ * @param {*} CoordinateSystem
+ */
+ echarts.registerCoordinateSystem = function (type, CoordinateSystem) {
+ CoordinateSystemManager.register(type, CoordinateSystem);
+ };
+
+ /**
+ * Get dimensions of specified coordinate system.
+ * @param {string} type
+ * @return {Array.}
+ */
+ echarts.getCoordinateSystemDimensions = function (type) {
+ var coordSysCreator = CoordinateSystemManager.get(type);
+ if (coordSysCreator) {
+ return coordSysCreator.getDimensionsInfo
+ ? coordSysCreator.getDimensionsInfo()
+ : coordSysCreator.dimensions.slice();
+ }
+ };
+
+ /**
+ * Layout is a special stage of visual encoding
+ * Most visual encoding like color are common for different chart
+ * But each chart has it's own layout algorithm
+ *
+ * @param {number} [priority=1000]
+ * @param {Function} layoutFunc
+ */
+ echarts.registerLayout = function (priority, layoutFunc) {
+ if (typeof priority === 'function') {
+ layoutFunc = priority;
+ priority = PRIORITY_VISUAL_LAYOUT;
+ }
+ if (true) {
+ if (isNaN(priority)) {
+ throw new Error('Unkown layout priority');
+ }
+ }
+ visualFuncs.push({
+ prio: priority,
+ func: layoutFunc,
+ isLayout: true
+ });
+ };
+
+ /**
+ * @param {number} [priority=3000]
+ * @param {Function} visualFunc
+ */
+ echarts.registerVisual = function (priority, visualFunc) {
+ if (typeof priority === 'function') {
+ visualFunc = priority;
+ priority = PRIORITY_VISUAL_CHART;
+ }
+ if (true) {
+ if (isNaN(priority)) {
+ throw new Error('Unkown visual priority');
+ }
+ }
+ visualFuncs.push({
+ prio: priority,
+ func: visualFunc
+ });
+ };
+
+ /**
+ * @param {string} name
+ */
+ echarts.registerLoading = function (name, loadingFx) {
+ loadingEffects[name] = loadingFx;
+ };
+
+ /**
+ * @param {Object} opts
+ * @param {string} [superClass]
+ */
+ echarts.extendComponentModel = function (opts/*, superClass*/) {
+ // var Clazz = ComponentModel;
+ // if (superClass) {
+ // var classType = parseClassType(superClass);
+ // Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
+ // }
+ return ComponentModel.extend(opts);
+ };
+
+ /**
+ * @param {Object} opts
+ * @param {string} [superClass]
+ */
+ echarts.extendComponentView = function (opts/*, superClass*/) {
+ // var Clazz = ComponentView;
+ // if (superClass) {
+ // var classType = parseClassType(superClass);
+ // Clazz = ComponentView.getClass(classType.main, classType.sub, true);
+ // }
+ return ComponentView.extend(opts);
+ };
+
+ /**
+ * @param {Object} opts
+ * @param {string} [superClass]
+ */
+ echarts.extendSeriesModel = function (opts/*, superClass*/) {
+ // var Clazz = SeriesModel;
+ // if (superClass) {
+ // superClass = 'series.' + superClass.replace('series.', '');
+ // var classType = parseClassType(superClass);
+ // Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
+ // }
+ return SeriesModel.extend(opts);
+ };
+
+ /**
+ * @param {Object} opts
+ * @param {string} [superClass]
+ */
+ echarts.extendChartView = function (opts/*, superClass*/) {
+ // var Clazz = ChartView;
+ // if (superClass) {
+ // superClass = superClass.replace('series.', '');
+ // var classType = parseClassType(superClass);
+ // Clazz = ChartView.getClass(classType.main, true);
+ // }
+ return ChartView.extend(opts);
+ };
+
+ /**
+ * ZRender need a canvas context to do measureText.
+ * But in node environment canvas may be created by node-canvas.
+ * So we need to specify how to create a canvas instead of using document.createElement('canvas')
+ *
+ * Be careful of using it in the browser.
+ *
+ * @param {Function} creator
+ * @example
+ * var Canvas = require('canvas');
+ * var echarts = require('echarts');
+ * echarts.setCanvasCreator(function () {
+ * // Small size is enough.
+ * return new Canvas(32, 32);
+ * });
+ */
+ echarts.setCanvasCreator = function (creator) {
+ zrUtil.createCanvas = creator;
+ };
+
+ echarts.registerVisual(PRIORITY_VISUAL_GLOBAL, __webpack_require__(94));
+ echarts.registerPreprocessor(__webpack_require__(95));
+ echarts.registerLoading('default', __webpack_require__(97));
+
+ // Default action
+ echarts.registerAction({
+ type: 'highlight',
+ event: 'highlight',
+ update: 'highlight'
+ }, zrUtil.noop);
+ echarts.registerAction({
+ type: 'downplay',
+ event: 'downplay',
+ update: 'downplay'
+ }, zrUtil.noop);
+
+
+ // --------
+ // Exports
+ // --------
+ echarts.zrender = zrender;
+
+ echarts.List = __webpack_require__(98);
+ echarts.Model = __webpack_require__(12);
+
+ echarts.Axis = __webpack_require__(100);
+
+ echarts.graphic = __webpack_require__(18);
+ echarts.number = __webpack_require__(7);
+ echarts.format = __webpack_require__(6);
+ echarts.throttle = throttle.throttle;
+ echarts.matrix = __webpack_require__(11);
+ echarts.vector = __webpack_require__(10);
+ echarts.color = __webpack_require__(31);
+
+ echarts.util = {};
+ each([
+ 'map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter',
+ 'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction',
+ 'extend', 'defaults', 'clone', 'merge'
+ ],
+ function (name) {
+ echarts.util[name] = zrUtil[name];
+ }
+ );
+
+ echarts.helper = __webpack_require__(108);
+
+
+ // PRIORITY
+ echarts.PRIORITY = {
+ PROCESSOR: {
+ FILTER: PRIORITY_PROCESSOR_FILTER,
+ STATISTIC: PRIORITY_PROCESSOR_STATISTIC
+ },
+ VISUAL: {
+ LAYOUT: PRIORITY_VISUAL_LAYOUT,
+ GLOBAL: PRIORITY_VISUAL_GLOBAL,
+ CHART: PRIORITY_VISUAL_CHART,
+ COMPONENT: PRIORITY_VISUAL_COMPONENT,
+ BRUSH: PRIORITY_VISUAL_BRUSH
+ }
+ };
+
+ module.exports = echarts;
+
+
+/***/ },
+/* 2 */
+/***/ function(module, exports) {
+
+ /**
+ * echarts设备环境识别
+ *
+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
+ * @author firede[firede@firede.us]
+ * @desc thanks zepto.
+ */
+
+ var env = {};
+ if (typeof navigator === 'undefined') {
+ // In node
+ env = {
+ browser: {},
+ os: {},
+ node: true,
+ // Assume canvas is supported
+ canvasSupported: true
+ };
+ }
+ else {
+ env = detect(navigator.userAgent);
+ }
+
+ module.exports = env;
+
+ // Zepto.js
+ // (c) 2010-2013 Thomas Fuchs
+ // Zepto.js may be freely distributed under the MIT license.
+
+ function detect(ua) {
+ var os = {};
+ var browser = {};
+ // var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/);
+ // var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
+ // var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
+ // var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
+ // var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
+ // var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/);
+ // var touchpad = webos && ua.match(/TouchPad/);
+ // var kindle = ua.match(/Kindle\/([\d.]+)/);
+ // var silk = ua.match(/Silk\/([\d._]+)/);
+ // var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/);
+ // var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/);
+ // var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/);
+ // var playbook = ua.match(/PlayBook/);
+ // var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/);
+ var firefox = ua.match(/Firefox\/([\d.]+)/);
+ // var safari = webkit && ua.match(/Mobile\//) && !chrome;
+ // var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome;
+ var ie = ua.match(/MSIE\s([\d.]+)/)
+ // IE 11 Trident/7.0; rv:11.0
+ || ua.match(/Trident\/.+?rv:(([\d.]+))/);
+ var edge = ua.match(/Edge\/([\d.]+)/); // IE 12 and 12+
+
+ var weChat = (/micromessenger/i).test(ua);
+
+ // Todo: clean this up with a better OS/browser seperation:
+ // - discern (more) between multiple browsers on android
+ // - decide if kindle fire in silk mode is android or not
+ // - Firefox on Android doesn't specify the Android version
+ // - possibly devide in os, device and browser hashes
+
+ // if (browser.webkit = !!webkit) browser.version = webkit[1];
+
+ // if (android) os.android = true, os.version = android[2];
+ // if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');
+ // if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');
+ // if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
+ // if (webos) os.webos = true, os.version = webos[2];
+ // if (touchpad) os.touchpad = true;
+ // if (blackberry) os.blackberry = true, os.version = blackberry[2];
+ // if (bb10) os.bb10 = true, os.version = bb10[2];
+ // if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2];
+ // if (playbook) browser.playbook = true;
+ // if (kindle) os.kindle = true, os.version = kindle[1];
+ // if (silk) browser.silk = true, browser.version = silk[1];
+ // if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;
+ // if (chrome) browser.chrome = true, browser.version = chrome[1];
+ if (firefox) {
+ browser.firefox = true;
+ browser.version = firefox[1];
+ }
+ // if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true;
+ // if (webview) browser.webview = true;
+
+ if (ie) {
+ browser.ie = true;
+ browser.version = ie[1];
+ }
+
+ if (edge) {
+ browser.edge = true;
+ browser.version = edge[1];
+ }
+
+ // It is difficult to detect WeChat in Win Phone precisely, because ua can
+ // not be set on win phone. So we do not consider Win Phone.
+ if (weChat) {
+ browser.weChat = true;
+ }
+
+ // os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||
+ // (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)));
+ // os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos ||
+ // (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) ||
+ // (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))));
+
+ return {
+ browser: browser,
+ os: os,
+ node: false,
+ // 原生canvas支持,改极端点了
+ // canvasSupported : !(browser.ie && parseFloat(browser.version) < 9)
+ canvasSupported : document.createElement('canvas').getContext ? true : false,
+ // @see
+ // works on most browsers
+ // IE10/11 does not support touch event, and MS Edge supports them but not by
+ // default, so we dont check navigator.maxTouchPoints for them here.
+ touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge,
+ // .
+ pointerEventsSupported: 'onpointerdown' in window
+ // Firefox supports pointer but not by default, only MS browsers are reliable on pointer
+ // events currently. So we dont use that on other browsers unless tested sufficiently.
+ // Although IE 10 supports pointer event, it use old style and is different from the
+ // standard. So we exclude that. (IE 10 is hardly used on touch device)
+ && (browser.edge || (browser.ie && browser.version >= 11))
+ };
+ }
+
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ECharts global model
+ *
+ * @module {echarts/model/Global}
+ */
+
+
+
+ /**
+ * Caution: If the mechanism should be changed some day, these cases
+ * should be considered:
+ *
+ * (1) In `merge option` mode, if using the same option to call `setOption`
+ * many times, the result should be the same (try our best to ensure that).
+ * (2) In `merge option` mode, if a component has no id/name specified, it
+ * will be merged by index, and the result sequence of the components is
+ * consistent to the original sequence.
+ * (3) `reset` feature (in toolbox). Find detailed info in comments about
+ * `mergeOption` in module:echarts/model/OptionManager.
+ */
+
+ var zrUtil = __webpack_require__(4);
+ var modelUtil = __webpack_require__(5);
+ var Model = __webpack_require__(12);
+ 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 = __webpack_require__(69);
+
+ var globalDefault = __webpack_require__(73);
+
+ var OPTION_INNER_KEY = '\0_ec_inner';
+
+ /**
+ * @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) {
+ zrUtil.assert(
+ !(OPTION_INNER_KEY in option),
+ 'please use chart.getOption()'
+ );
+
+ this._optionManager.setOption(option, optionPreprocessorFuncs);
+
+ this.resetOption(null);
+ },
+
+ /**
+ * @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(type === 'recreate');
+
+ if (!this.option || type === 'recreate') {
+ initBase.call(this, baseOption);
+ }
+ else {
+ this.restoreData();
+ this.mergeOption(baseOption);
+ }
+ optionChanged = true;
+ }
+
+ if (type === 'timeline' || type === 'media') {
+ this.restoreData();
+ }
+
+ if (!type || type === 'recreate' || type === 'timeline') {
+ var timelineOption = optionManager.getTimelineOption(this);
+ timelineOption && (this.mergeOption(timelineOption), optionChanged = true);
+ }
+
+ if (!type || type === 'recreate' || type === 'media') {
+ var mediaOptions = optionManager.getMediaOption(this, this._api);
+ if (mediaOptions.length) {
+ each(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
+ );
+
+ this._seriesIndices = this._seriesIndices || [];
+
+ function visitComponent(mainType, dependencies) {
+ var newCptOptionList = modelUtil.normalizeToArray(newOption[mainType]);
+
+ var mapResult = modelUtil.mappingToExists(
+ componentsMap.get(mainType), newCptOptionList
+ );
+
+ modelUtil.makeIdAndName(mapResult);
+
+ // Set mainType and complete subType.
+ each(mapResult, function (item, index) {
+ var opt = item.option;
+ if (isObject(opt)) {
+ item.keyInfo.mainType = mainType;
+ item.keyInfo.subType = determineSubType(mainType, opt, item.exist);
+ }
+ });
+
+ var dependentModels = getComponentsByTypes(
+ componentsMap, dependencies
+ );
+
+ option[mainType] = [];
+ componentsMap.set(mainType, []);
+
+ each(mapResult, function (resultItem, index) {
+ var componentModel = resultItem.exist;
+ var newCptOption = resultItem.option;
+
+ zrUtil.assert(
+ isObject(newCptOption) || componentModel,
+ 'Empty component definition'
+ );
+
+ // Consider where is no new option and should be merged using {},
+ // see removeEdgeAndAdd in topologicalTravel and
+ // ComponentModel.getAllClassMainTypes.
+ if (!newCptOption) {
+ componentModel.mergeOption({}, this);
+ componentModel.optionUpdated({}, false);
+ }
+ else {
+ var ComponentModelClass = ComponentModel.getClass(
+ mainType, resultItem.keyInfo.subType, true
+ );
+
+ if (componentModel && componentModel instanceof ComponentModelClass) {
+ componentModel.name = resultItem.keyInfo.name;
+ componentModel.mergeOption(newCptOption, this);
+ componentModel.optionUpdated(newCptOption, false);
+ }
+ else {
+ // PENDING Global as parent ?
+ var extraOpt = zrUtil.extend(
+ {
+ dependentModels: dependentModels,
+ componentIndex: index
+ },
+ resultItem.keyInfo
+ );
+ componentModel = new ComponentModelClass(
+ newCptOption, this, this, extraOpt
+ );
+ zrUtil.extend(componentModel, extraOpt);
+ componentModel.init(newCptOption, this, this, extraOpt);
+ // Call optionUpdated after init.
+ // newCptOption has been used as componentModel.option
+ // and may be merged with theme and default, so pass null
+ // to avoid confusion.
+ componentModel.optionUpdated(null, true);
+ }
+ }
+
+ componentsMap.get(mainType)[index] = componentModel;
+ option[mainType][index] = componentModel.option;
+ }, this);
+
+ // Backup series for filtering.
+ if (mainType === 'series') {
+ this._seriesIndices = createSeriesIndices(componentsMap.get('series'));
+ }
+ }
+ },
+
+ /**
+ * Get option for output (cloned option and inner info removed)
+ * @public
+ * @return {Object}
+ */
+ getOption: function () {
+ var option = zrUtil.clone(this.option);
+
+ each(option, function (opts, mainType) {
+ if (ComponentModel.hasClass(mainType)) {
+ var opts = modelUtil.normalizeToArray(opts);
+ for (var i = opts.length - 1; i >= 0; i--) {
+ // Remove options with inner id.
+ if (modelUtil.isIdInner(opts[i])) {
+ opts.splice(i, 1);
+ }
+ }
+ option[mainType] = opts;
+ }
+ });
+
+ delete option[OPTION_INNER_KEY];
+
+ return option;
+ },
+
+ /**
+ * @return {module:echarts/model/Model}
+ */
+ getTheme: function () {
+ return this._theme;
+ },
+
+ /**
+ * @param {string} mainType
+ * @param {number} [idx=0]
+ * @return {module:echarts/model/Component}
+ */
+ getComponent: function (mainType, idx) {
+ var list = this._componentsMap.get(mainType);
+ if (list) {
+ return list[idx || 0];
+ }
+ },
+
+ /**
+ * If none of index and id and name used, return all components with mainType.
+ * @param {Object} condition
+ * @param {string} condition.mainType
+ * @param {string} [condition.subType] If ignore, only query by mainType
+ * @param {number|Array.} [condition.index] Either input index or id or name.
+ * @param {string|Array.} [condition.id] Either input index or id or name.
+ * @param {string|Array.} [condition.name] Either input index or id or name.
+ * @return {Array.}
+ */
+ queryComponents: function (condition) {
+ var mainType = condition.mainType;
+ if (!mainType) {
+ return [];
+ }
+
+ var index = condition.index;
+ var id = condition.id;
+ var name = condition.name;
+
+ var cpts = this._componentsMap.get(mainType);
+
+ if (!cpts || !cpts.length) {
+ return [];
+ }
+
+ var result;
+
+ if (index != null) {
+ if (!isArray(index)) {
+ index = [index];
+ }
+ result = filter(map(index, function (idx) {
+ return cpts[idx];
+ }), function (val) {
+ return !!val;
+ });
+ }
+ else if (id != null) {
+ var isIdArray = isArray(id);
+ result = filter(cpts, function (cpt) {
+ return (isIdArray && indexOf(id, cpt.id) >= 0)
+ || (!isIdArray && cpt.id === id);
+ });
+ }
+ else if (name != null) {
+ var isNameArray = isArray(name);
+ result = filter(cpts, function (cpt) {
+ return (isNameArray && indexOf(name, cpt.name) >= 0)
+ || (!isNameArray && cpt.name === name);
+ });
+ }
+ else {
+ // Return all components with mainType
+ result = cpts.slice();
+ }
+
+ return filterBySubType(result, condition);
+ },
+
+ /**
+ * The interface is different from queryComponents,
+ * which is convenient for inner usage.
+ *
+ * @usage
+ * var result = findComponents(
+ * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
+ * );
+ * var result = findComponents(
+ * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
+ * );
+ * var result = findComponents(
+ * {mainType: 'series'},
+ * function (model, index) {...}
+ * );
+ * // 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.}
+ */
+ findComponents: function (condition) {
+ var query = condition.query;
+ var mainType = condition.mainType;
+
+ var queryCond = getQueryCond(query);
+ var result = queryCond
+ ? this.queryComponents(queryCond)
+ : this._componentsMap.get(mainType);
+
+ return doFilter(filterBySubType(result, condition));
+
+ function getQueryCond(q) {
+ var indexAttr = mainType + 'Index';
+ var idAttr = mainType + 'Id';
+ var nameAttr = mainType + 'Name';
+ return q && (
+ q[indexAttr] != null
+ || q[idAttr] != null
+ || q[nameAttr] != null
+ )
+ ? {
+ mainType: mainType,
+ // 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;
+ componentsMap.each(function (components, componentType) {
+ each(components, function (component, index) {
+ cb.call(context, componentType, component, index);
+ });
+ });
+ }
+ else if (zrUtil.isString(mainType)) {
+ each(componentsMap.get(mainType), cb, context);
+ }
+ else if (isObject(mainType)) {
+ var queryResult = this.findComponents(mainType);
+ each(queryResult, cb, context);
+ }
+ },
+
+ /**
+ * @param {string} name
+ * @return {Array.}
+ */
+ getSeriesByName: function (name) {
+ var series = this._componentsMap.get('series');
+ return filter(series, function (oneSeries) {
+ return oneSeries.name === name;
+ });
+ },
+
+ /**
+ * @param {number} seriesIndex
+ * @return {module:echarts/model/Series}
+ */
+ getSeriesByIndex: function (seriesIndex) {
+ return this._componentsMap.get('series')[seriesIndex];
+ },
+
+ /**
+ * @param {string} subType
+ * @return {Array.}
+ */
+ getSeriesByType: function (subType) {
+ var series = this._componentsMap.get('series');
+ return filter(series, function (oneSeries) {
+ return oneSeries.subType === subType;
+ });
+ },
+
+ /**
+ * @return {Array.}
+ */
+ getSeries: function () {
+ return this._componentsMap.get('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.get('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.get('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.get('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;
+ },
+
+ /**
+ * @return {Array.}
+ */
+ getCurrentSeriesIndices: function () {
+ return (this._seriesIndices || []).slice();
+ },
+
+ /**
+ * @param {Function} cb
+ * @param {*} context
+ */
+ filterSeries: function (cb, context) {
+ assertSeriesInitialized(this);
+ var filteredSeries = filter(
+ this._componentsMap.get('series'), cb, context
+ );
+ this._seriesIndices = createSeriesIndices(filteredSeries);
+ },
+
+ restoreData: function () {
+ var componentsMap = this._componentsMap;
+
+ this._seriesIndices = createSeriesIndices(componentsMap.get('series'));
+
+ var componentTypes = [];
+ componentsMap.each(function (components, componentType) {
+ componentTypes.push(componentType);
+ });
+
+ ComponentModel.topologicalTravel(
+ componentTypes,
+ ComponentModel.getAllClassMainTypes(),
+ function (componentType, dependencies) {
+ each(componentsMap.get(componentType), function (component) {
+ component.restoreData();
+ });
+ }
+ );
+ }
+
+ });
+
+ /**
+ * @inner
+ */
+ function mergeTheme(option, theme) {
+ zrUtil.each(theme, function (themeItem, name) {
+ // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
+ if (!ComponentModel.hasClass(name)) {
+ if (typeof themeItem === 'object') {
+ option[name] = !option[name]
+ ? zrUtil.clone(themeItem)
+ : zrUtil.merge(option[name], themeItem, false);
+ }
+ else {
+ if (option[name] == null) {
+ option[name] = themeItem;
+ }
+ }
+ }
+ });
+ }
+
+ function initBase(baseOption) {
+ baseOption = baseOption;
+
+ // Using OPTION_INNER_KEY to mark that this option can not be used outside,
+ // i.e. `chart.setOption(chart.getModel().option);` is forbiden.
+ this.option = {};
+ this.option[OPTION_INNER_KEY] = 1;
+
+ /**
+ * Init with series: [], in case of calling findSeries method
+ * before series initialized.
+ * @type {Object.>}
+ * @private
+ */
+ this._componentsMap = zrUtil.createHashMap({series: []});
+
+ /**
+ * Mapping between filtered series list and raw series list.
+ * key: filtered series indices, value: raw series indices.
+ * @type {Array.}
+ * @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} types model types
+ * @return {Object} key: {string} type, value: {Array./g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+ };
+
+ var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
+
+ var wrapVar = function (varName, seriesIdx) {
+ return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
+ };
+
+ /**
+ * Template formatter
+ * @param {string} tpl
+ * @param {Array.|Object} paramsList
+ * @param {boolean} [encode=false]
+ * @return {string}
+ */
+ formatUtil.formatTpl = function (tpl, paramsList, encode) {
+ 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];
+ var val = wrapVar(alias, 0);
+ tpl = tpl.replace(wrapVar(alias), encode ? encodeHTML(val) : val);
+ }
+ for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
+ for (var k = 0; k < $vars.length; k++) {
+ var val = paramsList[seriesIdx][$vars[k]];
+ tpl = tpl.replace(
+ wrapVar(TPL_VAR_ALIAS[k], seriesIdx),
+ encode ? encodeHTML(val) : val
+ );
+ }
+ }
+
+ return tpl;
+ };
+
+ /**
+ * simple Template formatter
+ *
+ * @param {string} tpl
+ * @param {Object} param
+ * @param {boolean} [encode=false]
+ * @return {string}
+ */
+ formatUtil.formatTplSimple = function (tpl, param, encode) {
+ zrUtil.each(param, function (value, key) {
+ tpl = tpl.replace(
+ '{' + key + '}',
+ encode ? encodeHTML(value) : value
+ );
+ });
+ return tpl;
+ };
+
+ /**
+ * @param {string} color
+ * @param {string} [extraCssText]
+ * @return {string}
+ */
+ formatUtil.getTooltipMarker = function (color, extraCssText) {
+ return color
+ ? ''
+ : '';
+ };
+
+ /**
+ * @param {string} str
+ * @return {string}
+ * @inner
+ */
+ var s2d = function (str) {
+ return str < 10 ? ('0' + str) : str;
+ };
+
+ /**
+ * ISO Date format
+ * @param {string} tpl
+ * @param {number} value
+ * @param {boolean} [isUTC=false] Default in local time.
+ * see `module:echarts/scale/Time`
+ * and `module:echarts/util/number#parseDate`.
+ * @inner
+ */
+ formatUtil.formatTime = function (tpl, value, isUTC) {
+ if (tpl === 'week'
+ || tpl === 'month'
+ || tpl === 'quarter'
+ || tpl === 'half-year'
+ || tpl === 'year'
+ ) {
+ tpl = 'MM-dd\nyyyy';
+ }
+
+ var date = numberUtil.parseDate(value);
+ var utc = isUTC ? 'UTC' : '';
+ var y = date['get' + utc + 'FullYear']();
+ var M = date['get' + utc + 'Month']() + 1;
+ var d = date['get' + utc + 'Date']();
+ var h = date['get' + utc + 'Hours']();
+ var m = date['get' + utc + 'Minutes']();
+ var s = date['get' + utc + 'Seconds']();
+
+ tpl = tpl.replace('MM', s2d(M))
+ .toLowerCase()
+ .replace('yyyy', y)
+ .replace('yy', y % 100)
+ .replace('dd', s2d(d))
+ .replace('d', d)
+ .replace('hh', s2d(h))
+ .replace('h', h)
+ .replace('mm', s2d(m))
+ .replace('m', m)
+ .replace('ss', s2d(s))
+ .replace('s', s);
+
+ return tpl;
+ };
+
+ /**
+ * Capital first
+ * @param {string} str
+ * @return {string}
+ */
+ formatUtil.capitalFirst = function (str) {
+ return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
+ };
+
+ formatUtil.truncateText = textContain.truncateText;
+
+ module.exports = formatUtil;
+
+
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 数值处理模块
+ * @module echarts/util/number
+ */
+
+
+
+ var zrUtil = __webpack_require__(4);
+
+ 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.)} val
+ * @param {Array.} domain Domain extent domain[0] can be bigger than domain[1]
+ * @param {Array.} range Range extent range[0] can be bigger than range[1]
+ * @param {boolean} clamp
+ * @return {(number|Array.}
+ */
+ number.linearMap = function (val, domain, range, clamp) {
+ var subDomain = domain[1] - domain[0];
+ var subRange = range[1] - range[0];
+
+ if (subDomain === 0) {
+ return subRange === 0
+ ? range[0]
+ : (range[0] + range[1]) / 2;
+ }
+
+ // Avoid accuracy problem in edge, such as
+ // 146.39 - 62.83 === 83.55999999999999.
+ // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError
+ // It is a little verbose for efficiency considering this method
+ // is a hotspot.
+ if (clamp) {
+ if (subDomain > 0) {
+ if (val <= domain[0]) {
+ return range[0];
+ }
+ else if (val >= domain[1]) {
+ return range[1];
+ }
+ }
+ else {
+ if (val >= domain[0]) {
+ return range[0];
+ }
+ else if (val <= domain[1]) {
+ return range[1];
+ }
+ }
+ }
+ else {
+ if (val === domain[0]) {
+ return range[0];
+ }
+ if (val === domain[1]) {
+ return range[1];
+ }
+ }
+
+ return (val - domain[0]) / subDomain * subRange + range[0];
+ };
+
+ /**
+ * 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;
+ };
+
+ /**
+ * (1) Fix rounding error of float numbers.
+ * (2) Support return string to avoid scientific notation like '3.5e-7'.
+ *
+ * @param {number} x
+ * @param {number} [precision]
+ * @param {boolean} [returnStr]
+ * @return {number|string}
+ */
+ number.round = function (x, precision, returnStr) {
+ if (precision == null) {
+ precision = 10;
+ }
+ // Avoid range error
+ precision = Math.min(Math.max(0, precision), 20);
+ x = (+x).toFixed(precision);
+ return returnStr ? x : +x;
+ };
+
+ number.asc = function (arr) {
+ arr.sort(function (a, b) {
+ return a - b;
+ });
+ return arr;
+ };
+
+ /**
+ * Get precision
+ * @param {number} val
+ */
+ number.getPrecision = function (val) {
+ val = +val;
+ if (isNaN(val)) {
+ return 0;
+ }
+ // 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 {string|number} val
+ * @return {number}
+ */
+ number.getPrecisionSafe = function (val) {
+ var str = val.toString();
+
+ // Consider scientific notation: '3.4e-12' '3.4e+12'
+ var eIndex = str.indexOf('e');
+ if (eIndex > 0) {
+ var precision = +str.slice(eIndex + 1);
+ return precision < 0 ? -precision : 0;
+ }
+ else {
+ var dotIndex = str.indexOf('.');
+ return dotIndex < 0 ? 0 : str.length - 1 - dotIndex;
+ }
+ };
+
+ /**
+ * Minimal dicernible data precisioin according to a single pixel.
+ *
+ * @param {Array.} dataExtent
+ * @param {Array.} 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);
+ // toFixed() digits argument must be between 0 and 20.
+ var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20);
+ return !isFinite(precision) ? 20 : precision;
+ };
+
+ /**
+ * Get a data of given precision, assuring the sum of percentages
+ * in valueList is 1.
+ * The largest remainer method is used.
+ * https://en.wikipedia.org/wiki/Largest_remainder_method
+ *
+ * @param {Array.} valueList a list of all data
+ * @param {number} idx index of the data to be processed in valueList
+ * @param {number} precision integer number showing digits of precision
+ * @return {number} percent ranging from 0 to 100
+ */
+ number.getPercentWithPrecision = function (valueList, idx, precision) {
+ if (!valueList[idx]) {
+ return 0;
+ }
+
+ var sum = zrUtil.reduce(valueList, function (acc, val) {
+ return acc + (isNaN(val) ? 0 : val);
+ }, 0);
+ if (sum === 0) {
+ return 0;
+ }
+
+ var digits = Math.pow(10, precision);
+ var votesPerQuota = zrUtil.map(valueList, function (val) {
+ return (isNaN(val) ? 0 : val) / sum * digits * 100;
+ });
+ var targetSeats = digits * 100;
+
+ var seats = zrUtil.map(votesPerQuota, function (votes) {
+ // Assign automatic seats.
+ return Math.floor(votes);
+ });
+ var currentSum = zrUtil.reduce(seats, function (acc, val) {
+ return acc + val;
+ }, 0);
+
+ var remainder = zrUtil.map(votesPerQuota, function (votes, idx) {
+ return votes - seats[idx];
+ });
+
+ // Has remainding votes.
+ while (currentSum < targetSeats) {
+ // Find next largest remainder.
+ var max = Number.NEGATIVE_INFINITY;
+ var maxId = null;
+ for (var i = 0, len = remainder.length; i < len; ++i) {
+ if (remainder[i] > max) {
+ max = remainder[i];
+ maxId = i;
+ }
+ }
+
+ // Add a vote to max remainder.
+ ++seats[maxId];
+ remainder[maxId] = 0;
+ ++currentSum;
+ }
+
+ return seats[idx] / digits;
+ };
+
+ // 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;
+ };
+
+ var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line
+
+ /**
+ * @return {number} in minutes
+ */
+ number.getTimezoneOffset = function () {
+ return (new Date()).getTimezoneOffset();
+ };
+
+ /**
+ * @param {string|Date|number} value These values can be accepted:
+ * + An instance of Date, represent a time in its own time zone.
+ * + Or string in a subset of ISO 8601, only including:
+ * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',
+ * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123',
+ * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00',
+ * all of which will be treated as local time if time zone is not specified
+ * (see ).
+ * + Or other string format, including (all of which will be treated as loacal time):
+ * '2012', '2012-3-1', '2012/3/1', '2012/03/01',
+ * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'
+ * + a timestamp, which represent a time in UTC.
+ * @return {Date} date
+ */
+ number.parseDate = function (value) {
+ if (value instanceof Date) {
+ return value;
+ }
+ else if (typeof value === 'string') {
+ // Different browsers parse date in different way, so we parse it manually.
+ // Some other issues:
+ // new Date('1970-01-01') is UTC,
+ // new Date('1970/01/01') and new Date('1970-1-01') is local.
+ // See issue #3623
+ var match = TIME_REG.exec(value);
+
+ if (!match) {
+ // return Invalid Date.
+ return new Date(NaN);
+ }
+
+ var timezoneOffset = number.getTimezoneOffset();
+ var timeOffset = !match[8]
+ ? 0
+ : match[8].toUpperCase() === 'Z'
+ ? timezoneOffset
+ : +match[8].slice(0, 3) * 60 + timezoneOffset;
+
+ // match[n] can only be string or undefined.
+ // But take care of '12' + 1 => '121'.
+ return new Date(
+ +match[1],
+ +(match[2] || 1) - 1,
+ +match[3] || 1,
+ +match[4] || 0,
+ +(match[5] || 0) - timeOffset,
+ +match[6] || 0,
+ +match[7] || 0
+ );
+ }
+ else if (value == null) {
+ return new Date(NaN);
+ }
+
+ return new Date(Math.round(value));
+ };
+
+ /**
+ * Quantity of a number. e.g. 0.1, 1, 10, 100
+ *
+ * @param {number} val
+ * @return {number}
+ */
+ number.quantity = function (val) {
+ return Math.pow(10, quantityExponent(val));
+ };
+
+ function quantityExponent(val) {
+ return Math.floor(Math.log(val) / Math.LN10);
+ }
+
+ /**
+ * find a “nice” number approximately equal to x. Round the number if round = true,
+ * take ceiling if round = false. The primary observation is that the “nicest”
+ * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers.
+ *
+ * See "Nice Numbers for Graph Labels" of Graphic Gems.
+ *
+ * @param {number} val Non-negative value.
+ * @param {boolean} round
+ * @return {number}
+ */
+ number.nice = function (val, round) {
+ var exponent = quantityExponent(val);
+ var exp10 = Math.pow(10, exponent);
+ var f = val / exp10; // 1 <= f < 10
+ var nf;
+ if (round) {
+ if (f < 1.5) { nf = 1; }
+ else if (f < 2.5) { nf = 2; }
+ else if (f < 4) { nf = 3; }
+ else if (f < 7) { nf = 5; }
+ else { nf = 10; }
+ }
+ else {
+ if (f < 1) { nf = 1; }
+ else if (f < 2) { nf = 2; }
+ else if (f < 3) { nf = 3; }
+ else if (f < 5) { nf = 5; }
+ else { nf = 10; }
+ }
+ val = nf * exp10;
+
+ // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
+ // 20 is the uppper bound of toFixed.
+ return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
+ };
+
+ /**
+ * Order intervals asc, and split them when overlap.
+ * expect(numberUtil.reformIntervals([
+ * {interval: [18, 62], close: [1, 1]},
+ * {interval: [-Infinity, -70], close: [0, 0]},
+ * {interval: [-70, -26], close: [1, 1]},
+ * {interval: [-26, 18], close: [1, 1]},
+ * {interval: [62, 150], close: [1, 1]},
+ * {interval: [106, 150], close: [1, 1]},
+ * {interval: [150, Infinity], close: [0, 0]}
+ * ])).toEqual([
+ * {interval: [-Infinity, -70], close: [0, 0]},
+ * {interval: [-70, -26], close: [1, 1]},
+ * {interval: [-26, 18], close: [0, 1]},
+ * {interval: [18, 62], close: [0, 1]},
+ * {interval: [62, 150], close: [0, 1]},
+ * {interval: [150, Infinity], close: [0, 0]}
+ * ]);
+ * @param {Array.} list, where `close` mean open or close
+ * of the interval, and Infinity can be used.
+ * @return {Array.} The origin list, which has been reformed.
+ */
+ number.reformIntervals = function (list) {
+ list.sort(function (a, b) {
+ return littleThan(a, b, 0) ? -1 : 1;
+ });
+
+ var curr = -Infinity;
+ var currClose = 1;
+ for (var i = 0; i < list.length;) {
+ var interval = list[i].interval;
+ var close = list[i].close;
+
+ for (var lg = 0; lg < 2; lg++) {
+ if (interval[lg] <= curr) {
+ interval[lg] = curr;
+ close[lg] = !lg ? 1 - currClose : 1;
+ }
+ curr = interval[lg];
+ currClose = close[lg];
+ }
+
+ if (interval[0] === interval[1] && close[0] * close[1] !== 1) {
+ list.splice(i, 1);
+ }
+ else {
+ i++;
+ }
+ }
+
+ return list;
+
+ function littleThan(a, b, lg) {
+ return a.interval[lg] < b.interval[lg]
+ || (
+ a.interval[lg] === b.interval[lg]
+ && (
+ (a.close[lg] - b.close[lg] === (!lg ? 1 : -1))
+ || (!lg && littleThan(a, b, 1))
+ )
+ );
+ }
+ };
+
+ /**
+ * parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ * ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ * subtraction forces infinities to NaN
+ *
+ * @param {*} v
+ * @return {boolean}
+ */
+ number.isNumeric = function (v) {
+ return v - parseFloat(v) >= 0;
+ };
+
+ module.exports = number;
+
+
+/***/ },
+/* 8 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var textWidthCache = {};
+ var textWidthCacheCounter = 0;
+ var TEXT_CACHE_MAX = 5000;
+
+ var util = __webpack_require__(4);
+ var BoundingRect = __webpack_require__(9);
+ var retrieve = util.retrieve;
+
+ 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 lineHeight = textRect.lineHeight;
+ var halfHeight = height / 2 - textHeight / 2 + lineHeight;
+
+ 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 - lineHeight;
+ textAlign = 'center';
+ break;
+ case 'bottom':
+ x += width / 2;
+ y += height + distance + lineHeight;
+ 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 + lineHeight;
+ textAlign = 'center';
+ break;
+ case 'insideBottom':
+ x += width / 2;
+ y += height - textHeight - distance + lineHeight;
+ textAlign = 'center';
+ break;
+ case 'insideTopLeft':
+ x += distance;
+ y += distance + lineHeight;
+ textAlign = 'left';
+ break;
+ case 'insideTopRight':
+ x += width - distance;
+ y += distance + lineHeight;
+ textAlign = 'right';
+ break;
+ case 'insideBottomLeft':
+ x += distance;
+ y += height - textHeight - distance + lineHeight;
+ break;
+ case 'insideBottomRight':
+ x += width - distance;
+ y += height - textHeight - distance + lineHeight;
+ textAlign = 'right';
+ break;
+ }
+
+ return {
+ x: x,
+ y: y,
+ textAlign: textAlign,
+ textBaseline: 'alphabetic'
+ };
+ }
+
+ /**
+ * Show ellipsis if overflow.
+ *
+ * @param {string} text
+ * @param {string} containerWidth
+ * @param {string} textFont
+ * @param {number} [ellipsis='...']
+ * @param {Object} [options]
+ * @param {number} [options.maxIterations=3]
+ * @param {number} [options.minChar=0] If truncate result are less
+ * then minChar, ellipsis will not show, which is
+ * better for user hint in some cases.
+ * @param {number} [options.placeholder=''] When all truncated, use the placeholder.
+ * @return {string}
+ */
+ function truncateText(text, containerWidth, textFont, ellipsis, options) {
+ if (!containerWidth) {
+ return '';
+ }
+
+ options = options || {};
+
+ ellipsis = retrieve(ellipsis, '...');
+ var maxIterations = retrieve(options.maxIterations, 2);
+ var minChar = retrieve(options.minChar, 0);
+ // FIXME
+ // Other languages?
+ var cnCharWidth = getTextWidth('国', textFont);
+ // FIXME
+ // Consider proportional font?
+ var ascCharWidth = getTextWidth('a', textFont);
+ var placeholder = retrieve(options.placeholder, '');
+
+ // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'.
+ // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'.
+ var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap.
+ for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
+ contentWidth -= ascCharWidth;
+ }
+
+ var ellipsisWidth = getTextWidth(ellipsis);
+ if (ellipsisWidth > contentWidth) {
+ ellipsis = '';
+ ellipsisWidth = 0;
+ }
+
+ contentWidth = containerWidth - ellipsisWidth;
+
+ var textLines = (text + '').split('\n');
+
+ for (var i = 0, len = textLines.length; i < len; i++) {
+ var textLine = textLines[i];
+ var lineWidth = getTextWidth(textLine, textFont);
+
+ if (lineWidth <= containerWidth) {
+ continue;
+ }
+
+ for (var j = 0;; j++) {
+ if (lineWidth <= contentWidth || j >= maxIterations) {
+ textLine += ellipsis;
+ break;
+ }
+
+ var subLength = j === 0
+ ? estimateLength(textLine, contentWidth, ascCharWidth, cnCharWidth)
+ : lineWidth > 0
+ ? Math.floor(textLine.length * contentWidth / lineWidth)
+ : 0;
+
+ textLine = textLine.substr(0, subLength);
+ lineWidth = getTextWidth(textLine, textFont);
+ }
+
+ if (textLine === '') {
+ textLine = placeholder;
+ }
+
+ textLines[i] = textLine;
+ }
+
+ return textLines.join('\n');
+ }
+
+ function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
+ var width = 0;
+ var i = 0;
+ for (var len = text.length; i < len && width < contentWidth; i++) {
+ var charCode = text.charCodeAt(i);
+ width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth;
+ }
+ return i;
+ }
+
+ var textContain = {
+
+ getWidth: getTextWidth,
+
+ getBoundingRect: getTextRect,
+
+ adjustTextPositionOnRect: adjustTextPositionOnRect,
+
+ truncateText: truncateText,
+
+ measureText: function (text, textFont) {
+ var ctx = util.getContext();
+ ctx.font = textFont || '12px sans-serif';
+ return ctx.measureText(text);
+ }
+ };
+
+ module.exports = textContain;
+
+
+/***/ },
+/* 9 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * @module echarts/core/BoundingRect
+ */
+
+
+ var vec2 = __webpack_require__(10);
+ var matrix = __webpack_require__(11);
+
+ var v2ApplyTransform = vec2.applyTransform;
+ var mathMin = Math.min;
+ var mathMax = Math.max;
+ /**
+ * @alias module:echarts/core/BoundingRect
+ */
+ function BoundingRect(x, y, width, height) {
+
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+
+ /**
+ * @type {number}
+ */
+ this.x = x;
+ /**
+ * @type {number}
+ */
+ this.y = y;
+ /**
+ * @type {number}
+ */
+ this.width = width;
+ /**
+ * @type {number}
+ */
+ this.height = height;
+ }
+
+ BoundingRect.prototype = {
+
+ constructor: BoundingRect,
+
+ /**
+ * @param {module:echarts/core/BoundingRect} other
+ */
+ union: function (other) {
+ var x = mathMin(other.x, this.x);
+ var y = mathMin(other.y, this.y);
+
+ this.width = mathMax(
+ other.x + other.width,
+ this.x + this.width
+ ) - x;
+ this.height = mathMax(
+ other.y + other.height,
+ this.y + this.height
+ ) - y;
+ this.x = x;
+ this.y = y;
+ },
+
+ /**
+ * @param {Array.} m
+ * @methods
+ */
+ applyTransform: (function () {
+ var lt = [];
+ var rb = [];
+ var lb = [];
+ var rt = [];
+ return function (m) {
+ // In case usage like this
+ // el.getBoundingRect().applyTransform(el.transform)
+ // And element has no transform
+ if (!m) {
+ return;
+ }
+ lt[0] = lb[0] = this.x;
+ lt[1] = rt[1] = this.y;
+ rb[0] = rt[0] = this.x + this.width;
+ rb[1] = lb[1] = this.y + this.height;
+
+ v2ApplyTransform(lt, lt, m);
+ v2ApplyTransform(rb, rb, m);
+ v2ApplyTransform(lb, lb, m);
+ v2ApplyTransform(rt, rt, m);
+
+ this.x = mathMin(lt[0], rb[0], lb[0], rt[0]);
+ this.y = mathMin(lt[1], rb[1], lb[1], rt[1]);
+ var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]);
+ var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]);
+ this.width = maxX - this.x;
+ this.height = maxY - this.y;
+ };
+ })(),
+
+ /**
+ * Calculate matrix of transforming from self to target rect
+ * @param {module:zrender/core/BoundingRect} b
+ * @return {Array.}
+ */
+ 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) {
+ if (!b) {
+ return false;
+ }
+
+ if (!(b instanceof BoundingRect)) {
+ // Normalize negative width/height.
+ b = BoundingRect.create(b);
+ }
+
+ var a = this;
+ var ax0 = a.x;
+ var ax1 = a.x + a.width;
+ var ay0 = a.y;
+ var ay1 = a.y + a.height;
+
+ var bx0 = b.x;
+ var bx1 = b.x + b.width;
+ var by0 = b.y;
+ var by1 = b.y + b.height;
+
+ 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;
+ },
+
+ plain: function () {
+ return {
+ x: this.x,
+ y: this.y,
+ width: this.width,
+ height: this.height
+ };
+ }
+ };
+
+ /**
+ * @param {Object|module:zrender/core/BoundingRect} rect
+ * @param {number} rect.x
+ * @param {number} rect.y
+ * @param {number} rect.width
+ * @param {number} rect.height
+ * @return {module:zrender/core/BoundingRect}
+ */
+ BoundingRect.create = function (rect) {
+ return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
+ };
+
+ module.exports = BoundingRect;
+
+
+/***/ },
+/* 10 */
+/***/ function(module, exports) {
+
+
+ var ArrayCtor = typeof Float32Array === 'undefined'
+ ? Array
+ : Float32Array;
+
+ /**
+ * @typedef {Float32Array|Array.} 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);
+ if (x == null) {
+ x = 0;
+ }
+ if (y == null) {
+ y = 0;
+ }
+ out[0] = x;
+ out[1] = y;
+ 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;
+
+ module.exports = vector;
+
+
+
+/***/ },
+/* 11 */
+/***/ function(module, exports) {
+
+
+ var ArrayCtor = typeof Float32Array === 'undefined'
+ ? Array
+ : Float32Array;
+ /**
+ * 3x2矩阵操作类
+ * @exports zrender/tool/matrix
+ */
+ var matrix = {
+ /**
+ * 创建一个单位矩阵
+ * @return {Float32Array|Array.}
+ */
+ create : function() {
+ var out = new ArrayCtor(6);
+ matrix.identity(out);
+
+ return out;
+ },
+ /**
+ * 设置矩阵为单位矩阵
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} m1
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} a
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} a
+ * @param {Float32Array|Array.} 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.} out
+ * @param {Float32Array|Array.} 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;
+ }
+ };
+
+ module.exports = matrix;
+
+
+
+/***/ },
+/* 12 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @module echarts/model/Model
+ */
+
+
+ var zrUtil = __webpack_require__(4);
+ var clazzUtil = __webpack_require__(13);
+ var env = __webpack_require__(2);
+
+ /**
+ * @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;
+
+ /**
+ * @type {module:echarts/model/Global}
+ * @readOnly
+ */
+ this.ecModel = ecModel;
+
+ /**
+ * @type {Object}
+ * @protected
+ */
+ this.option = option;
+
+ // Simple optimization
+ // if (this.init) {
+ // if (arguments.length <= 4) {
+ // this.init(option, parentModel, ecModel, extraOpt);
+ // }
+ // else {
+ // this.init.apply(this, arguments);
+ // }
+ // }
+ }
+
+ Model.prototype = {
+
+ constructor: Model,
+
+ /**
+ * Model 的初始化函数
+ * @param {Object} option
+ */
+ init: null,
+
+ /**
+ * 从新的 Option merge
+ */
+ mergeOption: function (option) {
+ zrUtil.merge(this.option, option, true);
+ },
+
+ /**
+ * @param {string|Array.} path
+ * @param {boolean} [ignoreParent=false]
+ * @return {*}
+ */
+ get: function (path, ignoreParent) {
+ if (path == null) {
+ return this.option;
+ }
+
+ return doGet(
+ this.option,
+ this.parsePath(path),
+ !ignoreParent && getParent(this, path)
+ );
+ },
+
+ /**
+ * @param {string} key
+ * @param {boolean} [ignoreParent=false]
+ * @return {*}
+ */
+ getShallow: function (key, ignoreParent) {
+ var option = this.option;
+
+ var val = option == null ? option : option[key];
+ var parentModel = !ignoreParent && getParent(this, key);
+ if (val == null && parentModel) {
+ val = parentModel.getShallow(key);
+ }
+ return val;
+ },
+
+ /**
+ * @param {string|Array.} [path]
+ * @param {module:echarts/model/Model} [parentModel]
+ * @return {module:echarts/model/Model}
+ */
+ getModel: function (path, parentModel) {
+ var obj = path == null
+ ? this.option
+ : doGet(this.option, path = this.parsePath(path));
+
+ var thisParentModel;
+ parentModel = parentModel || (
+ (thisParentModel = getParent(this, path))
+ && thisParentModel.getModel(path)
+ );
+
+ return new Model(obj, parentModel, this.ecModel);
+ },
+
+ /**
+ * 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);
+ },
+
+ // If path is null/undefined, return null/undefined.
+ parsePath: function(path) {
+ if (typeof path === 'string') {
+ path = path.split('.');
+ }
+ return path;
+ },
+
+ /**
+ * @param {Function} getParentMethod
+ * param {Array.|string} path
+ * return {module:echarts/model/Model}
+ */
+ customizeGetParent: function (getParentMethod) {
+ clazzUtil.set(this, 'getParent', getParentMethod);
+ },
+
+ isAnimationEnabled: function () {
+ if (!env.node) {
+ if (this.option.animation != null) {
+ return !!this.option.animation;
+ }
+ else if (this.parentModel) {
+ return this.parentModel.isAnimationEnabled();
+ }
+ }
+ }
+ };
+
+ function doGet(obj, pathArr, parentModel) {
+ for (var i = 0; i < pathArr.length; i++) {
+ // Ignore empty
+ if (!pathArr[i]) {
+ continue;
+ }
+ // obj could be number/string/... (like 0)
+ obj = (obj && typeof obj === 'object') ? obj[pathArr[i]] : null;
+ if (obj == null) {
+ break;
+ }
+ }
+ if (obj == null && parentModel) {
+ obj = parentModel.get(pathArr);
+ }
+ return obj;
+ }
+
+ // `path` can be null/undefined
+ function getParent(model, path) {
+ var getParentMethod = clazzUtil.get(model, 'getParent');
+ return getParentMethod ? getParentMethod.call(model, path) : model.parentModel;
+ }
+
+ // Enable Model.extend.
+ clazzUtil.enableClassExtend(Model);
+
+ var mixin = zrUtil.mixin;
+ mixin(Model, __webpack_require__(14));
+ mixin(Model, __webpack_require__(16));
+ mixin(Model, __webpack_require__(17));
+ mixin(Model, __webpack_require__(68));
+
+ module.exports = Model;
+
+
+/***/ },
+/* 13 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var clazz = {};
+
+ var TYPE_DELIMITER = '.';
+ var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';
+ var MEMBER_PRIFIX = '\0ec_\0';
+
+ /**
+ * Hide private class member.
+ * The same behavior as `host[name] = value;` (can be right-value)
+ * @public
+ */
+ clazz.set = function (host, name, value) {
+ return (host[MEMBER_PRIFIX + name] = value);
+ };
+
+ /**
+ * Hide private class member.
+ * The same behavior as `host[name];`
+ * @public
+ */
+ clazz.get = function (host, name) {
+ return host[MEMBER_PRIFIX + name];
+ };
+
+ /**
+ * For hidden private class member.
+ * The same behavior as `host.hasOwnProperty(name);`
+ * @public
+ */
+ clazz.hasOwn = function (host, name) {
+ return host.hasOwnProperty(MEMBER_PRIFIX + name);
+ };
+
+ /**
+ * Notice, parseClassType('') should returns {main: '', sub: ''}
+ * @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
+ */
+ function checkClassType(componentType) {
+ zrUtil.assert(
+ /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType),
+ 'componentType "' + componentType + '" illegal'
+ );
+ }
+
+ /**
+ * @public
+ */
+ clazz.enableClassExtend = function (RootClass, mandatoryMethods) {
+
+ RootClass.$constructor = RootClass;
+ RootClass.extend = function (proto) {
+
+ if (true) {
+ zrUtil.each(mandatoryMethods, function (method) {
+ if (!proto[method]) {
+ console.warn(
+ 'Method `' + method + '` should be implemented'
+ + (proto.type ? ' in ' + proto.type : '') + '.'
+ );
+ }
+ });
+ }
+
+ var superClass = this;
+ var ExtendedClass = function () {
+ if (!proto.$constructor) {
+ superClass.apply(this, arguments);
+ }
+ else {
+ proto.$constructor.apply(this, arguments);
+ }
+ };
+
+ zrUtil.extend(ExtendedClass.prototype, proto);
+
+ ExtendedClass.extend = this.extend;
+ ExtendedClass.superCall = superCall;
+ ExtendedClass.superApply = superApply;
+ zrUtil.inherits(ExtendedClass, this);
+ ExtendedClass.superClass = superClass;
+
+ return ExtendedClass;
+ };
+ };
+
+ // superCall should have class info, which can not be fetch from 'this'.
+ // Consider this case:
+ // class A has method f,
+ // class B inherits class A, overrides method f, f call superApply('f'),
+ // class C inherits class B, do not overrides method f,
+ // then when method of class C is called, dead loop occured.
+ function superCall(context, methodName) {
+ var args = zrUtil.slice(arguments, 2);
+ return this.superClass.prototype[methodName].apply(context, args);
+ }
+
+ function superApply(context, methodName, args) {
+ return this.superClass.prototype[methodName].apply(context, args);
+ }
+
+ /**
+ * @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., when componentType is 'xxx.yy'
+ * @type {Object}
+ */
+ var storage = {};
+
+ entity.registerClass = function (Clazz, componentType) {
+ if (componentType) {
+ checkClassType(componentType);
+ componentType = parseClassType(componentType);
+
+ if (!componentType.sub) {
+ if (true) {
+ if (storage[componentType.main]) {
+ console.warn(componentType.main + ' exists.');
+ }
+ }
+ storage[componentType.main] = Clazz;
+ }
+ else if (componentType.sub !== IS_CONTAINER) {
+ var container = makeContainer(componentType);
+ container[componentType.sub] = Clazz;
+ }
+ }
+ return Clazz;
+ };
+
+ entity.getClass = function (componentMainType, subType, throwWhenNotFound) {
+ var Clazz = storage[componentMainType];
+
+ if (Clazz && Clazz[IS_CONTAINER]) {
+ Clazz = subType ? Clazz[subType] : null;
+ }
+
+ if (throwWhenNotFound && !Clazz) {
+ throw new Error(
+ !subType
+ ? componentMainType + '.' + 'type should be specified.'
+ : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.'
+ );
+ }
+
+ return Clazz;
+ };
+
+ entity.getClassesByMainType = function (componentType) {
+ componentType = parseClassType(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.} 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.} properties
+ */
+ clazz.setReadOnly = function (obj, properties) {
+ // FIXME It seems broken in IE8 simulation of IE11
+ // 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]);
+ // });
+ };
+
+ module.exports = clazz;
+
+
+/***/ },
+/* 14 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+ var getLineStyle = __webpack_require__(15)(
+ [
+ ['lineWidth', 'width'],
+ ['stroke', 'color'],
+ ['opacity'],
+ ['shadowBlur'],
+ ['shadowOffsetX'],
+ ['shadowOffsetY'],
+ ['shadowColor']
+ ]
+ );
+ module.exports = {
+ getLineStyle: function (excludes) {
+ var style = getLineStyle.call(this, excludes);
+ var lineDash = this.getLineDash(style.lineWidth);
+ lineDash && (style.lineDash = lineDash);
+ return style;
+ },
+
+ getLineDash: function (lineWidth) {
+ if (lineWidth == null) {
+ lineWidth = 1;
+ }
+ var lineType = this.get('type');
+ var dotSize = Math.max(lineWidth, 2);
+ var dashSize = lineWidth * 4;
+ return (lineType === 'solid' || lineType == null) ? null
+ : (lineType === 'dashed' ? [dashSize, dashSize] : [dotSize, dotSize]);
+ }
+ };
+
+
+/***/ },
+/* 15 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // TODO Parse shadow style
+ // TODO Only shallow path support
+
+ var zrUtil = __webpack_require__(4);
+
+ module.exports = function (properties) {
+ // Normalize
+ for (var i = 0; i < properties.length; i++) {
+ if (!properties[i][1]) {
+ properties[i][1] = properties[i][0];
+ }
+ }
+ return function (excludes, includes) {
+ var style = {};
+ for (var i = 0; i < properties.length; i++) {
+ var propName = properties[i][1];
+ if ((excludes && zrUtil.indexOf(excludes, propName) >= 0)
+ || (includes && zrUtil.indexOf(includes, propName) < 0)
+ ) {
+ continue;
+ }
+ var val = this.getShallow(propName);
+ if (val != null) {
+ style[properties[i][0]] = val;
+ }
+ }
+ return style;
+ };
+ };
+
+
+/***/ },
+/* 16 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+ module.exports = {
+ getAreaStyle: __webpack_require__(15)(
+ [
+ ['fill', 'color'],
+ ['shadowBlur'],
+ ['shadowOffsetX'],
+ ['shadowOffsetY'],
+ ['opacity'],
+ ['shadowColor']
+ ]
+ )
+ };
+
+
+/***/ },
+/* 17 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var textContain = __webpack_require__(8);
+ var graphicUtil = __webpack_require__(18);
+
+ module.exports = {
+ /**
+ * 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 () {
+ return graphicUtil.getFont({
+ fontStyle: this.getShallow('fontStyle'),
+ fontWeight: this.getShallow('fontWeight'),
+ fontSize: this.getShallow('fontSize'),
+ fontFamily: this.getShallow('fontFamily')
+ }, this.ecModel);
+ },
+
+ getTextRect: function (text) {
+ return textContain.getBoundingRect(
+ text,
+ this.getFont(),
+ this.getShallow('align'),
+ this.getShallow('baseline')
+ );
+ },
+
+ truncateText: function (text, containerWidth, ellipsis, options) {
+ return textContain.truncateText(
+ text, containerWidth, this.getFont(), ellipsis, options
+ );
+ }
+ };
+
+
+/***/ },
+/* 18 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var pathTool = __webpack_require__(19);
+ var Path = __webpack_require__(20);
+ var colorTool = __webpack_require__(31);
+ var matrix = __webpack_require__(11);
+ var vector = __webpack_require__(10);
+ var Transformable = __webpack_require__(26);
+ var BoundingRect = __webpack_require__(9);
+
+ var round = Math.round;
+ var mathMax = Math.max;
+ var mathMin = Math.min;
+
+ var graphic = {};
+
+ graphic.Group = __webpack_require__(48);
+
+ graphic.Image = __webpack_require__(49);
+
+ graphic.Text = __webpack_require__(50);
+
+ graphic.Circle = __webpack_require__(51);
+
+ graphic.Sector = __webpack_require__(52);
+
+ graphic.Ring = __webpack_require__(53);
+
+ graphic.Polygon = __webpack_require__(54);
+
+ graphic.Polyline = __webpack_require__(58);
+
+ graphic.Rect = __webpack_require__(59);
+
+ graphic.Line = __webpack_require__(61);
+
+ graphic.BezierCurve = __webpack_require__(62);
+
+ graphic.Arc = __webpack_require__(63);
+
+ graphic.CompoundPath = __webpack_require__(64);
+
+ graphic.LinearGradient = __webpack_require__(65);
+
+ graphic.RadialGradient = __webpack_require__(67);
+
+ graphic.BoundingRect = BoundingRect;
+
+ /**
+ * Extend shape with parameters
+ */
+ graphic.extendShape = function (opts) {
+ return Path.extend(opts);
+ };
+
+ /**
+ * Extend path
+ */
+ graphic.extendPath = function (pathData, opts) {
+ return pathTool.extendFromString(pathData, opts);
+ };
+
+ /**
+ * Create a path element from path data string
+ * @param {string} pathData
+ * @param {Object} opts
+ * @param {module:zrender/core/BoundingRect} rect
+ * @param {string} [layout=cover] 'center' or 'cover'
+ */
+ graphic.makePath = function (pathData, opts, rect, layout) {
+ var path = pathTool.createFromString(pathData, opts);
+ var boundingRect = path.getBoundingRect();
+ if (rect) {
+ var aspect = boundingRect.width / boundingRect.height;
+
+ if (layout === 'center') {
+ // Set rect to center, keep width / height ratio.
+ var width = rect.height * aspect;
+ var height;
+ if (width <= rect.width) {
+ height = rect.height;
+ }
+ else {
+ width = rect.width;
+ height = width / aspect;
+ }
+ var cx = rect.x + rect.width / 2;
+ var cy = rect.y + rect.height / 2;
+
+ rect.x = cx - width / 2;
+ rect.y = cy - height / 2;
+ rect.width = width;
+ rect.height = height;
+ }
+
+ graphic.resizePath(path, rect);
+ }
+ return path;
+ };
+
+ graphic.mergePath = pathTool.mergePath,
+
+ /**
+ * Resize a path to fit the rect
+ * @param {module:zrender/graphic/Path} path
+ * @param {Object} rect
+ */
+ graphic.resizePath = function (path, rect) {
+ if (!path.applyTransform) {
+ return;
+ }
+
+ var pathRect = path.getBoundingRect();
+
+ var m = pathRect.calculateTransform(rect);
+
+ path.applyTransform(m);
+ };
+
+ /**
+ * Sub pixel optimize line for canvas
+ *
+ * @param {Object} param
+ * @param {Object} [param.shape]
+ * @param {number} [param.shape.x1]
+ * @param {number} [param.shape.y1]
+ * @param {number} [param.shape.x2]
+ * @param {number} [param.shape.y2]
+ * @param {Object} [param.style]
+ * @param {number} [param.style.lineWidth]
+ * @return {Object} Modified param
+ */
+ graphic.subPixelOptimizeLine = function (param) {
+ var subPixelOptimize = graphic.subPixelOptimize;
+ var shape = param.shape;
+ var lineWidth = param.style.lineWidth;
+
+ if (round(shape.x1 * 2) === round(shape.x2 * 2)) {
+ shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true);
+ }
+ if (round(shape.y1 * 2) === round(shape.y2 * 2)) {
+ shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true);
+ }
+ return param;
+ };
+
+ /**
+ * Sub pixel optimize rect for canvas
+ *
+ * @param {Object} param
+ * @param {Object} [param.shape]
+ * @param {number} [param.shape.x]
+ * @param {number} [param.shape.y]
+ * @param {number} [param.shape.width]
+ * @param {number} [param.shape.height]
+ * @param {Object} [param.style]
+ * @param {number} [param.style.lineWidth]
+ * @return {Object} Modified param
+ */
+ graphic.subPixelOptimizeRect = function (param) {
+ var subPixelOptimize = graphic.subPixelOptimize;
+ var shape = param.shape;
+ var lineWidth = param.style.lineWidth;
+ var originX = shape.x;
+ var originY = shape.y;
+ var originWidth = shape.width;
+ var originHeight = shape.height;
+ shape.x = subPixelOptimize(shape.x, lineWidth, true);
+ shape.y = subPixelOptimize(shape.y, lineWidth, true);
+ shape.width = Math.max(
+ subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x,
+ originWidth === 0 ? 0 : 1
+ );
+ shape.height = Math.max(
+ subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y,
+ originHeight === 0 ? 0 : 1
+ );
+ return param;
+ };
+
+ /**
+ * Sub pixel optimize for canvas
+ *
+ * @param {number} position Coordinate, such as x, y
+ * @param {number} lineWidth Should be nonnegative integer.
+ * @param {boolean=} positiveOrNegative Default false (negative).
+ * @return {number} Optimized position.
+ */
+ graphic.subPixelOptimize = function (position, lineWidth, positiveOrNegative) {
+ // Assure that (position + lineWidth / 2) is near integer edge,
+ // otherwise line will be fuzzy in canvas.
+ var doubledPosition = round(position * 2);
+ return (doubledPosition + round(lineWidth)) % 2 === 0
+ ? doubledPosition / 2
+ : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
+ };
+
+ function hasFillOrStroke(fillOrStroke) {
+ return fillOrStroke != null && fillOrStroke != 'none';
+ }
+
+ function liftColor(color) {
+ return typeof color === 'string' ? colorTool.lift(color, -0.1) : color;
+ }
+
+ /**
+ * @private
+ */
+ function cacheElementStl(el) {
+ if (el.__hoverStlDirty) {
+ var stroke = el.style.stroke;
+ var fill = el.style.fill;
+
+ // Create hoverStyle on mouseover
+ var hoverStyle = el.__hoverStl;
+ hoverStyle.fill = hoverStyle.fill
+ || (hasFillOrStroke(fill) ? liftColor(fill) : null);
+ hoverStyle.stroke = hoverStyle.stroke
+ || (hasFillOrStroke(stroke) ? liftColor(stroke) : null);
+
+ var normalStyle = {};
+ for (var name in hoverStyle) {
+ if (hoverStyle.hasOwnProperty(name)) {
+ normalStyle[name] = el.style[name];
+ }
+ }
+
+ el.__normalStl = normalStyle;
+
+ el.__hoverStlDirty = false;
+ }
+ }
+
+ /**
+ * @private
+ */
+ function doSingleEnterHover(el) {
+ if (el.__isHover) {
+ return;
+ }
+
+ cacheElementStl(el);
+
+ if (el.useHoverLayer) {
+ el.__zr && el.__zr.addHover(el, el.__hoverStl);
+ }
+ else {
+ el.setStyle(el.__hoverStl);
+ el.z2 += 1;
+ }
+
+ el.__isHover = true;
+ }
+
+ /**
+ * @inner
+ */
+ function doSingleLeaveHover(el) {
+ if (!el.__isHover) {
+ return;
+ }
+
+ var normalStl = el.__normalStl;
+ if (el.useHoverLayer) {
+ el.__zr && el.__zr.removeHover(el);
+ }
+ else {
+ normalStl && el.setStyle(normalStl);
+ el.z2 -= 1;
+ }
+
+ el.__isHover = false;
+ }
+
+ /**
+ * @inner
+ */
+ function doEnterHover(el) {
+ el.type === 'group'
+ ? el.traverse(function (child) {
+ if (child.type !== 'group') {
+ doSingleEnterHover(child);
+ }
+ })
+ : doSingleEnterHover(el);
+ }
+
+ function doLeaveHover(el) {
+ el.type === 'group'
+ ? el.traverse(function (child) {
+ if (child.type !== 'group') {
+ doSingleLeaveHover(child);
+ }
+ })
+ : doSingleLeaveHover(el);
+ }
+
+ /**
+ * @inner
+ */
+ function setElementHoverStl(el, hoverStl) {
+ // If element has sepcified hoverStyle, then use it instead of given hoverStyle
+ // Often used when item group has a label element and it's hoverStyle is different
+ el.__hoverStl = el.hoverStyle || hoverStl || {};
+ el.__hoverStlDirty = true;
+
+ if (el.__isHover) {
+ cacheElementStl(el);
+ }
+ }
+
+ /**
+ * @inner
+ */
+ function onElementMouseOver(e) {
+ if (this.__hoverSilentOnTouch && e.zrByTouch) {
+ return;
+ }
+
+ // Only if element is not in emphasis status
+ !this.__isEmphasis && doEnterHover(this);
+ }
+
+ /**
+ * @inner
+ */
+ function onElementMouseOut(e) {
+ if (this.__hoverSilentOnTouch && e.zrByTouch) {
+ return;
+ }
+
+ // Only if element is not in emphasis status
+ !this.__isEmphasis && doLeaveHover(this);
+ }
+
+ /**
+ * @inner
+ */
+ function enterEmphasis() {
+ this.__isEmphasis = true;
+ doEnterHover(this);
+ }
+
+ /**
+ * @inner
+ */
+ function leaveEmphasis() {
+ this.__isEmphasis = false;
+ doLeaveHover(this);
+ }
+
+ /**
+ * Set hover style of element.
+ * This method can be called repeatly without side-effects.
+ * @param {module:zrender/Element} el
+ * @param {Object} [hoverStyle]
+ * @param {Object} [opt]
+ * @param {boolean} [opt.hoverSilentOnTouch=false]
+ * In touch device, mouseover event will be trigger on touchstart event
+ * (see module:zrender/dom/HandlerProxy). By this mechanism, we can
+ * conviniently use hoverStyle when tap on touch screen without additional
+ * code for compatibility.
+ * But if the chart/component has select feature, which usually also use
+ * hoverStyle, there might be conflict between 'select-highlight' and
+ * 'hover-highlight' especially when roam is enabled (see geo for example).
+ * In this case, hoverSilentOnTouch should be used to disable hover-highlight
+ * on touch device.
+ */
+ graphic.setHoverStyle = function (el, hoverStyle, opt) {
+ el.__hoverSilentOnTouch = opt && opt.hoverSilentOnTouch;
+
+ el.type === 'group'
+ ? el.traverse(function (child) {
+ if (child.type !== 'group') {
+ setElementHoverStl(child, hoverStyle);
+ }
+ })
+ : setElementHoverStl(el, hoverStyle);
+
+ // Duplicated function will be auto-ignored, see Eventful.js.
+ el.on('mouseover', onElementMouseOver)
+ .on('mouseout', onElementMouseOut);
+
+ // Emphasis, normal can be triggered manually
+ el.on('emphasis', enterEmphasis)
+ .on('normal', leaveEmphasis);
+ };
+
+ /**
+ * Set text option in the style
+ * @param {Object} textStyle
+ * @param {module:echarts/model/Model} labelModel
+ * @param {string} color
+ */
+ graphic.setText = function (textStyle, labelModel, color) {
+ var labelPosition = labelModel.getShallow('position') || 'inside';
+ var labelOffset = labelModel.getShallow('offset');
+ var labelColor = labelPosition.indexOf('inside') >= 0 ? 'white' : color;
+ var textStyleModel = labelModel.getModel('textStyle');
+ zrUtil.extend(textStyle, {
+ textDistance: labelModel.getShallow('distance') || 5,
+ textFont: textStyleModel.getFont(),
+ textPosition: labelPosition,
+ textOffset: labelOffset,
+ textFill: textStyleModel.getTextColor() || labelColor
+ });
+ };
+
+ graphic.getFont = function (opt, ecModel) {
+ var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
+ return [
+ // FIXME in node-canvas fontWeight is before fontStyle
+ opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '',
+ opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '',
+ (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px',
+ opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'
+ ].join(' ');
+ };
+
+ function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) {
+ if (typeof dataIndex === 'function') {
+ cb = dataIndex;
+ dataIndex = null;
+ }
+ // Do not check 'animation' property directly here. Consider this case:
+ // animation model is an `itemModel`, whose does not have `isAnimationEnabled`
+ // but its parent model (`seriesModel`) does.
+ var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();
+
+ if (animationEnabled) {
+ var postfix = isUpdate ? 'Update' : '';
+ var duration = animatableModel.getShallow('animationDuration' + postfix);
+ var animationEasing = animatableModel.getShallow('animationEasing' + postfix);
+ var animationDelay = animatableModel.getShallow('animationDelay' + postfix);
+ if (typeof animationDelay === 'function') {
+ animationDelay = animationDelay(
+ dataIndex,
+ animatableModel.getAnimationDelayParams
+ ? animatableModel.getAnimationDelayParams(el, dataIndex)
+ : null
+ );
+ }
+ if (typeof duration === 'function') {
+ duration = duration(dataIndex);
+ }
+
+ duration > 0
+ ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb)
+ : (el.stopAnimation(), el.attr(props), cb && cb());
+ }
+ else {
+ el.stopAnimation();
+ el.attr(props);
+ cb && cb();
+ }
+ }
+
+ /**
+ * Update graphic element properties with or without animation according to the configuration in series
+ * @param {module:zrender/Element} el
+ * @param {Object} props
+ * @param {module:echarts/model/Model} [animatableModel]
+ * @param {number} [dataIndex]
+ * @param {Function} [cb]
+ * @example
+ * graphic.updateProps(el, {
+ * position: [100, 100]
+ * }, seriesModel, dataIndex, function () { console.log('Animation done!'); });
+ * // Or
+ * graphic.updateProps(el, {
+ * position: [100, 100]
+ * }, seriesModel, function () { console.log('Animation done!'); });
+ */
+ graphic.updateProps = function (el, props, animatableModel, dataIndex, cb) {
+ animateOrSetProps(true, el, props, animatableModel, dataIndex, cb);
+ };
+
+ /**
+ * Init graphic element properties with or without animation according to the configuration in series
+ * @param {module:zrender/Element} el
+ * @param {Object} props
+ * @param {module:echarts/model/Model} [animatableModel]
+ * @param {number} [dataIndex]
+ * @param {Function} cb
+ */
+ graphic.initProps = function (el, props, animatableModel, dataIndex, cb) {
+ animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);
+ };
+
+ /**
+ * Get transform matrix of target (param target),
+ * in coordinate of its ancestor (param ancestor)
+ *
+ * @param {module:zrender/mixin/Transformable} target
+ * @param {module:zrender/mixin/Transformable} [ancestor]
+ */
+ graphic.getTransform = function (target, ancestor) {
+ var mat = matrix.identity([]);
+
+ while (target && target !== ancestor) {
+ matrix.mul(mat, target.getLocalTransform(), mat);
+ target = target.parent;
+ }
+
+ return mat;
+ };
+
+ /**
+ * Apply transform to an vertex.
+ * @param {Array.} target [x, y]
+ * @param {Array.|TypedArray.|Object} transform Can be:
+ * + Transform matrix: like [1, 0, 0, 1, 0, 0]
+ * + {position, rotation, scale}, the same as `zrender/Transformable`.
+ * @param {boolean=} invert Whether use invert matrix.
+ * @return {Array.} [x, y]
+ */
+ graphic.applyTransform = function (target, transform, invert) {
+ if (transform && !zrUtil.isArrayLike(transform)) {
+ transform = Transformable.getLocalTransform(transform);
+ }
+
+ if (invert) {
+ transform = matrix.invert([], transform);
+ }
+ return vector.applyTransform([], target, transform);
+ };
+
+ /**
+ * @param {string} direction 'left' 'right' 'top' 'bottom'
+ * @param {Array.} transform Transform matrix: like [1, 0, 0, 1, 0, 0]
+ * @param {boolean=} invert Whether use invert matrix.
+ * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom'
+ */
+ graphic.transformDirection = function (direction, transform, invert) {
+
+ // Pick a base, ensure that transform result will not be (0, 0).
+ var hBase = (transform[4] === 0 || transform[5] === 0 || transform[0] === 0)
+ ? 1 : Math.abs(2 * transform[4] / transform[0]);
+ var vBase = (transform[4] === 0 || transform[5] === 0 || transform[2] === 0)
+ ? 1 : Math.abs(2 * transform[4] / transform[2]);
+
+ var vertex = [
+ direction === 'left' ? -hBase : direction === 'right' ? hBase : 0,
+ direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0
+ ];
+
+ vertex = graphic.applyTransform(vertex, transform, invert);
+
+ return Math.abs(vertex[0]) > Math.abs(vertex[1])
+ ? (vertex[0] > 0 ? 'right' : 'left')
+ : (vertex[1] > 0 ? 'bottom' : 'top');
+ };
+
+ /**
+ * Apply group transition animation from g1 to g2.
+ * If no animatableModel, no animation.
+ */
+ graphic.groupTransition = function (g1, g2, animatableModel, cb) {
+ if (!g1 || !g2) {
+ return;
+ }
+
+ function getElMap(g) {
+ var elMap = {};
+ g.traverse(function (el) {
+ if (!el.isGroup && el.anid) {
+ elMap[el.anid] = el;
+ }
+ });
+ return elMap;
+ }
+ function getAnimatableProps(el) {
+ var obj = {
+ position: vector.clone(el.position),
+ rotation: el.rotation
+ };
+ if (el.shape) {
+ obj.shape = zrUtil.extend({}, el.shape);
+ }
+ return obj;
+ }
+ var elMap1 = getElMap(g1);
+
+ g2.traverse(function (el) {
+ if (!el.isGroup && el.anid) {
+ var oldEl = elMap1[el.anid];
+ if (oldEl) {
+ var newProp = getAnimatableProps(el);
+ el.attr(getAnimatableProps(oldEl));
+ graphic.updateProps(el, newProp, animatableModel, el.dataIndex);
+ }
+ // else {
+ // if (el.previousProps) {
+ // graphic.updateProps
+ // }
+ // }
+ }
+ });
+ };
+
+ /**
+ * @param {Array.>} points Like: [[23, 44], [53, 66], ...]
+ * @param {Object} rect {x, y, width, height}
+ * @return {Array.>} A new clipped points.
+ */
+ graphic.clipPointsByRect = function (points, rect) {
+ return zrUtil.map(points, function (point) {
+ var x = point[0];
+ x = mathMax(x, rect.x);
+ x = mathMin(x, rect.x + rect.width);
+ var y = point[1];
+ y = mathMax(y, rect.y);
+ y = mathMin(y, rect.y + rect.height);
+ return [x, y];
+ });
+ };
+
+ /**
+ * @param {Object} targetRect {x, y, width, height}
+ * @param {Object} rect {x, y, width, height}
+ * @return {Object} A new clipped rect. If rect size are negative, return undefined.
+ */
+ graphic.clipRectByRect = function (targetRect, rect) {
+ var x = mathMax(targetRect.x, rect.x);
+ var x2 = mathMin(targetRect.x + targetRect.width, rect.x + rect.width);
+ var y = mathMax(targetRect.y, rect.y);
+ var y2 = mathMin(targetRect.y + targetRect.height, rect.y + rect.height);
+
+ if (x2 >= x && y2 >= y) {
+ return {
+ x: x,
+ y: y,
+ width: x2 - x,
+ height: y2 - y
+ };
+ }
+ };
+
+ module.exports = graphic;
+
+
+
+/***/ },
+/* 19 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var Path = __webpack_require__(20);
+ var PathProxy = __webpack_require__(36);
+ var transformPath = __webpack_require__(47);
+
+ // command chars
+ var cc = [
+ 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',
+ 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'
+ ];
+
+ var mathSqrt = Math.sqrt;
+ var mathSin = Math.sin;
+ var mathCos = Math.cos;
+ var PI = Math.PI;
+
+ var vMag = function(v) {
+ return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
+ };
+ var vRatio = function(u, v) {
+ return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
+ };
+ var vAngle = function(u, v) {
+ return (u[0] * v[1] < u[1] * v[0] ? -1 : 1)
+ * Math.acos(vRatio(u, v));
+ };
+
+ function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
+ var psi = psiDeg * (PI / 180.0);
+ var xp = mathCos(psi) * (x1 - x2) / 2.0
+ + mathSin(psi) * (y1 - y2) / 2.0;
+ var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0
+ + mathCos(psi) * (y1 - y2) / 2.0;
+
+ var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
+
+ if (lambda > 1) {
+ rx *= mathSqrt(lambda);
+ ry *= mathSqrt(lambda);
+ }
+
+ var f = (fa === fs ? -1 : 1)
+ * mathSqrt((((rx * rx) * (ry * ry))
+ - ((rx * rx) * (yp * yp))
+ - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp)
+ + (ry * ry) * (xp * xp))
+ ) || 0;
+
+ var cxp = f * rx * yp / ry;
+ var cyp = f * -ry * xp / rx;
+
+ var cx = (x1 + x2) / 2.0
+ + mathCos(psi) * cxp
+ - mathSin(psi) * cyp;
+ var cy = (y1 + y2) / 2.0
+ + mathSin(psi) * cxp
+ + mathCos(psi) * cyp;
+
+ var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]);
+ var u = [ (xp - cxp) / rx, (yp - cyp) / ry ];
+ var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ];
+ var dTheta = vAngle(u, v);
+
+ if (vRatio(u, v) <= -1) {
+ dTheta = PI;
+ }
+ if (vRatio(u, v) >= 1) {
+ dTheta = 0;
+ }
+ if (fs === 0 && dTheta > 0) {
+ dTheta = dTheta - 2 * PI;
+ }
+ if (fs === 1 && dTheta < 0) {
+ dTheta = dTheta + 2 * PI;
+ }
+
+ path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
+ }
+
+ function createPathProxyFromString(data) {
+ if (!data) {
+ return [];
+ }
+
+ // command string
+ var cs = data.replace(/-/g, ' -')
+ .replace(/ /g, ' ')
+ .replace(/ /g, ',')
+ .replace(/,,/g, ',');
+
+ var n;
+ // create pipes so that we can split the data
+ for (n = 0; n < cc.length; n++) {
+ cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);
+ }
+
+ // create array
+ var arr = cs.split('|');
+ // init context point
+ var cpx = 0;
+ var cpy = 0;
+
+ var path = new PathProxy();
+ var CMD = PathProxy.CMD;
+
+ var prevCmd;
+ for (n = 1; n < arr.length; n++) {
+ var str = arr[n];
+ var c = str.charAt(0);
+ var off = 0;
+ var p = str.slice(1).replace(/e,-/g, 'e-').split(',');
+ var cmd;
+
+ if (p.length > 0 && p[0] === '') {
+ p.shift();
+ }
+
+ for (var i = 0; i < p.length; i++) {
+ p[i] = parseFloat(p[i]);
+ }
+ while (off < p.length && !isNaN(p[off])) {
+ if (isNaN(p[0])) {
+ break;
+ }
+ var ctlPtx;
+ var ctlPty;
+
+ var rx;
+ var ry;
+ var psi;
+ var fa;
+ var fs;
+
+ var x1 = cpx;
+ var y1 = cpy;
+
+ // convert l, H, h, V, and v to L
+ switch (c) {
+ case 'l':
+ cpx += p[off++];
+ cpy += p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'L':
+ cpx = p[off++];
+ cpy = p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'm':
+ cpx += p[off++];
+ cpy += p[off++];
+ cmd = CMD.M;
+ path.addData(cmd, cpx, cpy);
+ c = 'l';
+ break;
+ case 'M':
+ cpx = p[off++];
+ cpy = p[off++];
+ cmd = CMD.M;
+ path.addData(cmd, cpx, cpy);
+ c = 'L';
+ break;
+ case 'h':
+ cpx += p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'H':
+ cpx = p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'v':
+ cpy += p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'V':
+ cpy = p[off++];
+ cmd = CMD.L;
+ path.addData(cmd, cpx, cpy);
+ break;
+ case 'C':
+ cmd = CMD.C;
+ path.addData(
+ cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]
+ );
+ cpx = p[off - 2];
+ cpy = p[off - 1];
+ break;
+ case 'c':
+ cmd = CMD.C;
+ path.addData(
+ cmd,
+ p[off++] + cpx, p[off++] + cpy,
+ p[off++] + cpx, p[off++] + cpy,
+ p[off++] + cpx, p[off++] + cpy
+ );
+ cpx += p[off - 2];
+ cpy += p[off - 1];
+ break;
+ case 'S':
+ ctlPtx = cpx;
+ ctlPty = cpy;
+ var len = path.len();
+ var pathData = path.data;
+ if (prevCmd === CMD.C) {
+ ctlPtx += cpx - pathData[len - 4];
+ ctlPty += cpy - pathData[len - 3];
+ }
+ cmd = CMD.C;
+ x1 = p[off++];
+ y1 = p[off++];
+ cpx = p[off++];
+ cpy = p[off++];
+ path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
+ break;
+ case 's':
+ ctlPtx = cpx;
+ ctlPty = cpy;
+ var len = path.len();
+ var pathData = path.data;
+ if (prevCmd === CMD.C) {
+ ctlPtx += cpx - pathData[len - 4];
+ ctlPty += cpy - pathData[len - 3];
+ }
+ cmd = CMD.C;
+ x1 = cpx + p[off++];
+ y1 = cpy + p[off++];
+ cpx += p[off++];
+ cpy += p[off++];
+ path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
+ break;
+ case 'Q':
+ x1 = p[off++];
+ y1 = p[off++];
+ cpx = p[off++];
+ cpy = p[off++];
+ cmd = CMD.Q;
+ path.addData(cmd, x1, y1, cpx, cpy);
+ break;
+ case 'q':
+ x1 = p[off++] + cpx;
+ y1 = p[off++] + cpy;
+ cpx += p[off++];
+ cpy += p[off++];
+ cmd = CMD.Q;
+ path.addData(cmd, x1, y1, cpx, cpy);
+ break;
+ case 'T':
+ ctlPtx = cpx;
+ ctlPty = cpy;
+ var len = path.len();
+ var pathData = path.data;
+ if (prevCmd === CMD.Q) {
+ ctlPtx += cpx - pathData[len - 4];
+ ctlPty += cpy - pathData[len - 3];
+ }
+ cpx = p[off++];
+ cpy = p[off++];
+ cmd = CMD.Q;
+ path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
+ break;
+ case 't':
+ ctlPtx = cpx;
+ ctlPty = cpy;
+ var len = path.len();
+ var pathData = path.data;
+ if (prevCmd === CMD.Q) {
+ ctlPtx += cpx - pathData[len - 4];
+ ctlPty += cpy - pathData[len - 3];
+ }
+ cpx += p[off++];
+ cpy += p[off++];
+ cmd = CMD.Q;
+ path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
+ break;
+ case 'A':
+ rx = p[off++];
+ ry = p[off++];
+ psi = p[off++];
+ fa = p[off++];
+ fs = p[off++];
+
+ x1 = cpx, y1 = cpy;
+ cpx = p[off++];
+ cpy = p[off++];
+ cmd = CMD.A;
+ processArc(
+ x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
+ );
+ break;
+ case 'a':
+ rx = p[off++];
+ ry = p[off++];
+ psi = p[off++];
+ fa = p[off++];
+ fs = p[off++];
+
+ x1 = cpx, y1 = cpy;
+ cpx += p[off++];
+ cpy += p[off++];
+ cmd = CMD.A;
+ processArc(
+ x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
+ );
+ break;
+ }
+ }
+
+ if (c === 'z' || c === 'Z') {
+ cmd = CMD.Z;
+ path.addData(cmd);
+ }
+
+ prevCmd = cmd;
+ }
+
+ path.toStatic();
+
+ return path;
+ }
+
+ // TODO Optimize double memory cost problem
+ function createPathOptions(str, opts) {
+ var pathProxy = createPathProxyFromString(str);
+ opts = opts || {};
+ opts.buildPath = function (path) {
+ if (path.setData) {
+ path.setData(pathProxy.data);
+ // Svg and vml renderer don't have context
+ var ctx = path.getContext();
+ if (ctx) {
+ path.rebuildPath(ctx);
+ }
+ }
+ else {
+ var ctx = path;
+ pathProxy.rebuildPath(ctx);
+ }
+ };
+
+ opts.applyTransform = function (m) {
+ transformPath(pathProxy, m);
+
+ this.dirty(true);
+ };
+
+ return opts;
+ }
+
+ module.exports = {
+ /**
+ * Create a Path object from path string data
+ * http://www.w3.org/TR/SVG/paths.html#PathData
+ * @param {Object} opts Other options
+ */
+ createFromString: function (str, opts) {
+ return new Path(createPathOptions(str, opts));
+ },
+
+ /**
+ * Create a Path class from path string data
+ * @param {string} str
+ * @param {Object} opts Other options
+ */
+ extendFromString: function (str, opts) {
+ return Path.extend(createPathOptions(str, opts));
+ },
+
+ /**
+ * Merge multiple paths
+ */
+ // TODO Apply transform
+ // TODO stroke dash
+ // TODO Optimize double memory cost problem
+ mergePath: function (pathEls, opts) {
+ var pathList = [];
+ var len = pathEls.length;
+ for (var i = 0; i < len; i++) {
+ var pathEl = pathEls[i];
+ if (!pathEl.path) {
+ pathEl.createPathProxy();
+ }
+ if (pathEl.__dirtyPath) {
+ pathEl.buildPath(pathEl.path, pathEl.shape, true);
+ }
+ pathList.push(pathEl.path);
+ }
+
+ var pathBundle = new Path(opts);
+ // Need path proxy.
+ pathBundle.createPathProxy();
+ pathBundle.buildPath = function (path) {
+ path.appendPath(pathList);
+ // Svg and vml renderer don't have context
+ var ctx = path.getContext();
+ if (ctx) {
+ path.rebuildPath(ctx);
+ }
+ };
+
+ return pathBundle;
+ }
+ };
+
+
+/***/ },
+/* 20 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Path element
+ * @module zrender/graphic/Path
+ */
+
+
+
+ var Displayable = __webpack_require__(21);
+ var zrUtil = __webpack_require__(4);
+ var PathProxy = __webpack_require__(36);
+ var pathContain = __webpack_require__(39);
+
+ var Pattern = __webpack_require__(46);
+ var getCanvasPattern = Pattern.prototype.getCanvasPattern;
+
+ var abs = Math.abs;
+
+ var pathProxyForDraw = new PathProxy(true);
+ /**
+ * @alias module:zrender/graphic/Path
+ * @extends module:zrender/graphic/Displayable
+ * @constructor
+ * @param {Object} opts
+ */
+ function Path(opts) {
+ Displayable.call(this, opts);
+
+ /**
+ * @type {module:zrender/core/PathProxy}
+ * @readOnly
+ */
+ this.path = null;
+ }
+
+ Path.prototype = {
+
+ constructor: Path,
+
+ type: 'path',
+
+ __dirtyPath: true,
+
+ strokeContainThreshold: 5,
+
+ brush: function (ctx, prevEl) {
+ var style = this.style;
+ var path = this.path || pathProxyForDraw;
+ var hasStroke = style.hasStroke();
+ var hasFill = style.hasFill();
+ var fill = style.fill;
+ var stroke = style.stroke;
+ var hasFillGradient = hasFill && !!(fill.colorStops);
+ var hasStrokeGradient = hasStroke && !!(stroke.colorStops);
+ var hasFillPattern = hasFill && !!(fill.image);
+ var hasStrokePattern = hasStroke && !!(stroke.image);
+
+ style.bind(ctx, this, prevEl);
+ this.setTransform(ctx);
+
+ if (this.__dirty) {
+ var rect;
+ // Update gradient because bounding rect may changed
+ if (hasFillGradient) {
+ rect = rect || this.getBoundingRect();
+ this._fillGradient = style.getGradient(ctx, fill, rect);
+ }
+ if (hasStrokeGradient) {
+ rect = rect || this.getBoundingRect();
+ this._strokeGradient = style.getGradient(ctx, stroke, rect);
+ }
+ }
+ // Use the gradient or pattern
+ if (hasFillGradient) {
+ // PENDING If may have affect the state
+ ctx.fillStyle = this._fillGradient;
+ }
+ else if (hasFillPattern) {
+ ctx.fillStyle = getCanvasPattern.call(fill, ctx);
+ }
+ if (hasStrokeGradient) {
+ ctx.strokeStyle = this._strokeGradient;
+ }
+ else if (hasStrokePattern) {
+ ctx.strokeStyle = getCanvasPattern.call(stroke, ctx);
+ }
+
+ var lineDash = style.lineDash;
+ var lineDashOffset = style.lineDashOffset;
+
+ var ctxLineDash = !!ctx.setLineDash;
+
+ // Update path sx, sy
+ var scale = this.getGlobalScale();
+ path.setScale(scale[0], scale[1]);
+
+ // Proxy context
+ // Rebuild path in following 2 cases
+ // 1. Path is dirty
+ // 2. Path needs javascript implemented lineDash stroking.
+ // In this case, lineDash information will not be saved in PathProxy
+ if (this.__dirtyPath
+ || (lineDash && !ctxLineDash && hasStroke)
+ ) {
+ path.beginPath(ctx);
+
+ // Setting line dash before build path
+ if (lineDash && !ctxLineDash) {
+ path.setLineDash(lineDash);
+ path.setLineDashOffset(lineDashOffset);
+ }
+
+ this.buildPath(path, this.shape, false);
+
+ // Clear path dirty flag
+ if (this.path) {
+ this.__dirtyPath = false;
+ }
+ }
+ else {
+ // Replay path building
+ ctx.beginPath();
+ this.path.rebuildPath(ctx);
+ }
+
+ hasFill && path.fill(ctx);
+
+ if (lineDash && ctxLineDash) {
+ ctx.setLineDash(lineDash);
+ ctx.lineDashOffset = lineDashOffset;
+ }
+
+ hasStroke && path.stroke(ctx);
+
+ if (lineDash && ctxLineDash) {
+ // PENDING
+ // Remove lineDash
+ ctx.setLineDash([]);
+ }
+
+
+ this.restoreTransform(ctx);
+
+ // Draw rect text
+ if (style.text != null) {
+ this.drawRectText(ctx, this.getBoundingRect());
+ }
+ },
+
+ // When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath
+ // Like in circle
+ buildPath: function (ctx, shapeCfg, inBundle) {},
+
+ createPathProxy: function () {
+ this.path = new PathProxy();
+ },
+
+ getBoundingRect: function () {
+ var rect = this._rect;
+ var style = this.style;
+ var needsUpdateRect = !rect;
+ if (needsUpdateRect) {
+ var path = this.path;
+ if (!path) {
+ // Create path on demand.
+ path = this.path = new PathProxy();
+ }
+ if (this.__dirtyPath) {
+ path.beginPath();
+ this.buildPath(path, this.shape, false);
+ }
+ rect = path.getBoundingRect();
+ }
+ this._rect = rect;
+
+ if (style.hasStroke()) {
+ // Needs update rect with stroke lineWidth when
+ // 1. Element changes scale or lineWidth
+ // 2. Shape is changed
+ var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone());
+ if (this.__dirty || needsUpdateRect) {
+ rectWithStroke.copy(rect);
+ // FIXME Must after updateTransform
+ var w = style.lineWidth;
+ // PENDING, Min line width is needed when line is horizontal or vertical
+ var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
+
+ // Only add extra hover lineWidth when there are no fill
+ if (!style.hasFill()) {
+ w = Math.max(w, this.strokeContainThreshold || 4);
+ }
+ // Consider line width
+ // Line scale can't be 0;
+ if (lineScale > 1e-10) {
+ rectWithStroke.width += w / lineScale;
+ rectWithStroke.height += w / lineScale;
+ rectWithStroke.x -= w / lineScale / 2;
+ rectWithStroke.y -= w / lineScale / 2;
+ }
+ }
+
+ // Return rect with stroke
+ return rectWithStroke;
+ }
+
+ return rect;
+ },
+
+ contain: function (x, y) {
+ var localPos = this.transformCoordToLocal(x, y);
+ var rect = this.getBoundingRect();
+ var style = this.style;
+ x = localPos[0];
+ y = localPos[1];
+
+ if (rect.contain(x, y)) {
+ var pathData = this.path.data;
+ if (style.hasStroke()) {
+ var lineWidth = style.lineWidth;
+ var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
+ // Line scale can't be 0;
+ if (lineScale > 1e-10) {
+ // Only add extra hover lineWidth when there are no fill
+ if (!style.hasFill()) {
+ lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
+ }
+ if (pathContain.containStroke(
+ pathData, lineWidth / lineScale, x, y
+ )) {
+ return true;
+ }
+ }
+ }
+ if (style.hasFill()) {
+ return pathContain.contain(pathData, x, y);
+ }
+ }
+ return false;
+ },
+
+ /**
+ * @param {boolean} dirtyPath
+ */
+ dirty: function (dirtyPath) {
+ if (dirtyPath == null) {
+ dirtyPath = true;
+ }
+ // Only mark dirty, not mark clean
+ if (dirtyPath) {
+ this.__dirtyPath = dirtyPath;
+ this._rect = null;
+ }
+
+ this.__dirty = true;
+
+ this.__zr && this.__zr.refresh();
+
+ // Used as a clipping path
+ if (this.__clipTarget) {
+ this.__clipTarget.dirty();
+ }
+ },
+
+ /**
+ * Alias for animate('shape')
+ * @param {boolean} loop
+ */
+ animateShape: function (loop) {
+ return this.animate('shape', loop);
+ },
+
+ // Overwrite attrKV
+ attrKV: function (key, value) {
+ // FIXME
+ if (key === 'shape') {
+ this.setShape(value);
+ this.__dirtyPath = true;
+ this._rect = null;
+ }
+ else {
+ Displayable.prototype.attrKV.call(this, key, value);
+ }
+ },
+
+ /**
+ * @param {Object|string} key
+ * @param {*} value
+ */
+ setShape: function (key, value) {
+ var shape = this.shape;
+ // Path from string may not have shape
+ if (shape) {
+ if (zrUtil.isObject(key)) {
+ for (var name in key) {
+ if (key.hasOwnProperty(name)) {
+ shape[name] = key[name];
+ }
+ }
+ }
+ else {
+ shape[key] = value;
+ }
+ this.dirty(true);
+ }
+ return this;
+ },
+
+ getLineScale: function () {
+ var m = this.transform;
+ // Get the line scale.
+ // Determinant of `m` means how much the area is enlarged by the
+ // transformation. So its square root can be used as a scale factor
+ // for width.
+ return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10
+ ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1]))
+ : 1;
+ }
+ };
+
+ /**
+ * 扩展一个 Path element, 比如星形,圆等。
+ * Extend a path element
+ * @param {Object} props
+ * @param {string} props.type Path type
+ * @param {Function} props.init Initialize
+ * @param {Function} props.buildPath Overwrite buildPath method
+ * @param {Object} [props.style] Extended default style config
+ * @param {Object} [props.shape] Extended default shape config
+ */
+ Path.extend = function (defaults) {
+ var Sub = function (opts) {
+ Path.call(this, opts);
+
+ if (defaults.style) {
+ // Extend default style
+ this.style.extendFrom(defaults.style, false);
+ }
+
+ // Extend default shape
+ var defaultShape = defaults.shape;
+ if (defaultShape) {
+ this.shape = this.shape || {};
+ var thisShape = this.shape;
+ for (var name in defaultShape) {
+ if (
+ ! thisShape.hasOwnProperty(name)
+ && defaultShape.hasOwnProperty(name)
+ ) {
+ thisShape[name] = defaultShape[name];
+ }
+ }
+ }
+
+ defaults.init && defaults.init.call(this, opts);
+ };
+
+ zrUtil.inherits(Sub, Path);
+
+ // FIXME 不能 extend position, rotation 等引用对象
+ for (var name in defaults) {
+ // Extending prototype values and methods
+ if (name !== 'style' && name !== 'shape') {
+ Sub.prototype[name] = defaults[name];
+ }
+ }
+
+ return Sub;
+ };
+
+ zrUtil.inherits(Path, Displayable);
+
+ module.exports = Path;
+
+
+/***/ },
+/* 21 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 可绘制的图形基类
+ * Base class of all displayable graphic objects
+ * @module zrender/graphic/Displayable
+ */
+
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var Style = __webpack_require__(22);
+
+ var Element = __webpack_require__(23);
+ var RectText = __webpack_require__(35);
+ // 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,
+
+ /**
+ * Render the element progressively when the value >= 0,
+ * usefull for large data.
+ * @type {number}
+ */
+ progressive: -1,
+
+ beforeBrush: function (ctx) {},
+
+ afterBrush: function (ctx) {},
+
+ /**
+ * 图形绘制方法
+ * @param {Canvas2DRenderingContext} ctx
+ */
+ // Interface
+ brush: function (ctx, prevEl) {},
+
+ /**
+ * 获取最小包围盒
+ * @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(false);
+ return this;
+ },
+
+ /**
+ * Use given style object
+ * @param {Object} obj
+ */
+ useStyle: function (obj) {
+ this.style = new Style(obj);
+ this.dirty(false);
+ return this;
+ }
+ };
+
+ zrUtil.inherits(Displayable, Element);
+
+ zrUtil.mixin(Displayable, RectText);
+ // zrUtil.mixin(Displayable, Stateful);
+
+ module.exports = Displayable;
+
+
+/***/ },
+/* 22 */
+/***/ function(module, exports) {
+
+ /**
+ * @module zrender/graphic/Style
+ */
+
+
+ var STYLE_COMMON_PROPS = [
+ ['shadowBlur', 0], ['shadowOffsetX', 0], ['shadowOffsetY', 0], ['shadowColor', '#000'],
+ ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]
+ ];
+
+ // var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4);
+ // var LINE_PROPS = STYLE_COMMON_PROPS.slice(4);
+
+ var Style = function (opts) {
+ this.extendFrom(opts);
+ };
+
+ function createLinearGradient(ctx, obj, rect) {
+ var x = obj.x == null ? 0 : obj.x;
+ var x2 = obj.x2 == null ? 1 : obj.x2;
+ var y = obj.y == null ? 0 : obj.y;
+ var y2 = obj.y2 == null ? 0 : obj.y2;
+
+ if (!obj.global) {
+ x = x * rect.width + rect.x;
+ x2 = x2 * rect.width + rect.x;
+ y = y * rect.height + rect.y;
+ y2 = y2 * rect.height + rect.y;
+ }
+
+ var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);
+
+ return canvasGradient;
+ }
+
+ function createRadialGradient(ctx, obj, rect) {
+ var width = rect.width;
+ var height = rect.height;
+ var min = Math.min(width, height);
+
+ var x = obj.x == null ? 0.5 : obj.x;
+ var y = obj.y == null ? 0.5 : obj.y;
+ var r = obj.r == null ? 0.5 : obj.r;
+ if (!obj.global) {
+ x = x * width + rect.x;
+ y = y * height + rect.y;
+ r = r * min;
+ }
+
+ var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);
+
+ return canvasGradient;
+ }
+
+
+ Style.prototype = {
+
+ constructor: Style,
+
+ /**
+ * @type {string}
+ */
+ fill: '#000000',
+
+ /**
+ * @type {string}
+ */
+ stroke: null,
+
+ /**
+ * @type {number}
+ */
+ opacity: 1,
+
+ /**
+ * @type {Array.}
+ */
+ 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.}
+ * @default 'inside'
+ */
+ textPosition: 'inside',
+
+ /**
+ * If not specified, use the boundingRect of a `displayable`.
+ * @type {Object}
+ */
+ textPositionRect: null,
+
+ /**
+ * [x, y]
+ * @type {Array.}
+ */
+ textOffset: null,
+
+ /**
+ * @type {string}
+ */
+ textBaseline: null,
+
+ /**
+ * @type {string}
+ */
+ textAlign: null,
+
+ /**
+ * @type {string}
+ */
+ textVerticalAlign: null,
+
+ /**
+ * Only useful in Path and Image element
+ * @type {number}
+ */
+ textDistance: 5,
+
+ /**
+ * Only useful in Path and Image element
+ * @type {number}
+ */
+ textShadowBlur: 0,
+
+ /**
+ * Only useful in Path and Image element
+ * @type {number}
+ */
+ textShadowOffsetX: 0,
+
+ /**
+ * Only useful in Path and Image element
+ * @type {number}
+ */
+ textShadowOffsetY: 0,
+
+ /**
+ * If transform text
+ * Only useful in Path and Image element
+ * @type {boolean}
+ */
+ textTransform: false,
+
+ /**
+ * Text rotate around position of Path or Image
+ * Only useful in Path and Image element and textTransform is false.
+ */
+ textRotation: 0,
+
+ /**
+ * @type {string}
+ * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
+ */
+ blend: null,
+
+ /**
+ * @param {CanvasRenderingContext2D} ctx
+ */
+ bind: function (ctx, el, prevEl) {
+ var style = this;
+ var prevStyle = prevEl && prevEl.style;
+ var firstDraw = !prevStyle;
+
+ for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
+ var prop = STYLE_COMMON_PROPS[i];
+ var styleName = prop[0];
+
+ if (firstDraw || style[styleName] !== prevStyle[styleName]) {
+ // FIXME Invalid property value will cause style leak from previous element.
+ ctx[styleName] = style[styleName] || prop[1];
+ }
+ }
+
+ if ((firstDraw || style.fill !== prevStyle.fill)) {
+ ctx.fillStyle = style.fill;
+ }
+ if ((firstDraw || style.stroke !== prevStyle.stroke)) {
+ ctx.strokeStyle = style.stroke;
+ }
+ if ((firstDraw || style.opacity !== prevStyle.opacity)) {
+ ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
+ }
+
+ if ((firstDraw || style.blend !== prevStyle.blend)) {
+ ctx.globalCompositeOperation = style.blend || 'source-over';
+ }
+ if (this.hasStroke()) {
+ var lineWidth = style.lineWidth;
+ ctx.lineWidth = lineWidth / (
+ (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1
+ );
+ }
+ },
+
+ hasFill: function () {
+ var fill = this.fill;
+ return fill != null && fill !== 'none';
+ },
+
+ hasStroke: function () {
+ var stroke = this.stroke;
+ return stroke != null && stroke !== 'none' && this.lineWidth > 0;
+ },
+
+ /**
+ * 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;
+ },
+
+ getGradient: function (ctx, obj, rect) {
+ var method = obj.type === 'radial' ? createRadialGradient : createLinearGradient;
+ var canvasGradient = method(ctx, obj, rect);
+ var colorStops = obj.colorStops;
+ for (var i = 0; i < colorStops.length; i++) {
+ canvasGradient.addColorStop(
+ colorStops[i].offset, colorStops[i].color
+ );
+ }
+ return canvasGradient;
+ }
+ };
+
+ var styleProto = Style.prototype;
+ for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
+ var prop = STYLE_COMMON_PROPS[i];
+ if (!(prop[0] in styleProto)) {
+ styleProto[prop[0]] = prop[1];
+ }
+ }
+
+ // Provide for others
+ Style.getGradient = styleProto.getGradient;
+
+ module.exports = Style;
+
+
+/***/ },
+/* 23 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * @module zrender/Element
+ */
+
+
+ var guid = __webpack_require__(24);
+ var Eventful = __webpack_require__(25);
+ var Transformable = __webpack_require__(26);
+ var Animatable = __webpack_require__(27);
+ var zrUtil = __webpack_require__(4);
+
+ /**
+ * @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(false);
+ },
+
+ /**
+ * 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(false);
+
+ 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(false);
+ },
+
+ /**
+ */
+ 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(false);
+ }
+ },
+
+ /**
+ * Add self from zrender instance.
+ * Not recursively because it will be invoked when element added to storage.
+ * @param {module:zrender/ZRender} zr
+ */
+ addSelfToZr: function (zr) {
+ this.__zr = zr;
+ // 添加动画
+ 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);
+
+ module.exports = Element;
+
+
+/***/ },
+/* 24 */
+/***/ function(module, exports) {
+
+ /**
+ * zrender: 生成唯一id
+ *
+ * @author errorrik (errorrik@gmail.com)
+ */
+
+
+ var idStart = 0x0907;
+
+ module.exports = function () {
+ return idStart++;
+ };
+
+
+
+/***/ },
+/* 25 */
+/***/ function(module, exports) {
+
+ /**
+ * 事件扩展
+ * @module zrender/mixin/Eventful
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * pissang (https://www.github.com/pissang)
+ */
+
+
+ var arrySlice = Array.prototype.slice;
+
+ /**
+ * 事件分发器
+ * @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] = [];
+ }
+
+ for (var i = 0; i < _h[event].length; i++) {
+ if (_h[event][i].h === handler) {
+ 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] = [];
+ }
+
+ for (var i = 0; i < _h[event].length; i++) {
+ if (_h[event][i].h === handler) {
+ return this;
+ }
+ }
+
+ _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#ondrag
+ * @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
+ */
+
+ module.exports = Eventful;
+
+
+
+/***/ },
+/* 26 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 提供变换扩展
+ * @module zrender/mixin/Transformable
+ * @author pissang (https://www.github.com/pissang)
+ */
+
+
+ var matrix = __webpack_require__(11);
+ var vector = __webpack_require__(10);
+ 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.}
+ * @default [0, 0]
+ */
+ this.position = [0, 0];
+ }
+ if (opts.rotation == null) {
+ /**
+ * 旋转
+ * @type {Array.}
+ * @default 0
+ */
+ this.rotation = 0;
+ }
+ if (!opts.scale) {
+ /**
+ * 缩放
+ * @type {Array.}
+ * @default [1, 1]
+ */
+ this.scale = [1, 1];
+ }
+ /**
+ * 旋转和缩放的原点
+ * @type {Array.}
+ * @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) {
+ return Transformable.getLocalTransform(this, m);
+ };
+
+ /**
+ * 将自己的transform应用到context上
+ * @param {Context2D} ctx
+ */
+ transformableProto.setTransform = function (ctx) {
+ var m = this.transform;
+ var dpr = ctx.dpr || 1;
+ if (m) {
+ ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
+ }
+ else {
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+ }
+ };
+
+ transformableProto.restoreTransform = function (ctx) {
+ var dpr = ctx.dpr || 1;
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+ };
+
+ var tmpTransform = [];
+
+ /**
+ * 分解`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);
+ };
+
+ /**
+ * Get global scale
+ * @return {Array.}
+ */
+ transformableProto.getGlobalScale = function () {
+ var m = this.transform;
+ if (!m) {
+ return [1, 1];
+ }
+ var sx = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
+ var sy = Math.sqrt(m[2] * m[2] + m[3] * m[3]);
+ if (m[0] < 0) {
+ sx = -sx;
+ }
+ if (m[3] < 0) {
+ sy = -sy;
+ }
+ return [sx, sy];
+ };
+ /**
+ * 变换坐标位置到 shape 的局部坐标空间
+ * @method
+ * @param {number} x
+ * @param {number} y
+ * @return {Array.}
+ */
+ 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.}
+ */
+ transformableProto.transformCoordToGlobal = function (x, y) {
+ var v2 = [x, y];
+ var transform = this.transform;
+ if (transform) {
+ vector.applyTransform(v2, v2, transform);
+ }
+ return v2;
+ };
+
+ /**
+ * @static
+ * @param {Object} target
+ * @param {Array.} target.origin
+ * @param {number} target.rotation
+ * @param {Array.} target.position
+ * @param {Array.} [m]
+ */
+ Transformable.getLocalTransform = function (target, m) {
+ m = m || [];
+ mIdentity(m);
+
+ var origin = target.origin;
+ var scale = target.scale || [1, 1];
+ var rotation = target.rotation || 0;
+ var position = target.position || [0, 0];
+
+ 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;
+ };
+
+ module.exports = Transformable;
+
+
+
+/***/ },
+/* 27 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * @module zrender/mixin/Animatable
+ */
+
+
+ var Animator = __webpack_require__(28);
+ var util = __webpack_require__(4);
+ var isString = util.isString;
+ var isFunction = util.isFunction;
+ var isObject = util.isObject;
+ var log = __webpack_require__(33);
+
+ /**
+ * @alias modue:zrender/mixin/Animatable
+ * @constructor
+ */
+ var Animatable = function () {
+
+ /**
+ * @type {Array.}
+ * @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 (!target.hasOwnProperty(name)) {
+ continue;
+ }
+
+ 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;
+ }
+ };
+
+ module.exports = Animatable;
+
+
+/***/ },
+/* 28 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @module echarts/animation/Animator
+ */
+
+
+ var Clip = __webpack_require__(29);
+ var color = __webpack_require__(31);
+ var util = __webpack_require__(4);
+ 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 = len && p0[0].length;
+ for (var i = 0; i < len; i++) {
+ for (var j = 0; j < len2; j++) {
+ out[i][j] = interpolateNumber(
+ p0[i][j], p1[i][j], percent
+ );
+ }
+ }
+ }
+ }
+
+ // arr0 is source array, arr1 is target array.
+ // Do some preprocess to avoid error happened when interpolating from arr0 to arr1
+ function fillArr(arr0, arr1, arrDim) {
+ var arr0Len = arr0.length;
+ var arr1Len = arr1.length;
+ if (arr0Len !== arr1Len) {
+ // 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])
+ );
+ }
+ }
+ }
+ // Handling NaN value
+ var len2 = arr0[0] && arr0[0].length;
+ for (var i = 0; i < arr0.length; i++) {
+ if (arrDim === 1) {
+ if (isNaN(arr0[i])) {
+ arr0[i] = arr1[i];
+ }
+ }
+ else {
+ for (var j = 0; j < len2; j++) {
+ if (isNaN(arr0[i][j])) {
+ arr0[i][j] = arr1[i][j];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @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 getArrayDim(keyframes) {
+ var lastValue = keyframes[keyframes.length - 1].value;
+ return isArrayLike(lastValue && lastValue[0]) ? 2 : 1;
+ }
+
+ 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 ? getArrayDim(keyframes) : 0;
+
+ 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;
+ }
+
+ var lastValue = kfValues[trackLen - 1];
+ // Polyfill array and NaN value
+ for (var i = 0; i < trackLen - 1; i++) {
+ if (isValueArray) {
+ fillArr(kfValues[i], lastValue, arrDim);
+ }
+ else {
+ if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) {
+ kfValues[i] = lastValue;
+ }
+ }
+ }
+ isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim);
+
+ // Cache the key of last frame to speed up when
+ // 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;
+ // In the easing function like elasticOut, percent may less than 0
+ if (percent < 0) {
+ frame = 0;
+ }
+ else if (percent < lastFramePercent) {
+ // Start from next key
+ // PENDING start from lastFrame ?
+ start = Math.min(lastFrame + 1, trackLen - 1);
+ for (frame = start; frame >= 0; frame--) {
+ if (kfPercents[frame] <= percent) {
+ break;
+ }
+ }
+ // PENDING really need to do this ?
+ frame = Math.min(frame, trackLen - 2);
+ }
+ else {
+ for (frame = lastFrame; frame < trackLen; frame++) {
+ if (kfPercents[frame] > percent) {
+ break;
+ }
+ }
+ frame = Math.min(frame - 1, trackLen - 2);
+ }
+ lastFrame = frame;
+ lastFramePercent = percent;
+
+ 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 (!props.hasOwnProperty(propName)) {
+ continue;
+ }
+
+ 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;
+ },
+
+ pause: function () {
+ for (var i = 0; i < this._clipList.length; i++) {
+ this._clipList[i].pause();
+ }
+ this._paused = true;
+ },
+
+ resume: function () {
+ for (var i = 0; i < this._clipList.length; i++) {
+ this._clipList[i].resume();
+ }
+ this._paused = false;
+ },
+
+ isPaused: function () {
+ return !!this._paused;
+ },
+
+ _doneCallback: function () {
+ // 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) {
+ if (!this._tracks.hasOwnProperty(propName)) {
+ continue;
+ }
+ 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.}
+ */
+ getClips: function () {
+ return this._clipList;
+ }
+ };
+
+ module.exports = Animator;
+
+
+/***/ },
+/* 29 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 动画主控制器
+ * @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
+ */
+
+
+ var easingFuncs = __webpack_require__(30);
+
+ 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;
+
+ this._pausedTime = 0;
+ this._paused = false;
+ }
+
+ Clip.prototype = {
+
+ constructor: Clip,
+
+ step: function (globalTime, deltaTime) {
+ // Set startTime on first step, or _startTime may has milleseconds different between clips
+ // PENDING
+ if (!this._initialized) {
+ this._startTime = globalTime + this._delay;
+ this._initialized = true;
+ }
+
+ if (this._paused) {
+ this._pausedTime += deltaTime;
+ return;
+ }
+
+ var percent = (globalTime - this._startTime - this._pausedTime) / this._life;
+
+ // 还没开始
+ if (percent < 0) {
+ 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 (globalTime);
+ // 重新开始周期
+ // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件
+ return 'restart';
+ }
+
+ // 动画完成将这个控制器标识为待删除
+ // 在Animation.update中进行批量删除
+ this._needsRemove = true;
+ return 'destroy';
+ }
+
+ return null;
+ },
+
+ restart: function (globalTime) {
+ var remainder = (globalTime - this._startTime - this._pausedTime) % this._life;
+ this._startTime = globalTime - remainder + this.gap;
+ this._pausedTime = 0;
+
+ this._needsRemove = false;
+ },
+
+ fire: function (eventType, arg) {
+ eventType = 'on' + eventType;
+ if (this[eventType]) {
+ this[eventType](this._target, arg);
+ }
+ },
+
+ pause: function () {
+ this._paused = true;
+ },
+
+ resume: function () {
+ this._paused = false;
+ }
+ };
+
+ module.exports = Clip;
+
+
+
+/***/ },
+/* 30 */
+/***/ function(module, exports) {
+
+ /**
+ * 缓动代码来自 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
+ */
+
+ 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;
+ }
+ };
+
+ module.exports = easing;
+
+
+
+
+/***/ },
+/* 31 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @module zrender/tool/color
+ */
+
+
+ var LRU = __webpack_require__(32);
+
+ 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;
+ }
+
+ function setRgba(out, r, g, b, a) {
+ out[0] = r; out[1] = g; out[2] = b; out[3] = a;
+ return out;
+ }
+ function copyRgba(out, a) {
+ out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3];
+ return out;
+ }
+ var colorCache = new LRU(20);
+ var lastRemovedArr = null;
+ function putToCache(colorStr, rgbaArr) {
+ // Reuse removed array
+ if (lastRemovedArr) {
+ copyRgba(lastRemovedArr, rgbaArr);
+ }
+ lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice()));
+ }
+ /**
+ * @param {string} colorStr
+ * @param {Array.} out
+ * @return {Array.}
+ * @memberOf module:zrender/util/color
+ */
+ function parse(colorStr, rgbaArr) {
+ if (!colorStr) {
+ return;
+ }
+ rgbaArr = rgbaArr || [];
+
+ var cached = colorCache.get(colorStr);
+ if (cached) {
+ return copyRgba(rgbaArr, cached);
+ }
+
+ // 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) {
+ copyRgba(rgbaArr, kCSSColorTable[str]);
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ }
+
+ // #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)) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return; // Covers NaN.
+ }
+ setRgba(rgbaArr,
+ ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
+ (iv & 0xf0) | ((iv & 0xf0) >> 4),
+ (iv & 0xf) | ((iv & 0xf) << 4),
+ 1
+ );
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ }
+ else if (str.length === 7) {
+ var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
+ if (!(iv >= 0 && iv <= 0xffffff)) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return; // Covers NaN.
+ }
+ setRgba(rgbaArr,
+ (iv & 0xff0000) >> 16,
+ (iv & 0xff00) >> 8,
+ iv & 0xff,
+ 1
+ );
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ }
+
+ 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) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return;
+ }
+ alpha = parseCssFloat(params.pop()); // jshint ignore:line
+ // Fall through.
+ case 'rgb':
+ if (params.length !== 3) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return;
+ }
+ setRgba(rgbaArr,
+ parseCssInt(params[0]),
+ parseCssInt(params[1]),
+ parseCssInt(params[2]),
+ alpha
+ );
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ case 'hsla':
+ if (params.length !== 4) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return;
+ }
+ params[3] = parseCssFloat(params[3]);
+ hsla2rgba(params, rgbaArr);
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ case 'hsl':
+ if (params.length !== 3) {
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return;
+ }
+ hsla2rgba(params, rgbaArr);
+ putToCache(colorStr, rgbaArr);
+ return rgbaArr;
+ default:
+ return;
+ }
+ }
+
+ setRgba(rgbaArr, 0, 0, 0, 1);
+ return;
+ }
+
+ /**
+ * @param {Array.} hsla
+ * @param {Array.} rgba
+ * @return {Array.} rgba
+ */
+ function hsla2rgba(hsla, rgba) {
+ 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;
+
+ rgba = rgba || [];
+ setRgba(rgba,
+ clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255),
+ clampCssByte(cssHueToRgb(m1, m2, h) * 255),
+ clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255),
+ 1
+ );
+
+ if (hsla.length === 4) {
+ rgba[3] = hsla[3];
+ }
+
+ return rgba;
+ }
+
+ /**
+ * @param {Array.} rgba
+ * @return {Array.} 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.>} colors List of rgba color array
+ * @param {Array.} [out] Mapped gba color array
+ * @return {Array.} will be null/undefined if input illegal.
+ */
+ function fastMapToColor(normalizedValue, colors, out) {
+ if (!(colors && colors.length)
+ || !(normalizedValue >= 0 && normalizedValue <= 1)
+ ) {
+ return;
+ }
+
+ out = out || [];
+
+ var value = normalizedValue * (colors.length - 1);
+ var leftIndex = Math.floor(value);
+ var rightIndex = Math.ceil(value);
+ var leftColor = colors[leftIndex];
+ var rightColor = colors[rightIndex];
+ var dv = value - leftIndex;
+ out[0] = clampCssByte(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] = clampCssFloat(lerp(leftColor[3], rightColor[3], dv));
+
+ return out;
+ }
+ /**
+ * @param {number} normalizedValue A float between 0 and 1.
+ * @param {Array.} 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 {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.} arrColor like [12,33,44,0.4]
+ * @param {string} type 'rgba', 'hsva', ...
+ * @return {string} Result color. (If input illegal, return undefined).
+ */
+ function stringify(arrColor, type) {
+ if (!arrColor || !arrColor.length) {
+ return;
+ }
+ var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];
+ if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
+ colorStr += ',' + arrColor[3];
+ }
+ return type + '(' + colorStr + ')';
+ }
+
+ module.exports = {
+ parse: parse,
+ lift: lift,
+ toHex: toHex,
+ fastMapToColor: fastMapToColor,
+ mapToColor: mapToColor,
+ modifyHSL: modifyHSL,
+ modifyAlpha: modifyAlpha,
+ stringify: stringify
+ };
+
+
+
+
+/***/ },
+/* 32 */
+/***/ function(module, exports) {
+
+ // Simple LRU cache use doubly linked list
+ // @module zrender/core/LRU
+
+
+ /**
+ * Simple double linked list. Compared with array, it has O(1) remove operation.
+ * @constructor
+ */
+ var LinkedList = function () {
+
+ /**
+ * @type {module:zrender/core/LRU~Entry}
+ */
+ this.head = null;
+
+ /**
+ * @type {module:zrender/core/LRU~Entry}
+ */
+ this.tail = null;
+
+ this._len = 0;
+ };
+
+ var linkedListProto = LinkedList.prototype;
+ /**
+ * Insert a new value at the tail
+ * @param {} val
+ * @return {module:zrender/core/LRU~Entry}
+ */
+ linkedListProto.insert = function (val) {
+ var entry = new Entry(val);
+ this.insertEntry(entry);
+ return entry;
+ };
+
+ /**
+ * Insert an entry at the tail
+ * @param {module:zrender/core/LRU~Entry} entry
+ */
+ linkedListProto.insertEntry = function (entry) {
+ if (!this.head) {
+ this.head = this.tail = entry;
+ }
+ else {
+ this.tail.next = entry;
+ entry.prev = this.tail;
+ entry.next = null;
+ this.tail = entry;
+ }
+ this._len++;
+ };
+
+ /**
+ * Remove entry.
+ * @param {module:zrender/core/LRU~Entry} entry
+ */
+ linkedListProto.remove = function (entry) {
+ var prev = entry.prev;
+ var next = entry.next;
+ if (prev) {
+ prev.next = next;
+ }
+ else {
+ // Is head
+ this.head = next;
+ }
+ if (next) {
+ next.prev = prev;
+ }
+ else {
+ // Is tail
+ this.tail = prev;
+ }
+ entry.next = entry.prev = null;
+ this._len--;
+ };
+
+ /**
+ * @return {number}
+ */
+ linkedListProto.len = function () {
+ return this._len;
+ };
+
+ /**
+ * Clear list
+ */
+ linkedListProto.clear = function () {
+ this.head = this.tail = null;
+ this._len = 0;
+ };
+
+ /**
+ * @constructor
+ * @param {} val
+ */
+ var Entry = function (val) {
+ /**
+ * @type {}
+ */
+ this.value = val;
+
+ /**
+ * @type {module:zrender/core/LRU~Entry}
+ */
+ this.next;
+
+ /**
+ * @type {module:zrender/core/LRU~Entry}
+ */
+ this.prev;
+ };
+
+ /**
+ * LRU Cache
+ * @constructor
+ * @alias module:zrender/core/LRU
+ */
+ var LRU = function (maxSize) {
+
+ this._list = new LinkedList();
+
+ this._map = {};
+
+ this._maxSize = maxSize || 10;
+
+ this._lastRemovedEntry = null;
+ };
+
+ var LRUProto = LRU.prototype;
+
+ /**
+ * @param {string} key
+ * @param {} value
+ * @return {} Removed value
+ */
+ LRUProto.put = function (key, value) {
+ var list = this._list;
+ var map = this._map;
+ var removed = null;
+ if (map[key] == null) {
+ var len = list.len();
+ // Reuse last removed entry
+ var entry = this._lastRemovedEntry;
+
+ if (len >= this._maxSize && len > 0) {
+ // Remove the least recently used
+ var leastUsedEntry = list.head;
+ list.remove(leastUsedEntry);
+ delete map[leastUsedEntry.key];
+
+ removed = leastUsedEntry.value;
+ this._lastRemovedEntry = leastUsedEntry;
+ }
+
+ if (entry) {
+ entry.value = value;
+ }
+ else {
+ entry = new Entry(value);
+ }
+ entry.key = key;
+ list.insertEntry(entry);
+ map[key] = entry;
+ }
+
+ return removed;
+ };
+
+ /**
+ * @param {string} key
+ * @return {}
+ */
+ LRUProto.get = function (key) {
+ var entry = this._map[key];
+ var list = this._list;
+ if (entry != null) {
+ // Put the latest used entry in the tail
+ if (entry !== list.tail) {
+ list.remove(entry);
+ list.insertEntry(entry);
+ }
+
+ return entry.value;
+ }
+ };
+
+ /**
+ * Clear the cache
+ */
+ LRUProto.clear = function () {
+ this._list.clear();
+ this._map = {};
+ };
+
+ module.exports = LRU;
+
+
+/***/ },
+/* 33 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+ var config = __webpack_require__(34);
+
+ /**
+ * @exports zrender/tool/log
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ */
+ module.exports = 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)
+ + '
'
+ + document.getElementById('wrong-message').innerHTML;
+ };
+ */
+
+
+
+/***/ },
+/* 34 */
+/***/ function(module, exports) {
+
+
+ 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
+ };
+ module.exports = config;
+
+
+
+
+/***/ },
+/* 35 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Mixin for drawing text in a element bounding rect
+ * @module zrender/mixin/RectText
+ */
+
+
+
+ var textContain = __webpack_require__(8);
+ var BoundingRect = __webpack_require__(9);
+
+ 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;
+ }
+
+ 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;
+ }
+
+ // FIXME
+ ctx.save();
+
+ var x;
+ var y;
+ var textPosition = style.textPosition;
+ var textOffset = style.textOffset;
+ var distance = style.textDistance;
+ var align = style.textAlign;
+ var font = style.textFont || style.font;
+ var baseline = style.textBaseline;
+ var verticalAlign = style.textVerticalAlign;
+ rect = style.textPositionRect || rect;
+
+ textRect = textRect || textContain.getBoundingRect(text, font, align, baseline);
+
+ // Transform rect to view space
+ var transform = this.transform;
+ if (!style.textTransform) {
+ if (transform) {
+ tmpRect.copy(rect);
+ tmpRect.applyTransform(transform);
+ rect = tmpRect;
+ }
+ }
+ else {
+ this.setTransform(ctx);
+ }
+
+ // 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';
+
+ if (verticalAlign) {
+ switch (verticalAlign) {
+ case 'middle':
+ y -= textRect.height / 2 - textRect.lineHeight / 2;
+ break;
+ case 'bottom':
+ y -= textRect.height - textRect.lineHeight / 2;
+ break;
+ default:
+ y += textRect.lineHeight / 2;
+ }
+ // Force bseline to be middle
+ baseline = 'middle';
+ }
+ }
+ 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;
+ }
+
+ if (textOffset) {
+ x += textOffset[0];
+ y += textOffset[1];
+ }
+
+ // Use canvas default left textAlign. Giving invalid value will cause state not change
+ ctx.textAlign = align || 'left';
+ // Use canvas default alphabetic baseline
+ ctx.textBaseline = baseline || 'alphabetic';
+
+ var textFill = style.textFill;
+ var textStroke = style.textStroke;
+ textFill && (ctx.fillStyle = textFill);
+ textStroke && (ctx.strokeStyle = textStroke);
+
+ // TODO Invalid font
+ ctx.font = font || '12px sans-serif';
+
+ // Text shadow
+ // Always set shadowBlur and shadowOffset to avoid leak from displayable
+ ctx.shadowBlur = style.textShadowBlur;
+ ctx.shadowColor = style.textShadowColor || 'transparent';
+ ctx.shadowOffsetX = style.textShadowOffsetX;
+ ctx.shadowOffsetY = style.textShadowOffsetY;
+
+ var textLines = text.split('\n');
+
+ if (style.textRotation) {
+ transform && ctx.translate(transform[4], transform[5]);
+ ctx.rotate(style.textRotation);
+ transform && ctx.translate(-transform[4], -transform[5]);
+ }
+
+ for (var i = 0; i < textLines.length; i++) {
+ // Fill after stroke so the outline will not cover the main part.
+ textStroke && ctx.strokeText(textLines[i], x, y);
+ textFill && ctx.fillText(textLines[i], x, y);
+ y += textRect.lineHeight;
+ }
+
+ ctx.restore();
+ }
+ };
+
+ module.exports = RectText;
+
+
+/***/ },
+/* 36 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中
+ * 可以用于 isInsidePath 判断以及获取boundingRect
+ *
+ * @module zrender/core/PathProxy
+ * @author Yi Shen (http://www.github.com/pissang)
+ */
+
+ // TODO getTotalLength, getPointAtLength
+
+
+ var curve = __webpack_require__(37);
+ var vec2 = __webpack_require__(10);
+ var bbox = __webpack_require__(38);
+ var BoundingRect = __webpack_require__(9);
+ var dpr = __webpack_require__(34).devicePixelRatio;
+
+ var CMD = {
+ M: 1,
+ L: 2,
+ C: 3,
+ Q: 4,
+ A: 5,
+ Z: 6,
+ // Rect
+ R: 7
+ };
+
+ // var CMD_MEM_SIZE = {
+ // M: 3,
+ // L: 3,
+ // C: 7,
+ // Q: 5,
+ // A: 9,
+ // R: 5,
+ // Z: 1
+ // };
+
+ 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 mathAbs = Math.abs;
+
+ var hasTypedArray = typeof Float32Array != 'undefined';
+
+ /**
+ * @alias module:zrender/core/PathProxy
+ * @constructor
+ */
+ var PathProxy = function (notSaveData) {
+
+ this._saveData = !(notSaveData || false);
+
+ if (this._saveData) {
+ /**
+ * Path data. Stored as flat array
+ * @type {Array.}
+ */
+ this.data = [];
+ }
+
+ this._ctx = null;
+ };
+
+ /**
+ * 快速计算Path包围盒(并不是最小包围盒)
+ * @return {Object}
+ */
+ PathProxy.prototype = {
+
+ constructor: PathProxy,
+
+ _xi: 0,
+ _yi: 0,
+
+ _x0: 0,
+ _y0: 0,
+ // Unit x, Unit y. Provide for avoiding drawing that too short line segment
+ _ux: 0,
+ _uy: 0,
+
+ _len: 0,
+
+ _lineDash: null,
+
+ _dashOffset: 0,
+
+ _dashIdx: 0,
+
+ _dashSum: 0,
+
+ /**
+ * @readOnly
+ */
+ setScale: function (sx, sy) {
+ this._ux = mathAbs(1 / dpr / sx) || 0;
+ this._uy = mathAbs(1 / dpr / sy) || 0;
+ },
+
+ getContext: function () {
+ return this._ctx;
+ },
+
+ /**
+ * @param {CanvasRenderingContext2D} ctx
+ * @return {module:zrender/core/PathProxy}
+ */
+ beginPath: function (ctx) {
+
+ this._ctx = ctx;
+
+ ctx && ctx.beginPath();
+
+ ctx && (this.dpr = ctx.dpr);
+
+ // Reset
+ if (this._saveData) {
+ 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) {
+ var exceedUnit = mathAbs(x - this._xi) > this._ux
+ || mathAbs(y - this._yi) > this._uy
+ // Force draw the first segment
+ || this._len < 5;
+
+ this.addData(CMD.L, x, y);
+
+ if (this._ctx && exceedUnit) {
+ this._needsDash() ? this._dashedLineTo(x, y)
+ : this._ctx.lineTo(x, y);
+ }
+ if (exceedUnit) {
+ this._xi = x;
+ this._yi = y;
+ }
+
+ return this;
+ },
+
+ /**
+ * @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._yi = 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.} 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) {
+ if (!this._saveData) {
+ return;
+ }
+
+ 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)
+ || (dx == 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) {
+ idx = this._dashIdx;
+ dash = lineDash[idx];
+ x += dx * dash;
+ y += dy * dash;
+ this._dashIdx = (idx + 1) % nDash;
+ // Skip positive offset
+ if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) {
+ continue;
+ }
+ ctx[idx % 2 ? 'moveTo' : 'lineTo'](
+ dx >= 0 ? mathMin(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
+ */
+ toStatic: function () {
+ var data = this.data;
+ if (data instanceof Array) {
+ data.length = this._len;
+ if (hasTypedArray) {
+ this.data = new Float32Array(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++];
+ break;
+ case CMD.Q:
+ bbox.fromQuadratic(
+ xi, yi, data[i++], data[i++], data[i], data[i + 1],
+ min2, max2
+ );
+ xi = data[i++];
+ yi = data[i++];
+ break;
+ case CMD.A:
+ // TODO Arc 判断的开销比较大
+ var cx = data[i++];
+ var cy = data[i++];
+ var rx = data[i++];
+ var ry = data[i++];
+ var startAngle = data[i++];
+ var endAngle = data[i++] + startAngle;
+ // TODO Arc 旋转
+ var psi = data[i++];
+ var anticlockwise = 1 - data[i++];
+
+ if (i == 1) {
+ // 直接使用 arc 命令
+ // 第一个命令起点还未定义
+ x0 = mathCos(startAngle) * rx + cx;
+ y0 = mathSin(startAngle) * ry + cy;
+ }
+
+ bbox.fromArc(
+ cx, cy, rx, ry, startAngle, endAngle,
+ anticlockwise, min2, max2
+ );
+
+ xi = mathCos(endAngle) * rx + cx;
+ yi = mathSin(endAngle) * ry + cy;
+ break;
+ case CMD.R:
+ x0 = xi = data[i++];
+ y0 = yi = data[i++];
+ var width = data[i++];
+ var height = data[i++];
+ // Use fromLine
+ bbox.fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
+ break;
+ case CMD.Z:
+ xi = x0;
+ yi = y0;
+ break;
+ }
+
+ // Union
+ vec2.min(min, min, min2);
+ vec2.max(max, max, max2);
+ }
+
+ // No data
+ if (i === 0) {
+ min[0] = min[1] = max[0] = max[1] = 0;
+ }
+
+ return new BoundingRect(
+ min[0], min[1], max[0] - min[0], max[1] - min[1]
+ );
+ },
+
+ /**
+ * Rebuild path from current data
+ * Rebuild path will not consider javascript implemented line dash.
+ * @param {CanvasRenderingContext} ctx
+ */
+ rebuildPath: function (ctx) {
+ var d = this.data;
+ var x0, y0;
+ var xi, yi;
+ var x, y;
+ var ux = this._ux;
+ var uy = this._uy;
+ var len = this._len;
+ for (var i = 0; i < len;) {
+ var cmd = d[i++];
+
+ if (i == 1) {
+ // 如果第一个命令是 L, C, Q
+ // 则 previous point 同绘制命令的第一个 point
+ //
+ // 第一个命令为 Arc 的情况下会在后面特殊处理
+ xi = d[i];
+ yi = d[i + 1];
+
+ x0 = xi;
+ y0 = yi;
+ }
+ switch (cmd) {
+ case CMD.M:
+ x0 = xi = d[i++];
+ y0 = yi = d[i++];
+ ctx.moveTo(xi, yi);
+ break;
+ case CMD.L:
+ x = d[i++];
+ y = d[i++];
+ // Not draw too small seg between
+ if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len - 1) {
+ ctx.lineTo(x, y);
+ xi = x;
+ yi = y;
+ }
+ break;
+ case CMD.C:
+ ctx.bezierCurveTo(
+ d[i++], d[i++], d[i++], d[i++], d[i++], d[i++]
+ );
+ xi = d[i - 2];
+ yi = d[i - 1];
+ break;
+ case CMD.Q:
+ ctx.quadraticCurveTo(d[i++], d[i++], d[i++], d[i++]);
+ xi = d[i - 2];
+ yi = d[i - 1];
+ break;
+ case CMD.A:
+ var cx = d[i++];
+ var cy = d[i++];
+ var rx = d[i++];
+ var ry = d[i++];
+ var theta = d[i++];
+ var dTheta = d[i++];
+ var psi = d[i++];
+ var fs = d[i++];
+ var r = (rx > ry) ? rx : ry;
+ var scaleX = (rx > ry) ? 1 : rx / ry;
+ var scaleY = (rx > ry) ? ry / rx : 1;
+ var isEllipse = Math.abs(rx - ry) > 1e-3;
+ var endAngle = theta + dTheta;
+ if (isEllipse) {
+ ctx.translate(cx, cy);
+ ctx.rotate(psi);
+ ctx.scale(scaleX, scaleY);
+ ctx.arc(0, 0, r, theta, endAngle, 1 - fs);
+ ctx.scale(1 / scaleX, 1 / scaleY);
+ ctx.rotate(-psi);
+ ctx.translate(-cx, -cy);
+ }
+ else {
+ ctx.arc(cx, cy, r, theta, endAngle, 1 - fs);
+ }
+
+ if (i == 1) {
+ // 直接使用 arc 命令
+ // 第一个命令起点还未定义
+ x0 = mathCos(theta) * rx + cx;
+ y0 = mathSin(theta) * ry + cy;
+ }
+ xi = mathCos(endAngle) * rx + cx;
+ yi = mathSin(endAngle) * ry + cy;
+ break;
+ case CMD.R:
+ x0 = xi = d[i];
+ y0 = yi = d[i + 1];
+ ctx.rect(d[i++], d[i++], d[i++], d[i++]);
+ break;
+ case CMD.Z:
+ ctx.closePath();
+ xi = x0;
+ yi = y0;
+ }
+ }
+ }
+ };
+
+ PathProxy.CMD = CMD;
+
+ module.exports = PathProxy;
+
+
+/***/ },
+/* 37 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 曲线辅助模块
+ * @module zrender/core/curve
+ * @author pissang(https://www.github.com/pissang)
+ */
+
+
+ var vec2 = __webpack_require__(10);
+ var v2Create = vec2.create;
+ var v2DistSquare = vec2.distSquare;
+ var mathPow = Math.pow;
+ var mathSqrt = Math.sqrt;
+
+ var EPSILON = 1e-8;
+ var EPSILON_NUMERIC = 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.} 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.} 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.} 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.} [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_NUMERIC) {
+ break;
+ }
+ prev = t - interval;
+ next = t + interval;
+ // t - interval
+ _v1[0] = cubicAt(x0, x1, x2, x3, prev);
+ _v1[1] = cubicAt(y0, y1, y2, y3, prev);
+
+ d1 = 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.} 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.} 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.} 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_NUMERIC) {
+ 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);
+ }
+
+ module.exports = {
+
+ cubicAt: cubicAt,
+
+ cubicDerivativeAt: cubicDerivativeAt,
+
+ cubicRootAt: cubicRootAt,
+
+ cubicExtrema: cubicExtrema,
+
+ cubicSubdivide: cubicSubdivide,
+
+ cubicProjectPoint: cubicProjectPoint,
+
+ quadraticAt: quadraticAt,
+
+ quadraticDerivativeAt: quadraticDerivativeAt,
+
+ quadraticRootAt: quadraticRootAt,
+
+ quadraticExtremum: quadraticExtremum,
+
+ quadraticSubdivide: quadraticSubdivide,
+
+ quadraticProjectPoint: quadraticProjectPoint
+ };
+
+
+/***/ },
+/* 38 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @author Yi Shen(https://github.com/pissang)
+ */
+
+
+ var vec2 = __webpack_require__(10);
+ var curve = __webpack_require__(37);
+
+ 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} 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.} min
+ * @param {Array.} 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);
+ };
+
+ var xDim = [];
+ var yDim = [];
+ /**
+ * 从三阶贝塞尔曲线(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.} min
+ * @param {Array.} max
+ */
+ bbox.fromCubic = function(
+ x0, y0, x1, y1, x2, y2, x3, y3, min, max
+ ) {
+ var cubicExtrema = curve.cubicExtrema;
+ var cubicAt = curve.cubicAt;
+ var i;
+ var n = cubicExtrema(x0, x1, x2, x3, xDim);
+ min[0] = Infinity;
+ min[1] = Infinity;
+ max[0] = -Infinity;
+ max[1] = -Infinity;
+
+ for (i = 0; i < n; i++) {
+ var x = cubicAt(x0, x1, x2, x3, xDim[i]);
+ min[0] = mathMin(x, min[0]);
+ max[0] = mathMax(x, max[0]);
+ }
+ n = cubicExtrema(y0, y1, y2, y3, yDim);
+ for (i = 0; i < n; i++) {
+ var y = cubicAt(y0, y1, y2, y3, yDim[i]);
+ min[1] = mathMin(y, min[1]);
+ max[1] = mathMax(y, max[1]);
+ }
+
+ min[0] = mathMin(x0, min[0]);
+ max[0] = mathMax(x0, max[0]);
+ min[0] = mathMin(x3, min[0]);
+ max[0] = mathMax(x3, max[0]);
+
+ min[1] = mathMin(y0, min[1]);
+ max[1] = mathMax(y0, max[1]);
+ min[1] = mathMin(y3, min[1]);
+ max[1] = mathMax(y3, max[1]);
+ };
+
+ /**
+ * 从二阶贝塞尔曲线(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.} min
+ * @param {Array.} 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.} min
+ * @param {Array.} max
+ */
+ bbox.fromArc = function (
+ x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max
+ ) {
+ var vec2Min = vec2.min;
+ var vec2Max = vec2.max;
+
+ var diff = Math.abs(startAngle - endAngle);
+
+
+ if (diff % PI2 < 1e-4 && diff > 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);
+ }
+ }
+ };
+
+ module.exports = bbox;
+
+
+
+/***/ },
+/* 39 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var CMD = __webpack_require__(36).CMD;
+ var line = __webpack_require__(40);
+ var cubic = __webpack_require__(41);
+ var quadratic = __webpack_require__(42);
+ var arc = __webpack_require__(43);
+ var normalizeRadian = __webpack_require__(44).normalizeRadian;
+ var curve = __webpack_require__(37);
+
+ var windingLine = __webpack_require__(45);
+
+ var containStroke = line.containStroke;
+
+ var PI2 = Math.PI * 2;
+
+ var EPSILON = 1e-4;
+
+ function isAroundEqual(a, b) {
+ return Math.abs(a - b) < EPSILON;
+ }
+
+ // 临时数组
+ var roots = [-1, -1, -1];
+ var extrema = [-1, -1];
+
+ function swapExtrema() {
+ var tmp = extrema[0];
+ extrema[0] = extrema[1];
+ extrema[1] = tmp;
+ }
+
+ function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) {
+ // Quick reject
+ if (
+ (y > y0 && y > y1 && y > y2 && y > y3)
+ || (y < y0 && y < y1 && y < y2 && y < y3)
+ ) {
+ return 0;
+ }
+ var nRoots = curve.cubicRootAt(y0, y1, y2, y3, y, roots);
+ if (nRoots === 0) {
+ return 0;
+ }
+ else {
+ var w = 0;
+ var nExtrema = -1;
+ var y0_, y1_;
+ for (var i = 0; i < nRoots; i++) {
+ var t = roots[i];
+
+ // Avoid winding error when intersection point is the connect point of two line of polygon
+ var unit = (t === 0 || t === 1) ? 0.5 : 1;
+
+ var x_ = curve.cubicAt(x0, x1, x2, x3, t);
+ if (x_ < x) { // Quick reject
+ continue;
+ }
+ if (nExtrema < 0) {
+ nExtrema = curve.cubicExtrema(y0, y1, y2, y3, extrema);
+ if (extrema[1] < extrema[0] && nExtrema > 1) {
+ swapExtrema();
+ }
+ y0_ = curve.cubicAt(y0, y1, y2, y3, extrema[0]);
+ if (nExtrema > 1) {
+ y1_ = curve.cubicAt(y0, y1, y2, y3, extrema[1]);
+ }
+ }
+ if (nExtrema == 2) {
+ // 分成三段单调函数
+ if (t < extrema[0]) {
+ w += y0_ < y0 ? unit : -unit;
+ }
+ else if (t < extrema[1]) {
+ w += y1_ < y0_ ? unit : -unit;
+ }
+ else {
+ w += y3 < y1_ ? unit : -unit;
+ }
+ }
+ else {
+ // 分成两段单调函数
+ if (t < extrema[0]) {
+ w += y0_ < y0 ? unit : -unit;
+ }
+ else {
+ w += y3 < y0_ ? unit : -unit;
+ }
+ }
+ }
+ return w;
+ }
+ }
+
+ function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) {
+ // Quick reject
+ if (
+ (y > y0 && y > y1 && y > y2)
+ || (y < y0 && y < y1 && y < y2)
+ ) {
+ return 0;
+ }
+ var nRoots = curve.quadraticRootAt(y0, y1, y2, y, roots);
+ if (nRoots === 0) {
+ return 0;
+ }
+ else {
+ var t = curve.quadraticExtremum(y0, y1, y2);
+ if (t >= 0 && t <= 1) {
+ var w = 0;
+ var y_ = curve.quadraticAt(y0, y1, y2, t);
+ for (var i = 0; i < nRoots; i++) {
+ // Remove one endpoint.
+ var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1;
+
+ var x_ = curve.quadraticAt(x0, x1, x2, roots[i]);
+ if (x_ < x) { // Quick reject
+ continue;
+ }
+ if (roots[i] < t) {
+ w += y_ < y0 ? unit : -unit;
+ }
+ else {
+ w += y2 < y_ ? unit : -unit;
+ }
+ }
+ return w;
+ }
+ else {
+ // Remove one endpoint.
+ var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1;
+
+ var x_ = curve.quadraticAt(x0, x1, x2, roots[0]);
+ if (x_ < x) { // Quick reject
+ return 0;
+ }
+ return y2 < y0 ? unit : -unit;
+ }
+ }
+ }
+
+ // TODO
+ // Arc 旋转
+ function windingArc(
+ cx, cy, r, startAngle, endAngle, anticlockwise, x, y
+ ) {
+ y -= cy;
+ if (y > r || y < -r) {
+ return 0;
+ }
+ var tmp = Math.sqrt(r * r - y * y);
+ roots[0] = -tmp;
+ roots[1] = tmp;
+
+ var diff = Math.abs(startAngle - endAngle);
+ if (diff < 1e-4) {
+ return 0;
+ }
+ if (diff % PI2 < 1e-4) {
+ // Is a circle
+ startAngle = 0;
+ endAngle = PI2;
+ var dir = anticlockwise ? 1 : -1;
+ if (x >= roots[0] + cx && x <= roots[1] + cx) {
+ return dir;
+ } else {
+ return 0;
+ }
+ }
+
+ if (anticlockwise) {
+ var tmp = startAngle;
+ startAngle = normalizeRadian(endAngle);
+ endAngle = normalizeRadian(tmp);
+ }
+ else {
+ startAngle = normalizeRadian(startAngle);
+ endAngle = normalizeRadian(endAngle);
+ }
+ if (startAngle > endAngle) {
+ endAngle += PI2;
+ }
+
+ var w = 0;
+ for (var i = 0; i < 2; i++) {
+ var x_ = roots[i];
+ if (x_ + cx > x) {
+ var angle = Math.atan2(y, x_);
+ var dir = anticlockwise ? 1 : -1;
+ if (angle < 0) {
+ angle = PI2 + angle;
+ }
+ if (
+ (angle >= startAngle && angle <= endAngle)
+ || (angle + PI2 >= startAngle && angle + PI2 <= endAngle)
+ ) {
+ if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
+ dir = -dir;
+ }
+ w += dir;
+ }
+ }
+ }
+ return w;
+ }
+
+ function containPath(data, lineWidth, isStroke, x, y) {
+ var w = 0;
+ var xi = 0;
+ var yi = 0;
+ var x0 = 0;
+ var y0 = 0;
+
+ for (var i = 0; i < data.length;) {
+ var cmd = data[i++];
+ // Begin a new subpath
+ if (cmd === CMD.M && i > 1) {
+ // Close previous subpath
+ if (!isStroke) {
+ w += windingLine(xi, yi, x0, y0, x, y);
+ }
+ // 如果被任何一个 subpath 包含
+ // if (w !== 0) {
+ // return true;
+ // }
+ }
+
+ if (i == 1) {
+ // 如果第一个命令是 L, C, Q
+ // 则 previous point 同绘制命令的第一个 point
+ //
+ // 第一个命令为 Arc 的情况下会在后面特殊处理
+ xi = data[i];
+ yi = data[i + 1];
+
+ x0 = xi;
+ y0 = yi;
+ }
+
+ switch (cmd) {
+ case CMD.M:
+ // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点
+ // 在 closePath 的时候使用
+ x0 = data[i++];
+ y0 = data[i++];
+ xi = x0;
+ yi = y0;
+ break;
+ case CMD.L:
+ if (isStroke) {
+ if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) {
+ return true;
+ }
+ }
+ else {
+ // NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN
+ w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0;
+ }
+ xi = data[i++];
+ yi = data[i++];
+ break;
+ case CMD.C:
+ if (isStroke) {
+ if (cubic.containStroke(xi, yi,
+ data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
+ lineWidth, x, y
+ )) {
+ return true;
+ }
+ }
+ else {
+ w += windingCubic(
+ xi, yi,
+ data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
+ x, y
+ ) || 0;
+ }
+ xi = data[i++];
+ yi = data[i++];
+ break;
+ case CMD.Q:
+ if (isStroke) {
+ if (quadratic.containStroke(xi, yi,
+ data[i++], data[i++], data[i], data[i + 1],
+ lineWidth, x, y
+ )) {
+ return true;
+ }
+ }
+ else {
+ w += windingQuadratic(
+ xi, yi,
+ data[i++], data[i++], data[i], data[i + 1],
+ x, y
+ ) || 0;
+ }
+ xi = data[i++];
+ yi = data[i++];
+ break;
+ case CMD.A:
+ // TODO Arc 判断的开销比较大
+ var cx = data[i++];
+ var cy = data[i++];
+ var rx = data[i++];
+ var ry = data[i++];
+ var theta = data[i++];
+ var dTheta = data[i++];
+ // TODO Arc 旋转
+ var psi = data[i++];
+ var anticlockwise = 1 - data[i++];
+ var x1 = Math.cos(theta) * rx + cx;
+ var y1 = Math.sin(theta) * ry + cy;
+ // 不是直接使用 arc 命令
+ if (i > 1) {
+ w += windingLine(xi, yi, x1, y1, x, y);
+ }
+ else {
+ // 第一个命令起点还未定义
+ x0 = x1;
+ y0 = y1;
+ }
+ // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放
+ var _x = (x - cx) * ry / rx + cx;
+ if (isStroke) {
+ if (arc.containStroke(
+ cx, cy, ry, theta, theta + dTheta, anticlockwise,
+ lineWidth, _x, y
+ )) {
+ return true;
+ }
+ }
+ else {
+ w += windingArc(
+ cx, cy, ry, theta, theta + dTheta, anticlockwise,
+ _x, y
+ );
+ }
+ xi = Math.cos(theta + dTheta) * rx + cx;
+ yi = Math.sin(theta + dTheta) * ry + cy;
+ break;
+ case CMD.R:
+ x0 = xi = data[i++];
+ y0 = yi = data[i++];
+ var width = data[i++];
+ var height = data[i++];
+ var x1 = x0 + width;
+ var y1 = y0 + height;
+ if (isStroke) {
+ if (containStroke(x0, y0, x1, y0, lineWidth, x, y)
+ || containStroke(x1, y0, x1, y1, lineWidth, x, y)
+ || containStroke(x1, y1, x0, y1, lineWidth, x, y)
+ || containStroke(x0, y1, x0, y0, lineWidth, x, y)
+ ) {
+ return true;
+ }
+ }
+ else {
+ // FIXME Clockwise ?
+ w += windingLine(x1, y0, x1, y1, x, y);
+ w += windingLine(x0, y1, x0, y0, x, y);
+ }
+ break;
+ case CMD.Z:
+ if (isStroke) {
+ if (containStroke(
+ xi, yi, x0, y0, lineWidth, x, y
+ )) {
+ return true;
+ }
+ }
+ else {
+ // Close a subpath
+ w += windingLine(xi, yi, x0, y0, x, y);
+ // 如果被任何一个 subpath 包含
+ // FIXME subpaths may overlap
+ // if (w !== 0) {
+ // return true;
+ // }
+ }
+ xi = x0;
+ yi = y0;
+ break;
+ }
+ }
+ if (!isStroke && !isAroundEqual(yi, y0)) {
+ w += windingLine(xi, yi, x0, y0, x, y) || 0;
+ }
+ return w !== 0;
+ }
+
+ module.exports = {
+ contain: function (pathData, x, y) {
+ return containPath(pathData, 0, false, x, y);
+ },
+
+ containStroke: function (pathData, lineWidth, x, y) {
+ return containPath(pathData, lineWidth, true, x, y);
+ }
+ };
+
+
+/***/ },
+/* 40 */
+/***/ function(module, exports) {
+
+
+ module.exports = {
+ /**
+ * 线段包含判断
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} lineWidth
+ * @param {number} x
+ * @param {number} y
+ * @return {boolean}
+ */
+ containStroke: function (x0, y0, x1, y1, lineWidth, x, y) {
+ if (lineWidth === 0) {
+ return false;
+ }
+ var _l = lineWidth;
+ var _a = 0;
+ var _b = x0;
+ // Quick reject
+ if (
+ (y > y0 + _l && y > y1 + _l)
+ || (y < y0 - _l && y < y1 - _l)
+ || (x > x0 + _l && x > x1 + _l)
+ || (x < x0 - _l && x < x1 - _l)
+ ) {
+ return false;
+ }
+
+ if (x0 !== x1) {
+ _a = (y0 - y1) / (x0 - x1);
+ _b = (x0 * y1 - x1 * y0) / (x0 - x1) ;
+ }
+ else {
+ return Math.abs(x - x0) <= _l / 2;
+ }
+ var tmp = _a * x - y + _b;
+ var _s = tmp * tmp / (_a * _a + 1);
+ return _s <= _l / 2 * _l / 2;
+ }
+ };
+
+
+/***/ },
+/* 41 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var curve = __webpack_require__(37);
+
+ module.exports = {
+ /**
+ * 三次贝塞尔曲线描边包含判断
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} x2
+ * @param {number} y2
+ * @param {number} x3
+ * @param {number} y3
+ * @param {number} lineWidth
+ * @param {number} x
+ * @param {number} y
+ * @return {boolean}
+ */
+ containStroke: function(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) {
+ if (lineWidth === 0) {
+ return false;
+ }
+ var _l = lineWidth;
+ // Quick reject
+ if (
+ (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l)
+ || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l)
+ || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l)
+ || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)
+ ) {
+ return false;
+ }
+ var d = curve.cubicProjectPoint(
+ x0, y0, x1, y1, x2, y2, x3, y3,
+ x, y, null
+ );
+ return d <= _l / 2;
+ }
+ };
+
+
+/***/ },
+/* 42 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var curve = __webpack_require__(37);
+
+ module.exports = {
+ /**
+ * 二次贝塞尔曲线描边包含判断
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} x2
+ * @param {number} y2
+ * @param {number} lineWidth
+ * @param {number} x
+ * @param {number} y
+ * @return {boolean}
+ */
+ containStroke: function (x0, y0, x1, y1, x2, y2, lineWidth, x, y) {
+ if (lineWidth === 0) {
+ return false;
+ }
+ var _l = lineWidth;
+ // Quick reject
+ if (
+ (y > y0 + _l && y > y1 + _l && y > y2 + _l)
+ || (y < y0 - _l && y < y1 - _l && y < y2 - _l)
+ || (x > x0 + _l && x > x1 + _l && x > x2 + _l)
+ || (x < x0 - _l && x < x1 - _l && x < x2 - _l)
+ ) {
+ return false;
+ }
+ var d = curve.quadraticProjectPoint(
+ x0, y0, x1, y1, x2, y2,
+ x, y, null
+ );
+ return d <= _l / 2;
+ }
+ };
+
+
+/***/ },
+/* 43 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var normalizeRadian = __webpack_require__(44).normalizeRadian;
+ var PI2 = Math.PI * 2;
+
+ module.exports = {
+ /**
+ * 圆弧描边包含判断
+ * @param {number} cx
+ * @param {number} cy
+ * @param {number} r
+ * @param {number} startAngle
+ * @param {number} endAngle
+ * @param {boolean} anticlockwise
+ * @param {number} lineWidth
+ * @param {number} x
+ * @param {number} y
+ * @return {Boolean}
+ */
+ containStroke: function (
+ cx, cy, r, startAngle, endAngle, anticlockwise,
+ lineWidth, x, y
+ ) {
+
+ if (lineWidth === 0) {
+ return false;
+ }
+ var _l = lineWidth;
+
+ x -= cx;
+ y -= cy;
+ var d = Math.sqrt(x * x + y * y);
+
+ if ((d - _l > r) || (d + _l < r)) {
+ return false;
+ }
+ if (Math.abs(startAngle - endAngle) % PI2 < 1e-4) {
+ // Is a circle
+ return true;
+ }
+ if (anticlockwise) {
+ var tmp = startAngle;
+ startAngle = normalizeRadian(endAngle);
+ endAngle = normalizeRadian(tmp);
+ } else {
+ startAngle = normalizeRadian(startAngle);
+ endAngle = normalizeRadian(endAngle);
+ }
+ if (startAngle > endAngle) {
+ endAngle += PI2;
+ }
+
+ var angle = Math.atan2(y, x);
+ if (angle < 0) {
+ angle += PI2;
+ }
+ return (angle >= startAngle && angle <= endAngle)
+ || (angle + PI2 >= startAngle && angle + PI2 <= endAngle);
+ }
+ };
+
+
+/***/ },
+/* 44 */
+/***/ function(module, exports) {
+
+
+
+ var PI2 = Math.PI * 2;
+ module.exports = {
+ normalizeRadian: function(angle) {
+ angle %= PI2;
+ if (angle < 0) {
+ angle += PI2;
+ }
+ return angle;
+ }
+ };
+
+
+/***/ },
+/* 45 */
+/***/ function(module, exports) {
+
+
+ module.exports = function windingLine(x0, y0, x1, y1, x, y) {
+ if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
+ return 0;
+ }
+ // Ignore horizontal line
+ if (y1 === y0) {
+ return 0;
+ }
+ var dir = y1 < y0 ? 1 : -1;
+ var t = (y - y0) / (y1 - y0);
+
+ // Avoid winding error when intersection point is the connect point of two line of polygon
+ if (t === 1 || t === 0) {
+ dir = y1 < y0 ? 0.5 : -0.5;
+ }
+
+ var x_ = t * (x1 - x0) + x0;
+
+ return x_ > x ? dir : 0;
+ };
+
+
+/***/ },
+/* 46 */
+/***/ function(module, exports) {
+
+
+
+ var Pattern = function (image, repeat) {
+ // Should do nothing more in this constructor. Because gradient can be
+ // declard by `color: {image: ...}`, where this constructor will not be called.
+
+ this.image = image;
+ this.repeat = repeat;
+
+ // Can be cloned
+ this.type = 'pattern';
+ };
+
+ Pattern.prototype.getCanvasPattern = function (ctx) {
+ return ctx.createPattern(this.image, this.repeat || 'repeat');
+ };
+
+ module.exports = Pattern;
+
+
+/***/ },
+/* 47 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var CMD = __webpack_require__(36).CMD;
+ var vec2 = __webpack_require__(10);
+ var v2ApplyTransform = vec2.applyTransform;
+
+ var points = [[], [], []];
+ var mathSqrt = Math.sqrt;
+ var mathAtan2 = Math.atan2;
+ function transformPath(path, m) {
+ var data = path.data;
+ var cmd;
+ var nPoint;
+ var i;
+ var j;
+ var k;
+ var p;
+
+ var M = CMD.M;
+ var C = CMD.C;
+ var L = CMD.L;
+ var R = CMD.R;
+ var A = CMD.A;
+ var Q = CMD.Q;
+
+ for (i = 0, j = 0; i < data.length;) {
+ cmd = data[i++];
+ j = i;
+ nPoint = 0;
+
+ switch (cmd) {
+ case M:
+ nPoint = 1;
+ break;
+ case L:
+ nPoint = 1;
+ break;
+ case C:
+ nPoint = 3;
+ break;
+ case Q:
+ nPoint = 2;
+ break;
+ case A:
+ var x = m[4];
+ var y = m[5];
+ var sx = mathSqrt(m[0] * m[0] + m[1] * m[1]);
+ var sy = mathSqrt(m[2] * m[2] + m[3] * m[3]);
+ var angle = mathAtan2(-m[1] / sy, m[0] / sx);
+ // cx
+ data[i] *= sx;
+ data[i++] += x;
+ // cy
+ data[i] *= sy;
+ data[i++] += y;
+ // Scale rx and ry
+ // FIXME Assume psi is 0 here
+ data[i++] *= sx;
+ data[i++] *= sy;
+
+ // Start angle
+ data[i++] += angle;
+ // end angle
+ data[i++] += angle;
+ // FIXME psi
+ i += 2;
+ j = i;
+ break;
+ case R:
+ // x0, y0
+ p[0] = data[i++];
+ p[1] = data[i++];
+ v2ApplyTransform(p, p, m);
+ data[j++] = p[0];
+ data[j++] = p[1];
+ // x1, y1
+ p[0] += data[i++];
+ p[1] += data[i++];
+ v2ApplyTransform(p, p, m);
+ data[j++] = p[0];
+ data[j++] = p[1];
+ }
+
+ for (k = 0; k < nPoint; k++) {
+ var p = points[k];
+ p[0] = data[i++];
+ p[1] = data[i++];
+
+ v2ApplyTransform(p, p, m);
+ // Write back
+ data[j++] = p[0];
+ data[j++] = p[1];
+ }
+ }
+ }
+
+ module.exports = transformPath;
+
+
+/***/ },
+/* 48 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上
+ * @module zrender/graphic/Group
+ * @example
+ * var Group = require('zrender/lib/container/Group');
+ * var Circle = require('zrender/lib/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);
+ */
+
+
+ var zrUtil = __webpack_require__(4);
+ var Element = __webpack_require__(23);
+ var BoundingRect = __webpack_require__(9);
+
+ /**
+ * @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) {
+ if (opts.hasOwnProperty(key)) {
+ this[key] = opts[key];
+ }
+ }
+
+ this._children = [];
+
+ this.__storage = null;
+
+ this.__dirty = true;
+ };
+
+ Group.prototype = {
+
+ constructor: Group,
+
+ isGroup: true,
+
+ /**
+ * @type {string}
+ */
+ type: 'group',
+
+ /**
+ * 所有子孙元素是否响应鼠标事件
+ * @name module:/zrender/container/Group#silent
+ * @type {boolean}
+ * @default false
+ */
+ silent: false,
+
+ /**
+ * @return {Array.}
+ */
+ children: function () {
+ return this._children.slice();
+ },
+
+ /**
+ * 获取指定 index 的儿子节点
+ * @param {number} idx
+ * @return {module:zrender/Element}
+ */
+ childAt: function (idx) {
+ return this._children[idx];
+ },
+
+ /**
+ * 获取指定名字的儿子节点
+ * @param {string} name
+ * @return {module:zrender/Element}
+ */
+ childOfName: function (name) {
+ var children = this._children;
+ for (var i = 0; i < children.length; i++) {
+ if (children[i].name === name) {
+ return children[i];
+ }
+ }
+ },
+
+ /**
+ * @return {number}
+ */
+ childCount: function () {
+ return this._children.length;
+ },
+
+ /**
+ * 添加子节点到最后
+ * @param {module:zrender/Element} child
+ */
+ add: function (child) {
+ if (child && child !== this && child.parent !== this) {
+
+ this._children.push(child);
+
+ this._doAdd(child);
+ }
+
+ return this;
+ },
+
+ /**
+ * 添加子节点在 nextSibling 之前
+ * @param {module:zrender/Element} child
+ * @param {module:zrender/Element} nextSibling
+ */
+ addBefore: function (child, nextSibling) {
+ if (child && child !== this && child.parent !== this
+ && nextSibling && nextSibling.parent === this) {
+
+ var children = this._children;
+ var idx = children.indexOf(nextSibling);
+
+ if (idx >= 0) {
+ children.splice(idx, 0, child);
+ this._doAdd(child);
+ }
+ }
+
+ return this;
+ },
+
+ _doAdd: function (child) {
+ if (child.parent) {
+ child.parent.remove(child);
+ }
+
+ child.parent = this;
+
+ var storage = this.__storage;
+ var zr = this.__zr;
+ if (storage && storage !== child.__storage) {
+
+ storage.addToStorage(child);
+
+ if (child instanceof Group) {
+ child.addChildrenToStorage(storage);
+ }
+ }
+
+ zr && zr.refresh();
+ },
+
+ /**
+ * 移除子节点
+ * @param {module:zrender/Element} child
+ */
+ remove: function (child) {
+ var zr = this.__zr;
+ var storage = this.__storage;
+ var children = this._children;
+
+ var idx = zrUtil.indexOf(children, child);
+ if (idx < 0) {
+ return this;
+ }
+ children.splice(idx, 1);
+
+ child.parent = null;
+
+ if (storage) {
+
+ storage.delFromStorage(child);
+
+ if (child instanceof Group) {
+ child.delChildrenFromStorage(storage);
+ }
+ }
+
+ zr && zr.refresh();
+
+ return this;
+ },
+
+ /**
+ * 移除所有子节点
+ */
+ removeAll: function () {
+ var children = this._children;
+ var storage = this.__storage;
+ var child;
+ var i;
+ for (i = 0; i < children.length; i++) {
+ child = children[i];
+ if (storage) {
+ storage.delFromStorage(child);
+ if (child instanceof Group) {
+ child.delChildrenFromStorage(storage);
+ }
+ }
+ child.parent = null;
+ }
+ children.length = 0;
+
+ return this;
+ },
+
+ /**
+ * 遍历所有子节点
+ * @param {Function} cb
+ * @param {} context
+ */
+ eachChild: function (cb, context) {
+ var children = this._children;
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ cb.call(context, child, i);
+ }
+ return this;
+ },
+
+ /**
+ * 深度优先遍历所有子孙节点
+ * @param {Function} cb
+ * @param {} context
+ */
+ traverse: function (cb, context) {
+ for (var i = 0; i < this._children.length; i++) {
+ var child = this._children[i];
+ cb.call(context, child);
+
+ if (child.type === 'group') {
+ child.traverse(cb, context);
+ }
+ }
+ return this;
+ },
+
+ addChildrenToStorage: function (storage) {
+ for (var i = 0; i < this._children.length; i++) {
+ var child = this._children[i];
+ storage.addToStorage(child);
+ if (child instanceof Group) {
+ child.addChildrenToStorage(storage);
+ }
+ }
+ },
+
+ delChildrenFromStorage: function (storage) {
+ for (var i = 0; i < this._children.length; i++) {
+ var child = this._children[i];
+ storage.delFromStorage(child);
+ if (child instanceof Group) {
+ child.delChildrenFromStorage(storage);
+ }
+ }
+ },
+
+ dirty: function () {
+ this.__dirty = true;
+ this.__zr && this.__zr.refresh();
+ return this;
+ },
+
+ /**
+ * @return {module:zrender/core/BoundingRect}
+ */
+ getBoundingRect: function (includeChildren) {
+ // TODO Caching
+ 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);
+ // TODO
+ // The boundingRect cacluated by transforming original
+ // rect may be bigger than the actual bundingRect when rotation
+ // is used. (Consider a circle rotated aginst its center, where
+ // the actual boundingRect should be the same as that not be
+ // rotated.) But we can not find better approach to calculate
+ // actual boundingRect yet, considering performance.
+ if (transform) {
+ tmpRect.copy(childRect);
+ tmpRect.applyTransform(transform);
+ rect = rect || tmpRect.clone();
+ rect.union(tmpRect);
+ }
+ else {
+ rect = rect || childRect.clone();
+ rect.union(childRect);
+ }
+ }
+ return rect || tmpRect;
+ }
+ };
+
+ zrUtil.inherits(Group, Element);
+
+ module.exports = Group;
+
+
+/***/ },
+/* 49 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Image element
+ * @module zrender/graphic/Image
+ */
+
+
+
+ var Displayable = __webpack_require__(21);
+ var BoundingRect = __webpack_require__(9);
+ var zrUtil = __webpack_require__(4);
+
+ var LRU = __webpack_require__(32);
+ var globalImageCache = new LRU(50);
+ /**
+ * @alias zrender/graphic/Image
+ * @extends module:zrender/graphic/Displayable
+ * @constructor
+ * @param {Object} opts
+ */
+ function ZImage(opts) {
+ Displayable.call(this, opts);
+ }
+
+ ZImage.prototype = {
+
+ constructor: ZImage,
+
+ type: 'image',
+
+ brush: function (ctx, prevEl) {
+ var style = this.style;
+ var src = style.image;
+ var image;
+
+ // Must bind each time
+ style.bind(ctx, this, prevEl);
+ // style.image is a url string
+ if (typeof src === 'string') {
+ image = this._image;
+ }
+ // style.image is an HTMLImageElement or HTMLCanvasElement or Canvas
+ else {
+ image = src;
+ }
+ // FIXME Case create many images with src
+ if (!image && src) {
+ // Try get from global image cache
+ var cachedImgObj = globalImageCache.get(src);
+ if (!cachedImgObj) {
+ // Create a new image
+ image = new Image();
+ image.onload = function () {
+ image.onload = null;
+ for (var i = 0; i < cachedImgObj.pending.length; i++) {
+ cachedImgObj.pending[i].dirty();
+ }
+ };
+ cachedImgObj = {
+ image: image,
+ pending: [this]
+ };
+ image.src = src;
+ globalImageCache.put(src, cachedImgObj);
+ this._image = image;
+ return;
+ }
+ else {
+ image = cachedImgObj.image;
+ this._image = image;
+ // Image is not complete finish, add to pending list
+ if (!image.width || !image.height) {
+ cachedImgObj.pending.push(this);
+ return;
+ }
+ }
+ }
+
+ if (image) {
+ // 图片已经加载完成
+ // if (image.nodeName.toUpperCase() == 'IMG') {
+ // if (!image.complete) {
+ // return;
+ // }
+ // }
+ // Else is canvas
+
+ var x = style.x || 0;
+ var y = style.y || 0;
+ // 图片加载失败
+ if (!image.width || !image.height) {
+ return;
+ }
+ var width = style.width;
+ var height = style.height;
+ var aspect = image.width / image.height;
+ if (width == null && height != null) {
+ // Keep image/height ratio
+ width = height * aspect;
+ }
+ else if (height == null && width != null) {
+ height = width / aspect;
+ }
+ else if (width == null && height == null) {
+ width = image.width;
+ height = image.height;
+ }
+
+ // 设置transform
+ this.setTransform(ctx);
+
+ if (style.sWidth && style.sHeight) {
+ var sx = style.sx || 0;
+ var sy = style.sy || 0;
+ ctx.drawImage(
+ image,
+ sx, sy, style.sWidth, style.sHeight,
+ x, y, width, height
+ );
+ }
+ else if (style.sx && style.sy) {
+ var sx = style.sx;
+ var sy = style.sy;
+ var sWidth = width - sx;
+ var sHeight = height - sy;
+ ctx.drawImage(
+ image,
+ sx, sy, sWidth, sHeight,
+ x, y, width, height
+ );
+ }
+ else {
+ ctx.drawImage(image, x, y, width, height);
+ }
+
+ this.restoreTransform(ctx);
+
+ // Draw rect text
+ if (style.text != null) {
+ this.drawRectText(ctx, this.getBoundingRect());
+ }
+
+ }
+ },
+
+ getBoundingRect: function () {
+ var style = this.style;
+ if (! this._rect) {
+ this._rect = new BoundingRect(
+ style.x || 0, style.y || 0, style.width || 0, style.height || 0
+ );
+ }
+ return this._rect;
+ }
+ };
+
+ zrUtil.inherits(ZImage, Displayable);
+
+ module.exports = ZImage;
+
+
+/***/ },
+/* 50 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Text element
+ * @module zrender/graphic/Text
+ *
+ * TODO Wrapping
+ *
+ * Text not support gradient
+ */
+
+
+
+ var Displayable = __webpack_require__(21);
+ var zrUtil = __webpack_require__(4);
+ var textContain = __webpack_require__(8);
+
+ /**
+ * @alias zrender/graphic/Text
+ * @extends module:zrender/graphic/Displayable
+ * @constructor
+ * @param {Object} opts
+ */
+ var Text = function (opts) {
+ Displayable.call(this, opts);
+ };
+
+ Text.prototype = {
+
+ constructor: Text,
+
+ type: 'text',
+
+ brush: function (ctx, prevEl) {
+ var style = this.style;
+ var x = style.x || 0;
+ var y = style.y || 0;
+ // Convert to string
+ var text = style.text;
+
+ // Convert to string
+ text != null && (text += '');
+
+ // Always bind style
+ style.bind(ctx, this, prevEl);
+
+ if (text) {
+
+ this.setTransform(ctx);
+
+ var textBaseline;
+ var textAlign = style.textAlign;
+ var font = style.textFont || style.font;
+ if (style.textVerticalAlign) {
+ var rect = textContain.getBoundingRect(
+ text, font, style.textAlign, 'top'
+ );
+ // Ignore textBaseline
+ textBaseline = 'middle';
+ switch (style.textVerticalAlign) {
+ case 'middle':
+ y -= rect.height / 2 - rect.lineHeight / 2;
+ break;
+ case 'bottom':
+ y -= rect.height - rect.lineHeight / 2;
+ break;
+ default:
+ y += rect.lineHeight / 2;
+ }
+ }
+ else {
+ textBaseline = style.textBaseline;
+ }
+
+ // TODO Invalid font
+ ctx.font = font || '12px sans-serif';
+ ctx.textAlign = textAlign || 'left';
+ // Use canvas default left textAlign. Giving invalid value will cause state not change
+ if (ctx.textAlign !== textAlign) {
+ ctx.textAlign = 'left';
+ }
+ // FIXME in text contain default is top
+ ctx.textBaseline = textBaseline || 'alphabetic';
+ // Use canvas default alphabetic baseline
+ if (ctx.textBaseline !== textBaseline) {
+ ctx.textBaseline = 'alphabetic';
+ }
+
+ var lineHeight = textContain.measureText('国', ctx.font).width;
+
+ var textLines = text.split('\n');
+ for (var i = 0; i < textLines.length; i++) {
+ // Fill after stroke so the outline will not cover the main part.
+ style.hasStroke() && ctx.strokeText(textLines[i], x, y);
+ style.hasFill() && ctx.fillText(textLines[i], x, y);
+ y += lineHeight;
+ }
+
+ this.restoreTransform(ctx);
+ }
+ },
+
+ getBoundingRect: function () {
+ var style = this.style;
+ if (!this._rect) {
+ var textVerticalAlign = style.textVerticalAlign;
+ var rect = textContain.getBoundingRect(
+ style.text + '', style.textFont || style.font, style.textAlign,
+ textVerticalAlign ? 'top' : style.textBaseline
+ );
+ switch (textVerticalAlign) {
+ case 'middle':
+ rect.y -= rect.height / 2;
+ break;
+ case 'bottom':
+ rect.y -= rect.height;
+ break;
+ }
+ rect.x += style.x || 0;
+ rect.y += style.y || 0;
+ if (style.hasStroke()) {
+ var w = style.lineWidth;
+ rect.x -= w / 2;
+ rect.y -= w / 2;
+ rect.width += w;
+ rect.height += w;
+ }
+ this._rect = rect;
+ }
+
+ return this._rect;
+ }
+ };
+
+ zrUtil.inherits(Text, Displayable);
+
+ module.exports = Text;
+
+
+/***/ },
+/* 51 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 圆形
+ * @module zrender/shape/Circle
+ */
+
+
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'circle',
+
+ shape: {
+ cx: 0,
+ cy: 0,
+ r: 0
+ },
+
+
+ buildPath : function (ctx, shape, inBundle) {
+ // Better stroking in ShapeBundle
+ // Always do it may have performence issue ( fill may be 2x more cost)
+ if (inBundle) {
+ ctx.moveTo(shape.cx + shape.r, shape.cy);
+ }
+ // else {
+ // if (ctx.allocate && !ctx.data.length) {
+ // ctx.allocate(ctx.CMD_MEM_SIZE.A);
+ // }
+ // }
+ // Better stroking in ShapeBundle
+ // ctx.moveTo(shape.cx + shape.r, shape.cy);
+ ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true);
+ }
+ });
+
+
+
+/***/ },
+/* 52 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 扇形
+ * @module zrender/graphic/shape/Sector
+ */
+
+
+
+ var env = __webpack_require__(2);
+ var Path = __webpack_require__(20);
+
+ var shadowTemp = [
+ ['shadowBlur', 0],
+ ['shadowColor', '#000'],
+ ['shadowOffsetX', 0],
+ ['shadowOffsetY', 0]
+ ];
+
+ module.exports = Path.extend({
+
+ type: 'sector',
+
+ shape: {
+
+ cx: 0,
+
+ cy: 0,
+
+ r0: 0,
+
+ r: 0,
+
+ startAngle: 0,
+
+ endAngle: Math.PI * 2,
+
+ clockwise: true
+ },
+
+ brush: (env.browser.ie && env.browser.version >= 11) // version: '11.0'
+ // Fix weird bug in some version of IE11 (like 11.0.9600.17801),
+ // where exception "unexpected call to method or property access"
+ // might be thrown when calling ctx.fill after a path whose area size
+ // is zero is drawn and ctx.clip() is called and shadowBlur is set.
+ // (e.g.,
+ // ctx.moveTo(10, 10);
+ // ctx.lineTo(20, 10);
+ // ctx.closePath();
+ // ctx.clip();
+ // ctx.shadowBlur = 10;
+ // ...
+ // ctx.fill();
+ // )
+ ? function () {
+ var clipPaths = this.__clipPaths;
+ var style = this.style;
+ var modified;
+
+ if (clipPaths) {
+ for (var i = 0; i < clipPaths.length; i++) {
+ var shape = clipPaths[i] && clipPaths[i].shape;
+ if (shape && shape.startAngle === shape.endAngle) {
+ for (var j = 0; j < shadowTemp.length; j++) {
+ shadowTemp[j][2] = style[shadowTemp[j][0]];
+ style[shadowTemp[j][0]] = shadowTemp[j][1];
+ }
+ modified = true;
+ break;
+ }
+ }
+ }
+
+ Path.prototype.brush.apply(this, arguments);
+
+ if (modified) {
+ for (var j = 0; j < shadowTemp.length; j++) {
+ style[shadowTemp[j][0]] = shadowTemp[j][2];
+ }
+ }
+ }
+ : Path.prototype.brush,
+
+ buildPath: function (ctx, shape) {
+
+ var x = shape.cx;
+ var y = shape.cy;
+ var r0 = Math.max(shape.r0 || 0, 0);
+ var r = Math.max(shape.r, 0);
+ var startAngle = shape.startAngle;
+ var endAngle = shape.endAngle;
+ var clockwise = shape.clockwise;
+
+ var unitX = Math.cos(startAngle);
+ var unitY = Math.sin(startAngle);
+
+ ctx.moveTo(unitX * r0 + x, unitY * r0 + y);
+
+ ctx.lineTo(unitX * r + x, unitY * r + y);
+
+ ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
+
+ ctx.lineTo(
+ Math.cos(endAngle) * r0 + x,
+ Math.sin(endAngle) * r0 + y
+ );
+
+ if (r0 !== 0) {
+ ctx.arc(x, y, r0, endAngle, startAngle, clockwise);
+ }
+
+ ctx.closePath();
+ }
+ });
+
+
+
+/***/ },
+/* 53 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 圆环
+ * @module zrender/graphic/shape/Ring
+ */
+
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'ring',
+
+ shape: {
+ cx: 0,
+ cy: 0,
+ r: 0,
+ r0: 0
+ },
+
+ buildPath: function (ctx, shape) {
+ var x = shape.cx;
+ var y = shape.cy;
+ var PI2 = Math.PI * 2;
+ ctx.moveTo(x + shape.r, y);
+ ctx.arc(x, y, shape.r, 0, PI2, false);
+ ctx.moveTo(x + shape.r0, y);
+ ctx.arc(x, y, shape.r0, 0, PI2, true);
+ }
+ });
+
+
+
+/***/ },
+/* 54 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 多边形
+ * @module zrender/shape/Polygon
+ */
+
+
+ var polyHelper = __webpack_require__(55);
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'polygon',
+
+ shape: {
+ points: null,
+
+ smooth: false,
+
+ smoothConstraint: null
+ },
+
+ buildPath: function (ctx, shape) {
+ polyHelper.buildPath(ctx, shape, true);
+ }
+ });
+
+
+/***/ },
+/* 55 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var smoothSpline = __webpack_require__(56);
+ var smoothBezier = __webpack_require__(57);
+
+ module.exports = {
+ buildPath: function (ctx, shape, closePath) {
+ var points = shape.points;
+ var smooth = shape.smooth;
+ if (points && points.length >= 2) {
+ if (smooth && smooth !== 'spline') {
+ var controlPoints = smoothBezier(
+ points, smooth, closePath, shape.smoothConstraint
+ );
+
+ ctx.moveTo(points[0][0], points[0][1]);
+ var len = points.length;
+ for (var i = 0; i < (closePath ? len : len - 1); i++) {
+ var cp1 = controlPoints[i * 2];
+ var cp2 = controlPoints[i * 2 + 1];
+ var p = points[(i + 1) % len];
+ ctx.bezierCurveTo(
+ cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]
+ );
+ }
+ }
+ else {
+ if (smooth === 'spline') {
+ points = smoothSpline(points, closePath);
+ }
+
+ ctx.moveTo(points[0][0], points[0][1]);
+ for (var i = 1, l = points.length; i < l; i++) {
+ ctx.lineTo(points[i][0], points[i][1]);
+ }
+ }
+
+ closePath && ctx.closePath();
+ }
+ }
+ };
+
+
+/***/ },
+/* 56 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Catmull-Rom spline 插值折线
+ * @module zrender/shape/util/smoothSpline
+ * @author pissang (https://www.github.com/pissang)
+ * Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * errorrik (errorrik@gmail.com)
+ */
+
+ var vec2 = __webpack_require__(10);
+
+ /**
+ * @inner
+ */
+ function interpolate(p0, p1, p2, p3, t, t2, t3) {
+ var v0 = (p2 - p0) * 0.5;
+ var v1 = (p3 - p1) * 0.5;
+ return (2 * (p1 - p2) + v0 + v1) * t3
+ + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
+ + v0 * t + p1;
+ }
+
+ /**
+ * @alias module:zrender/shape/util/smoothSpline
+ * @param {Array} points 线段顶点数组
+ * @param {boolean} isLoop
+ * @return {Array}
+ */
+ module.exports = function (points, isLoop) {
+ var len = points.length;
+ var ret = [];
+
+ var distance = 0;
+ for (var i = 1; i < len; i++) {
+ distance += vec2.distance(points[i - 1], points[i]);
+ }
+
+ var segs = distance / 2;
+ segs = segs < len ? len : segs;
+ for (var i = 0; i < segs; i++) {
+ var pos = i / (segs - 1) * (isLoop ? len : len - 1);
+ var idx = Math.floor(pos);
+
+ var w = pos - idx;
+
+ var p0;
+ var p1 = points[idx % len];
+ var p2;
+ var p3;
+ if (!isLoop) {
+ p0 = points[idx === 0 ? idx : idx - 1];
+ p2 = points[idx > len - 2 ? len - 1 : idx + 1];
+ p3 = points[idx > len - 3 ? len - 1 : idx + 2];
+ }
+ else {
+ p0 = points[(idx - 1 + len) % len];
+ p2 = points[(idx + 1) % len];
+ p3 = points[(idx + 2) % len];
+ }
+
+ var w2 = w * w;
+ var w3 = w * w2;
+
+ ret.push([
+ interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3),
+ interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3)
+ ]);
+ }
+ return ret;
+ };
+
+
+
+/***/ },
+/* 57 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 贝塞尔平滑曲线
+ * @module zrender/shape/util/smoothBezier
+ * @author pissang (https://www.github.com/pissang)
+ * Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * errorrik (errorrik@gmail.com)
+ */
+
+
+ var vec2 = __webpack_require__(10);
+ var v2Min = vec2.min;
+ var v2Max = vec2.max;
+ var v2Scale = vec2.scale;
+ var v2Distance = vec2.distance;
+ var v2Add = vec2.add;
+
+ /**
+ * 贝塞尔平滑曲线
+ * @alias module:zrender/shape/util/smoothBezier
+ * @param {Array} points 线段顶点数组
+ * @param {number} smooth 平滑等级, 0-1
+ * @param {boolean} isLoop
+ * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内
+ * 比如 [[0, 0], [100, 100]], 这个包围盒会与
+ * 整个折线的包围盒做一个并集用来约束控制点。
+ * @param {Array} 计算出来的控制点数组
+ */
+ module.exports = function (points, smooth, isLoop, constraint) {
+ var cps = [];
+
+ var v = [];
+ var v1 = [];
+ var v2 = [];
+ var prevPoint;
+ var nextPoint;
+
+ var min, max;
+ if (constraint) {
+ min = [Infinity, Infinity];
+ max = [-Infinity, -Infinity];
+ for (var i = 0, len = points.length; i < len; i++) {
+ v2Min(min, min, points[i]);
+ v2Max(max, max, points[i]);
+ }
+ // 与指定的包围盒做并集
+ v2Min(min, min, constraint[0]);
+ v2Max(max, max, constraint[1]);
+ }
+
+ for (var i = 0, len = points.length; i < len; i++) {
+ var point = points[i];
+
+ if (isLoop) {
+ prevPoint = points[i ? i - 1 : len - 1];
+ nextPoint = points[(i + 1) % len];
+ }
+ else {
+ if (i === 0 || i === len - 1) {
+ cps.push(vec2.clone(points[i]));
+ continue;
+ }
+ else {
+ prevPoint = points[i - 1];
+ nextPoint = points[i + 1];
+ }
+ }
+
+ vec2.sub(v, nextPoint, prevPoint);
+
+ // use degree to scale the handle length
+ v2Scale(v, v, smooth);
+
+ var d0 = v2Distance(point, prevPoint);
+ var d1 = v2Distance(point, nextPoint);
+ var sum = d0 + d1;
+ if (sum !== 0) {
+ d0 /= sum;
+ d1 /= sum;
+ }
+
+ v2Scale(v1, v, -d0);
+ v2Scale(v2, v, d1);
+ var cp0 = v2Add([], point, v1);
+ var cp1 = v2Add([], point, v2);
+ if (constraint) {
+ v2Max(cp0, cp0, min);
+ v2Min(cp0, cp0, max);
+ v2Max(cp1, cp1, min);
+ v2Min(cp1, cp1, max);
+ }
+ cps.push(cp0);
+ cps.push(cp1);
+ }
+
+ if (isLoop) {
+ cps.push(cps.shift());
+ }
+
+ return cps;
+ };
+
+
+
+/***/ },
+/* 58 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @module zrender/graphic/shape/Polyline
+ */
+
+
+ var polyHelper = __webpack_require__(55);
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'polyline',
+
+ shape: {
+ points: null,
+
+ smooth: false,
+
+ smoothConstraint: null
+ },
+
+ style: {
+ stroke: '#000',
+
+ fill: null
+ },
+
+ buildPath: function (ctx, shape) {
+ polyHelper.buildPath(ctx, shape, false);
+ }
+ });
+
+
+/***/ },
+/* 59 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 矩形
+ * @module zrender/graphic/shape/Rect
+ */
+
+
+ var roundRectHelper = __webpack_require__(60);
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'rect',
+
+ shape: {
+ // 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4
+ // r缩写为1 相当于 [1, 1, 1, 1]
+ // r缩写为[1] 相当于 [1, 1, 1, 1]
+ // r缩写为[1, 2] 相当于 [1, 2, 1, 2]
+ // r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2]
+ r: 0,
+
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0
+ },
+
+ buildPath: function (ctx, shape) {
+ var x = shape.x;
+ var y = shape.y;
+ var width = shape.width;
+ var height = shape.height;
+ if (!shape.r) {
+ ctx.rect(x, y, width, height);
+ }
+ else {
+ roundRectHelper.buildPath(ctx, shape);
+ }
+ ctx.closePath();
+ return;
+ }
+ });
+
+
+
+/***/ },
+/* 60 */
+/***/ function(module, exports) {
+
+
+
+ module.exports = {
+ buildPath: function (ctx, shape) {
+ var x = shape.x;
+ var y = shape.y;
+ var width = shape.width;
+ var height = shape.height;
+ var r = shape.r;
+ var r1;
+ var r2;
+ var r3;
+ var r4;
+
+ // Convert width and height to positive for better borderRadius
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+
+ if (typeof r === 'number') {
+ r1 = r2 = r3 = r4 = r;
+ }
+ else if (r instanceof Array) {
+ if (r.length === 1) {
+ r1 = r2 = r3 = r4 = r[0];
+ }
+ else if (r.length === 2) {
+ r1 = r3 = r[0];
+ r2 = r4 = r[1];
+ }
+ else if (r.length === 3) {
+ r1 = r[0];
+ r2 = r4 = r[1];
+ r3 = r[2];
+ }
+ else {
+ r1 = r[0];
+ r2 = r[1];
+ r3 = r[2];
+ r4 = r[3];
+ }
+ }
+ else {
+ r1 = r2 = r3 = r4 = 0;
+ }
+
+ var total;
+ if (r1 + r2 > width) {
+ total = r1 + r2;
+ r1 *= width / total;
+ r2 *= width / total;
+ }
+ if (r3 + r4 > width) {
+ total = r3 + r4;
+ r3 *= width / total;
+ r4 *= width / total;
+ }
+ if (r2 + r3 > height) {
+ total = r2 + r3;
+ r2 *= height / total;
+ r3 *= height / total;
+ }
+ if (r1 + r4 > height) {
+ total = r1 + r4;
+ r1 *= height / total;
+ r4 *= height / total;
+ }
+ ctx.moveTo(x + r1, y);
+ ctx.lineTo(x + width - r2, y);
+ r2 !== 0 && ctx.quadraticCurveTo(
+ x + width, y, x + width, y + r2
+ );
+ ctx.lineTo(x + width, y + height - r3);
+ r3 !== 0 && ctx.quadraticCurveTo(
+ x + width, y + height, x + width - r3, y + height
+ );
+ ctx.lineTo(x + r4, y + height);
+ r4 !== 0 && ctx.quadraticCurveTo(
+ x, y + height, x, y + height - r4
+ );
+ ctx.lineTo(x, y + r1);
+ r1 !== 0 && ctx.quadraticCurveTo(x, y, x + r1, y);
+ }
+ };
+
+
+/***/ },
+/* 61 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 直线
+ * @module zrender/graphic/shape/Line
+ */
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'line',
+
+ shape: {
+ // Start point
+ x1: 0,
+ y1: 0,
+ // End point
+ x2: 0,
+ y2: 0,
+
+ percent: 1
+ },
+
+ style: {
+ stroke: '#000',
+ fill: null
+ },
+
+ buildPath: function (ctx, shape) {
+ var x1 = shape.x1;
+ var y1 = shape.y1;
+ var x2 = shape.x2;
+ var y2 = shape.y2;
+ var percent = shape.percent;
+
+ if (percent === 0) {
+ return;
+ }
+
+ ctx.moveTo(x1, y1);
+
+ if (percent < 1) {
+ x2 = x1 * (1 - percent) + x2 * percent;
+ y2 = y1 * (1 - percent) + y2 * percent;
+ }
+ ctx.lineTo(x2, y2);
+ },
+
+ /**
+ * Get point at percent
+ * @param {number} percent
+ * @return {Array.}
+ */
+ pointAt: function (p) {
+ var shape = this.shape;
+ return [
+ shape.x1 * (1 - p) + shape.x2 * p,
+ shape.y1 * (1 - p) + shape.y2 * p
+ ];
+ }
+ });
+
+
+
+/***/ },
+/* 62 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 贝塞尔曲线
+ * @module zrender/shape/BezierCurve
+ */
+
+
+ var curveTool = __webpack_require__(37);
+ var vec2 = __webpack_require__(10);
+ var quadraticSubdivide = curveTool.quadraticSubdivide;
+ var cubicSubdivide = curveTool.cubicSubdivide;
+ var quadraticAt = curveTool.quadraticAt;
+ var cubicAt = curveTool.cubicAt;
+ var quadraticDerivativeAt = curveTool.quadraticDerivativeAt;
+ var cubicDerivativeAt = curveTool.cubicDerivativeAt;
+
+ var out = [];
+
+ function someVectorAt(shape, t, isTangent) {
+ var cpx2 = shape.cpx2;
+ var cpy2 = shape.cpy2;
+ if (cpx2 === null || cpy2 === null) {
+ return [
+ (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t),
+ (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)
+ ];
+ }
+ else {
+ return [
+ (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t),
+ (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)
+ ];
+ }
+ }
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'bezier-curve',
+
+ shape: {
+ x1: 0,
+ y1: 0,
+ x2: 0,
+ y2: 0,
+ cpx1: 0,
+ cpy1: 0,
+ // cpx2: 0,
+ // cpy2: 0
+
+ // Curve show percent, for animating
+ percent: 1
+ },
+
+ style: {
+ stroke: '#000',
+ fill: null
+ },
+
+ buildPath: function (ctx, shape) {
+ var x1 = shape.x1;
+ var y1 = shape.y1;
+ var x2 = shape.x2;
+ var y2 = shape.y2;
+ var cpx1 = shape.cpx1;
+ var cpy1 = shape.cpy1;
+ var cpx2 = shape.cpx2;
+ var cpy2 = shape.cpy2;
+ var percent = shape.percent;
+ if (percent === 0) {
+ return;
+ }
+
+ ctx.moveTo(x1, y1);
+
+ if (cpx2 == null || cpy2 == null) {
+ if (percent < 1) {
+ quadraticSubdivide(
+ x1, cpx1, x2, percent, out
+ );
+ cpx1 = out[1];
+ x2 = out[2];
+ quadraticSubdivide(
+ y1, cpy1, y2, percent, out
+ );
+ cpy1 = out[1];
+ y2 = out[2];
+ }
+
+ ctx.quadraticCurveTo(
+ cpx1, cpy1,
+ x2, y2
+ );
+ }
+ else {
+ if (percent < 1) {
+ cubicSubdivide(
+ x1, cpx1, cpx2, x2, percent, out
+ );
+ cpx1 = out[1];
+ cpx2 = out[2];
+ x2 = out[3];
+ cubicSubdivide(
+ y1, cpy1, cpy2, y2, percent, out
+ );
+ cpy1 = out[1];
+ cpy2 = out[2];
+ y2 = out[3];
+ }
+ ctx.bezierCurveTo(
+ cpx1, cpy1,
+ cpx2, cpy2,
+ x2, y2
+ );
+ }
+ },
+
+ /**
+ * Get point at percent
+ * @param {number} t
+ * @return {Array.}
+ */
+ pointAt: function (t) {
+ return someVectorAt(this.shape, t, false);
+ },
+
+ /**
+ * Get tangent at percent
+ * @param {number} t
+ * @return {Array.}
+ */
+ tangentAt: function (t) {
+ var p = someVectorAt(this.shape, t, true);
+ return vec2.normalize(p, p);
+ }
+ });
+
+
+
+/***/ },
+/* 63 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * 圆弧
+ * @module zrender/graphic/shape/Arc
+ */
+
+
+ module.exports = __webpack_require__(20).extend({
+
+ type: 'arc',
+
+ shape: {
+
+ cx: 0,
+
+ cy: 0,
+
+ r: 0,
+
+ startAngle: 0,
+
+ endAngle: Math.PI * 2,
+
+ clockwise: true
+ },
+
+ style: {
+
+ stroke: '#000',
+
+ fill: null
+ },
+
+ buildPath: function (ctx, shape) {
+
+ var x = shape.cx;
+ var y = shape.cy;
+ var r = Math.max(shape.r, 0);
+ var startAngle = shape.startAngle;
+ var endAngle = shape.endAngle;
+ var clockwise = shape.clockwise;
+
+ var unitX = Math.cos(startAngle);
+ var unitY = Math.sin(startAngle);
+
+ ctx.moveTo(unitX * r + x, unitY * r + y);
+ ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
+ }
+ });
+
+
+/***/ },
+/* 64 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // CompoundPath to improve performance
+
+
+ var Path = __webpack_require__(20);
+
+ module.exports = Path.extend({
+
+ type: 'compound',
+
+ shape: {
+
+ paths: null
+ },
+
+ _updatePathDirty: function () {
+ var dirtyPath = this.__dirtyPath;
+ var paths = this.shape.paths;
+ for (var i = 0; i < paths.length; i++) {
+ // Mark as dirty if any subpath is dirty
+ dirtyPath = dirtyPath || paths[i].__dirtyPath;
+ }
+ this.__dirtyPath = dirtyPath;
+ this.__dirty = this.__dirty || dirtyPath;
+ },
+
+ beforeBrush: function () {
+ this._updatePathDirty();
+ var paths = this.shape.paths || [];
+ var scale = this.getGlobalScale();
+ // Update path scale
+ for (var i = 0; i < paths.length; i++) {
+ if (!paths[i].path) {
+ paths[i].createPathProxy();
+ }
+ paths[i].path.setScale(scale[0], scale[1]);
+ }
+ },
+
+ buildPath: function (ctx, shape) {
+ var paths = shape.paths || [];
+ for (var i = 0; i < paths.length; i++) {
+ paths[i].buildPath(ctx, paths[i].shape, true);
+ }
+ },
+
+ afterBrush: function () {
+ var paths = this.shape.paths;
+ for (var i = 0; i < paths.length; i++) {
+ paths[i].__dirtyPath = false;
+ }
+ },
+
+ getBoundingRect: function () {
+ this._updatePathDirty();
+ return Path.prototype.getBoundingRect.call(this);
+ }
+ });
+
+
+/***/ },
+/* 65 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var Gradient = __webpack_require__(66);
+
+ /**
+ * x, y, x2, y2 are all percent from 0 to 1
+ * @param {number} [x=0]
+ * @param {number} [y=0]
+ * @param {number} [x2=1]
+ * @param {number} [y2=0]
+ * @param {Array.} colorStops
+ * @param {boolean} [globalCoord=false]
+ */
+ var LinearGradient = function (x, y, x2, y2, colorStops, globalCoord) {
+ // Should do nothing more in this constructor. Because gradient can be
+ // declard by `color: {type: 'linear', colorStops: ...}`, where
+ // this constructor will not be called.
+
+ this.x = x == null ? 0 : x;
+
+ this.y = y == null ? 0 : y;
+
+ this.x2 = x2 == null ? 1 : x2;
+
+ this.y2 = y2 == null ? 0 : y2;
+
+ // Can be cloned
+ this.type = 'linear';
+
+ // If use global coord
+ this.global = globalCoord || false;
+
+ Gradient.call(this, colorStops);
+ };
+
+ LinearGradient.prototype = {
+
+ constructor: LinearGradient
+ };
+
+ zrUtil.inherits(LinearGradient, Gradient);
+
+ module.exports = LinearGradient;
+
+
+/***/ },
+/* 66 */
+/***/ function(module, exports) {
+
+
+
+ /**
+ * @param {Array.} colorStops
+ */
+ var Gradient = function (colorStops) {
+
+ this.colorStops = colorStops || [];
+ };
+
+ Gradient.prototype = {
+
+ constructor: Gradient,
+
+ addColorStop: function (offset, color) {
+ this.colorStops.push({
+
+ offset: offset,
+
+ color: color
+ });
+ }
+ };
+
+ module.exports = Gradient;
+
+
+/***/ },
+/* 67 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var Gradient = __webpack_require__(66);
+
+ /**
+ * x, y, r are all percent from 0 to 1
+ * @param {number} [x=0.5]
+ * @param {number} [y=0.5]
+ * @param {number} [r=0.5]
+ * @param {Array.} [colorStops]
+ * @param {boolean} [globalCoord=false]
+ */
+ var RadialGradient = function (x, y, r, colorStops, globalCoord) {
+ // Should do nothing more in this constructor. Because gradient can be
+ // declard by `color: {type: 'radial', colorStops: ...}`, where
+ // this constructor will not be called.
+
+ this.x = x == null ? 0.5 : x;
+
+ this.y = y == null ? 0.5 : y;
+
+ this.r = r == null ? 0.5 : r;
+
+ // Can be cloned
+ this.type = 'radial';
+
+ // If use global coord
+ this.global = globalCoord || false;
+
+ Gradient.call(this, colorStops);
+ };
+
+ RadialGradient.prototype = {
+
+ constructor: RadialGradient
+ };
+
+ zrUtil.inherits(RadialGradient, Gradient);
+
+ module.exports = RadialGradient;
+
+
+/***/ },
+/* 68 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+ var getItemStyle = __webpack_require__(15)(
+ [
+ ['fill', 'color'],
+ ['stroke', 'borderColor'],
+ ['lineWidth', 'borderWidth'],
+ ['opacity'],
+ ['shadowBlur'],
+ ['shadowOffsetX'],
+ ['shadowOffsetY'],
+ ['shadowColor'],
+ ['textPosition'],
+ ['textAlign']
+ ]
+ );
+ module.exports = {
+ getItemStyle: function (excludes, includes) {
+ var style = getItemStyle.call(this, excludes, includes);
+ var lineDash = this.getBorderLineDash();
+ lineDash && (style.lineDash = lineDash);
+ return style;
+ },
+
+ getBorderLineDash: function () {
+ var lineType = this.get('borderType');
+ return (lineType === 'solid' || lineType == null) ? null
+ : (lineType === 'dashed' ? [5, 5] : [1, 1]);
+ }
+ };
+
+
+/***/ },
+/* 69 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Component model
+ *
+ * @module echarts/model/Component
+ */
+
+
+ var Model = __webpack_require__(12);
+ var zrUtil = __webpack_require__(4);
+ var arrayPush = Array.prototype.push;
+ var componentUtil = __webpack_require__(70);
+ var clazzUtil = __webpack_require__(13);
+ var layout = __webpack_require__(71);
+
+ /**
+ * @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.>}
+ * @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,
+
+ $constructor: function (option, parentModel, ecModel, extraOpt) {
+ Model.call(this, option, parentModel, ecModel, extraOpt);
+
+ this.uid = componentUtil.getUID('componentModel');
+ },
+
+
+ init: function (option, parentModel, ecModel, extraOpt) {
+ this.mergeDefaultAndTheme(option, 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, extraOpt) {
+ zrUtil.merge(this.option, option, true);
+
+ var layoutMode = this.layoutMode;
+ if (layoutMode) {
+ layout.mergeLayoutParam(this.option, option, layoutMode);
+ }
+ },
+
+ // Hooker after init or mergeOption
+ optionUpdated: function (newCptOption, isInit) {},
+
+ getDefaultOption: function () {
+ if (!clazzUtil.hasOwn(this, '__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);
+ }
+ clazzUtil.set(this, '__defaultOption', defaultOption);
+ }
+ return clazzUtil.get(this, '__defaultOption');
+ },
+
+ getReferringComponents: function (mainType) {
+ return this.ecModel.queryComponents({
+ mainType: mainType,
+ index: this.get(mainType + 'Index', true),
+ id: this.get(mainType + 'Id', true)
+ });
+ }
+
+ });
+
+ // Reset ComponentModel.extend, add preConstruct.
+ // clazzUtil.enableClassExtend(
+ // ComponentModel,
+ // function (option, parentModel, ecModel, extraOpt) {
+ // // Set dependentModels, componentIndex, name, id, mainType, subType.
+ // zrUtil.extend(this, extraOpt);
+
+ // this.uid = componentUtil.getUID('componentModel');
+
+ // // this.setReadOnly([
+ // // 'type', 'id', 'uid', 'name', 'mainType', 'subType',
+ // // 'dependentModels', 'componentIndex'
+ // // ]);
+ // }
+ // );
+
+ // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
+ 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, __webpack_require__(72));
+
+ module.exports = ComponentModel;
+
+
+/***/ },
+/* 70 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var zrUtil = __webpack_require__(4);
+ var clazz = __webpack_require__(13);
+
+ 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.} targetNameList Target Component type list.
+ * Can be ['aa', 'bb', 'aa.xx']
+ * @param {Array.} 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 on series, and we call
+ // chart.setOption({series: [...]}), where only series is in option.
+ // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will
+ // not be called, but only sereis.mergeOption is called. Thus legend
+ // have no chance to update its local record about series (like which
+ // name of series is available in legend).
+ 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;
+ }
+ };
+
+ module.exports = componentUtil;
+
+
+/***/ },
+/* 71 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ // Layout helpers for each component positioning
+
+
+ var zrUtil = __webpack_require__(4);
+ var BoundingRect = __webpack_require__(9);
+ var numberUtil = __webpack_require__(7);
+ var formatUtil = __webpack_require__(6);
+ var parsePercent = numberUtil.parsePercent;
+ var each = zrUtil.each;
+
+ var layout = {};
+
+ /**
+ * @public
+ */
+ var LOCATION_PARAMS = layout.LOCATION_PARAMS = [
+ 'left', 'right', 'top', 'bottom', 'width', 'height'
+ ];
+
+ /**
+ * @public
+ */
+ var HV_NAMES = layout.HV_NAMES = [
+ ['width', 'left', 'right'],
+ ['height', 'top', 'bottom']
+ ];
+
+ function boxLayout(orient, group, gap, maxWidth, maxHeight) {
+ var x = 0;
+ var y = 0;
+ if (maxWidth == null) {
+ maxWidth = Infinity;
+ }
+ if (maxHeight == null) {
+ maxHeight = Infinity;
+ }
+ var currentLineMaxSize = 0;
+ group.eachChild(function (child, idx) {
+ var position = child.position;
+ var rect = child.getBoundingRect();
+ var nextChild = group.childAt(idx + 1);
+ var nextChildRect = nextChild && nextChild.getBoundingRect();
+ var nextX;
+ var nextY;
+ if (orient === 'horizontal') {
+ var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0);
+ nextX = x + moveX;
+ // Wrap when width exceeds maxWidth or meet a `newline` group
+ if (nextX > maxWidth || child.newline) {
+ x = 0;
+ nextX = moveX;
+ y += currentLineMaxSize + gap;
+ currentLineMaxSize = rect.height;
+ }
+ else {
+ currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
+ }
+ }
+ else {
+ var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);
+ nextY = y + moveY;
+ // Wrap when width exceeds maxHeight or meet a `newline` group
+ if (nextY > maxHeight || child.newline) {
+ x += currentLineMaxSize + gap;
+ y = 0;
+ nextY = moveY;
+ currentLineMaxSize = rect.width;
+ }
+ else {
+ currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
+ }
+ }
+
+ if (child.newline) {
+ return;
+ }
+
+ 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;
+ }
+ // If something is wrong and left, top, width, height are calculated as NaN
+ left = left || 0;
+ top = top || 0;
+ if (isNaN(width)) {
+ // Width may be NaN if only one value is given except width
+ width = containerWidth - left - (right || 0);
+ }
+ if (isNaN(height)) {
+ // Height may be NaN if only one value is given except height
+ height = containerHeight - top - (bottom || 0);
+ }
+
+ var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
+ rect.margin = margin;
+ return rect;
+ };
+
+
+ /**
+ * Position a zr element in viewport
+ * Group position is specified by either
+ * {left, top}, {right, bottom}
+ * If all properties exists, right and bottom will be igonred.
+ *
+ * Logic:
+ * 1. Scale (against origin point in parent coord)
+ * 2. Rotate (against origin point in parent coord)
+ * 3. Traslate (with el.position by this method)
+ * So this method only fixes the last step 'Traslate', which does not affect
+ * scaling and rotating.
+ *
+ * If be called repeatly with the same input el, the same result will be gotten.
+ *
+ * @param {module:zrender/Element} el Should have `getBoundingRect` method.
+ * @param {Object} positionInfo
+ * @param {number|string} [positionInfo.left]
+ * @param {number|string} [positionInfo.top]
+ * @param {number|string} [positionInfo.right]
+ * @param {number|string} [positionInfo.bottom]
+ * @param {Object} containerRect
+ * @param {string|number} margin
+ * @param {Object} [opt]
+ * @param {Array.} [opt.hv=[1,1]] Only horizontal or only vertical.
+ * @param {Array.} [opt.boundingMode='all']
+ * Specify how to calculate boundingRect when locating.
+ * 'all': Position the boundingRect that is transformed and uioned
+ * both itself and its descendants.
+ * This mode simplies confine the elements in the bounding
+ * of their container (e.g., using 'right: 0').
+ * 'raw': Position the boundingRect that is not transformed and only itself.
+ * This mode is useful when you want a element can overflow its
+ * container. (Consider a rotated circle needs to be located in a corner.)
+ * In this mode positionInfo.width/height can only be number.
+ */
+ layout.positionElement = function (el, positionInfo, containerRect, margin, opt) {
+ var h = !opt || !opt.hv || opt.hv[0];
+ var v = !opt || !opt.hv || opt.hv[1];
+ var boundingMode = opt && opt.boundingMode || 'all';
+
+ if (!h && !v) {
+ return;
+ }
+
+ var rect;
+ if (boundingMode === 'raw') {
+ rect = el.type === 'group'
+ ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0)
+ : el.getBoundingRect();
+ }
+ else {
+ rect = el.getBoundingRect();
+ if (el.needLocalTransform()) {
+ var transform = el.getLocalTransform();
+ // Notice: raw rect may be inner object of el,
+ // which should not be modified.
+ rect = rect.clone();
+ rect.applyTransform(transform);
+ }
+ }
+
+ positionInfo = layout.getLayoutRect(
+ zrUtil.defaults(
+ {width: rect.width, height: rect.height},
+ positionInfo
+ ),
+ containerRect,
+ margin
+ );
+
+ // Because 'tranlate' is the last step in transform
+ // (see zrender/core/Transformable#getLocalTransfrom),
+ // we can just only modify el.position to get final result.
+ var elPos = el.position;
+ var dx = h ? positionInfo.x - rect.x : 0;
+ var dy = v ? positionInfo.y - rect.y : 0;
+
+ el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]);
+ };
+
+ /**
+ * @param {Object} option Contains some of the properties in HV_NAMES.
+ * @param {number} hvIdx 0: horizontal; 1: vertical.
+ */
+ layout.sizeCalculable = function (option, hvIdx) {
+ return option[HV_NAMES[hvIdx][0]] != null
+ || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null);
+ };
+
+ /**
+ * 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|string} [opt]
+ * @param {boolean|Array.} [opt.ignoreSize=false] Some component must has width and height.
+ */
+ layout.mergeLayoutParam = function (targetOption, newOption, opt) {
+ !zrUtil.isObject(opt) && (opt = {});
+
+ var ignoreSize = opt.ignoreSize;
+ !zrUtil.isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);
+
+ var hResult = merge(HV_NAMES[0], 0);
+ var vResult = merge(HV_NAMES[1], 1);
+
+ copy(HV_NAMES[0], targetOption, hResult);
+ copy(HV_NAMES[1], targetOption, vResult);
+
+ function merge(names, hvIdx) {
+ var newParams = {};
+ var newValueCount = 0;
+ var merged = {};
+ var mergedValueCount = 0;
+ var enoughParamNumber = 2;
+
+ each(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++;
+ });
+
+ if (ignoreSize[hvIdx]) {
+ // Only one of left/right is premitted to exist.
+ if (hasValue(newOption, names[1])) {
+ merged[names[2]] = null;
+ }
+ else if (hasValue(newOption, names[2])) {
+ merged[names[1]] = null;
+ }
+ return merged;
+ }
+
+ // 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;
+ }
+ // 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.
+ 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) {
+ return layout.copyLayoutParams({}, source);
+ };
+
+ /**
+ * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
+ * @param {Object} source
+ * @return {Object} Result contains those props.
+ */
+ layout.copyLayoutParams = function (target, source) {
+ source && target && each(LOCATION_PARAMS, function (name) {
+ source.hasOwnProperty(name) && (target[name] = source[name]);
+ });
+ return target;
+ };
+
+ module.exports = layout;
+
+
+
+/***/ },
+/* 72 */
+/***/ function(module, exports) {
+
+
+
+ module.exports = {
+ 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')
+ };
+ }
+ };
+
+
+/***/ },
+/* 73 */
+/***/ function(module, exports) {
+
+
+ var platform = '';
+ // Navigator not exists in node
+ if (typeof navigator !== 'undefined') {
+ platform = navigator.platform || '';
+ }
+ module.exports = {
+ // 全图默认背景
+ // 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','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#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'
+ },
+
+ // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/
+ // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
+ // Default is source-over
+ blendMode: null,
+
+ animation: 'auto',
+ animationDuration: 1000,
+ animationDurationUpdate: 300,
+ animationEasing: 'exponentialOut',
+ animationEasingUpdate: 'cubicOut',
+
+ animationThreshold: 2000,
+ // Configuration for progressive/incremental rendering
+ progressiveThreshold: 3000,
+ progressive: 400,
+
+ // Threshold of if use single hover layer to optimize.
+ // It is recommended that `hoverLayerThreshold` is equivalent to or less than
+ // `progressiveThreshold`, otherwise hover will cause restart of progressive,
+ // which is unexpected.
+ // see example .
+ hoverLayerThreshold: 3000,
+
+ // See: module:echarts/scale/Time
+ useUTC: false
+ };
+
+
+/***/ },
+/* 74 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var classUtil = __webpack_require__(13);
+ var set = classUtil.set;
+ var get = classUtil.get;
+
+ module.exports = {
+ clearColorPalette: function () {
+ set(this, 'colorIdx', 0);
+ set(this, 'colorNameMap', {});
+ },
+
+ getColorFromPalette: function (name, scope) {
+ scope = scope || this;
+ var colorIdx = get(scope, 'colorIdx') || 0;
+ var colorNameMap = get(scope, 'colorNameMap') || set(scope, 'colorNameMap', {});
+ // Use `hasOwnProperty` to avoid conflict with Object.prototype.
+ if (colorNameMap.hasOwnProperty(name)) {
+ return colorNameMap[name];
+ }
+ var colorPalette = this.get('color', true) || [];
+ if (!colorPalette.length) {
+ return;
+ }
+
+ var color = colorPalette[colorIdx];
+ if (name) {
+ colorNameMap[name] = color;
+ }
+ set(scope, 'colorIdx', (colorIdx + 1) % colorPalette.length);
+
+ return color;
+ }
+ };
+
+
+/***/ },
+/* 75 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var echartsAPIList = [
+ 'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed',
+ 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption',
+ 'getViewOfComponentModel', 'getViewOfSeriesModel'
+ ];
+ // And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js
+
+ function ExtensionAPI(chartInstance) {
+ zrUtil.each(echartsAPIList, function (name) {
+ this[name] = zrUtil.bind(chartInstance[name], chartInstance);
+ }, this);
+ }
+
+ module.exports = ExtensionAPI;
+
+
+/***/ },
+/* 76 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var coordinateSystemCreators = {};
+
+ function CoordinateSystemManager() {
+
+ this._coordinateSystems = [];
+ }
+
+ CoordinateSystemManager.prototype = {
+
+ constructor: CoordinateSystemManager,
+
+ create: function (ecModel, api) {
+ var coordinateSystems = [];
+ zrUtil.each(coordinateSystemCreators, function (creater, type) {
+ var list = creater.create(ecModel, api);
+ coordinateSystems = coordinateSystems.concat(list || []);
+ });
+
+ this._coordinateSystems = coordinateSystems;
+ },
+
+ update: function (ecModel, api) {
+ zrUtil.each(this._coordinateSystems, function (coordSys) {
+ // FIXME MUST have
+ coordSys.update && coordSys.update(ecModel, api);
+ });
+ },
+
+ getCoordinateSystems: function () {
+ return this._coordinateSystems.slice();
+ }
+ };
+
+ CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
+ coordinateSystemCreators[type] = coordinateSystemCreator;
+ };
+
+ CoordinateSystemManager.get = function (type) {
+ return coordinateSystemCreators[type];
+ };
+
+ module.exports = CoordinateSystemManager;
+
+
+/***/ },
+/* 77 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ECharts option manager
+ *
+ * @module {echarts/model/OptionManager}
+ */
+
+
+
+ var zrUtil = __webpack_require__(4);
+ var modelUtil = __webpack_require__(5);
+ var ComponentModel = __webpack_require__(69);
+ var each = zrUtil.each;
+ var clone = zrUtil.clone;
+ var map = zrUtil.map;
+ var merge = zrUtil.merge;
+
+ var QUERY_REG = /^(min|max)?(.+)$/;
+
+ /**
+ * TERM EXPLANATIONS:
+ *
+ * [option]:
+ *
+ * An object that contains definitions of components. For example:
+ * var option = {
+ * title: {...},
+ * legend: {...},
+ * visualMap: {...},
+ * series: [
+ * {data: [...]},
+ * {data: [...]},
+ * ...
+ * ]
+ * };
+ *
+ * [rawOption]:
+ *
+ * An object input to echarts.setOption. 'rawOption' may be an
+ * 'option', or may be an object contains multi-options. For example:
+ * var option = {
+ * baseOption: {
+ * title: {...},
+ * legend: {...},
+ * series: [
+ * {data: [...]},
+ * {data: [...]},
+ * ...
+ * ]
+ * },
+ * timeline: {...},
+ * options: [
+ * {title: {...}, series: {data: [...]}},
+ * {title: {...}, series: {data: [...]}},
+ * ...
+ * ],
+ * media: [
+ * {
+ * query: {maxWidth: 320},
+ * option: {series: {x: 20}, visualMap: {show: false}}
+ * },
+ * {
+ * query: {minWidth: 320, maxWidth: 720},
+ * option: {series: {x: 500}, visualMap: {show: true}}
+ * },
+ * {
+ * option: {series: {x: 1200}, visualMap: {show: true}}
+ * }
+ * ]
+ * };
+ *
+ * @alias module:echarts/model/OptionManager
+ * @param {module:echarts/ExtensionAPI} api
+ */
+ function OptionManager(api) {
+
+ /**
+ * @private
+ * @type {module:echarts/ExtensionAPI}
+ */
+ this._api = api;
+
+ /**
+ * @private
+ * @type {Array.}
+ */
+ this._timelineOptions = [];
+
+ /**
+ * @private
+ * @type {Array.}
+ */
+ this._mediaList = [];
+
+ /**
+ * @private
+ * @type {Object}
+ */
+ this._mediaDefault;
+
+ /**
+ * -1, means default.
+ * empty means no media.
+ * @private
+ * @type {Array.}
+ */
+ this._currentMediaIndices = [];
+
+ /**
+ * @private
+ * @type {Object}
+ */
+ this._optionBackup;
+
+ /**
+ * @private
+ * @type {Object}
+ */
+ this._newBaseOption;
+ }
+
+ // 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.} optionPreprocessorFuncs
+ * @return {Object} Init option
+ */
+ setOption: function (rawOption, optionPreprocessorFuncs) {
+ rawOption = clone(rawOption, true);
+
+ // FIXME
+ // 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。
+
+ var oldOptionBackup = this._optionBackup;
+ var newParsedOption = parseRawOption.call(
+ this, rawOption, optionPreprocessorFuncs, !oldOptionBackup
+ );
+ this._newBaseOption = newParsedOption.baseOption;
+
+ // For setOption at second time (using merge mode);
+ if (oldOptionBackup) {
+ // Only baseOption can be merged.
+ mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption);
+
+ // For simplicity, timeline options and media options do not support merge,
+ // that is, if you `setOption` twice and both has timeline options, the latter
+ // timeline opitons will not be merged to the formers, but just substitude them.
+ if (newParsedOption.timelineOptions.length) {
+ oldOptionBackup.timelineOptions = newParsedOption.timelineOptions;
+ }
+ if (newParsedOption.mediaList.length) {
+ oldOptionBackup.mediaList = newParsedOption.mediaList;
+ }
+ if (newParsedOption.mediaDefault) {
+ oldOptionBackup.mediaDefault = newParsedOption.mediaDefault;
+ }
+ }
+ else {
+ this._optionBackup = newParsedOption;
+ }
+ },
+
+ /**
+ * @param {boolean} isRecreate
+ * @return {Object}
+ */
+ mountOption: function (isRecreate) {
+ var optionBackup = this._optionBackup;
+
+ // TODO
+ // 如果没有reset功能则不clone。
+
+ this._timelineOptions = map(optionBackup.timelineOptions, clone);
+ this._mediaList = map(optionBackup.mediaList, clone);
+ this._mediaDefault = clone(optionBackup.mediaDefault);
+ this._currentMediaIndices = [];
+
+ return clone(isRecreate
+ // this._optionBackup.baseOption, which is created at the first `setOption`
+ // called, and is merged into every new option by inner method `mergeOption`
+ // each time `setOption` called, can be only used in `isRecreate`, because
+ // its reliability is under suspicion. In other cases option merge is
+ // performed by `model.mergeOption`.
+ ? optionBackup.baseOption : this._newBaseOption
+ );
+ },
+
+ /**
+ * @param {module:echarts/model/Global} ecModel
+ * @return {Object}
+ */
+ getTimelineOption: function (ecModel) {
+ var option;
+ var timelineOptions = this._timelineOptions;
+
+ if (timelineOptions.length) {
+ // 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.}
+ */
+ 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, isNew) {
+ var timelineOptions = [];
+ var mediaList = [];
+ var mediaDefault;
+ var baseOption;
+
+ // Compatible with ec2.
+ var timelineOpt = rawOption.timeline;
+
+ if (rawOption.baseOption) {
+ baseOption = rawOption.baseOption;
+ }
+
+ // For timeline
+ if (timelineOpt || rawOption.options) {
+ baseOption = baseOption || {};
+ timelineOptions = (rawOption.options || []).slice();
+ }
+
+ // For media query
+ if (rawOption.media) {
+ baseOption = 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, isNew);
+ });
+ }
+ );
+
+ return {
+ baseOption: baseOption,
+ timelineOptions: timelineOptions,
+ mediaDefault: mediaDefault,
+ mediaList: mediaList
+ };
+ }
+
+ /**
+ * @see
+ * 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(',');
+ }
+
+ /**
+ * Consider case:
+ * `chart.setOption(opt1);`
+ * Then user do some interaction like dataZoom, dataView changing.
+ * `chart.setOption(opt2);`
+ * Then user press 'reset button' in toolbox.
+ *
+ * After doing that all of the interaction effects should be reset, the
+ * chart should be the same as the result of invoke
+ * `chart.setOption(opt1); chart.setOption(opt2);`.
+ *
+ * Although it is not able ensure that
+ * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
+ * `chart.setOption(merge(opt1, opt2));` exactly,
+ * this might be the only simple way to implement that feature.
+ *
+ * MEMO: We've considered some other approaches:
+ * 1. Each model handle its self restoration but not uniform treatment.
+ * (Too complex in logic and error-prone)
+ * 2. Use a shadow ecModel. (Performace expensive)
+ */
+ function mergeOption(oldOption, newOption) {
+ newOption = newOption || {};
+
+ each(newOption, function (newCptOpt, mainType) {
+ if (newCptOpt == null) {
+ return;
+ }
+
+ var oldCptOpt = oldOption[mainType];
+
+ if (!ComponentModel.hasClass(mainType)) {
+ oldOption[mainType] = merge(oldCptOpt, newCptOpt, true);
+ }
+ else {
+ newCptOpt = modelUtil.normalizeToArray(newCptOpt);
+ oldCptOpt = modelUtil.normalizeToArray(oldCptOpt);
+
+ var mapResult = modelUtil.mappingToExists(oldCptOpt, newCptOpt);
+
+ oldOption[mainType] = map(mapResult, function (item) {
+ return (item.option && item.exist)
+ ? merge(item.exist, item.option, true)
+ : (item.exist || item.option);
+ });
+ }
+ });
+ }
+
+ module.exports = OptionManager;
+
+
+/***/ },
+/* 78 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+
+ var zrUtil = __webpack_require__(4);
+ var formatUtil = __webpack_require__(6);
+ var classUtil = __webpack_require__(13);
+ var modelUtil = __webpack_require__(5);
+ var ComponentModel = __webpack_require__(69);
+ var colorPaletteMixin = __webpack_require__(74);
+ var env = __webpack_require__(2);
+ var layout = __webpack_require__(71);
+
+ var set = classUtil.set;
+ var get = classUtil.get;
+ var encodeHTML = formatUtil.encodeHTML;
+ var addCommas = formatUtil.addCommas;
+
+ var SeriesModel = ComponentModel.extend({
+
+ type: 'series.__base__',
+
+ /**
+ * @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,
+
+ /**
+ * Access path of color for visual
+ */
+ visualColorAccessPath: 'itemStyle.normal.color',
+
+ /**
+ * 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) {
+
+ /**
+ * @type {number}
+ * @readOnly
+ */
+ this.seriesIndex = this.componentIndex;
+
+ this.mergeDefaultAndTheme(option, ecModel);
+
+ var data = this.getInitialData(option, ecModel);
+ if (true) {
+ zrUtil.assert(data, 'getInitialData returned invalid data.');
+ }
+ /**
+ * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
+ * @private
+ */
+ set(this, 'dataBeforeProcessed', data);
+
+ // If we reverse the order (make data firstly, and then make
+ // dataBeforeProcessed by cloneShallow), cloneShallow will
+ // cause data.graph.data !== data when using
+ // module:echarts/data/Graph or module:echarts/data/Tree.
+ // See module:echarts/data/helper/linkList
+ this.restoreData();
+ },
+
+ /**
+ * Util for merge default and theme to option
+ * @param {Object} option
+ * @param {module:echarts/model/Global} ecModel
+ */
+ mergeDefaultAndTheme: function (option, ecModel) {
+ var layoutMode = this.layoutMode;
+ var inputPositionParams = layoutMode
+ ? layout.getLayoutParams(option) : {};
+
+ zrUtil.merge(
+ option,
+ ecModel.getTheme().get(this.subType)
+ );
+ zrUtil.merge(option, this.getDefaultOption());
+
+ // Default label emphasis `position` and `show`
+ // FIXME Set label in mergeOption
+ modelUtil.defaultEmphasis(option.label, modelUtil.LABEL_OPTIONS);
+
+ this.fillDataTextStyle(option.data);
+
+ if (layoutMode) {
+ layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
+ }
+ },
+
+ mergeOption: function (newSeriesOption, ecModel) {
+ newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
+ this.fillDataTextStyle(newSeriesOption.data);
+
+ var layoutMode = this.layoutMode;
+ if (layoutMode) {
+ layout.mergeLayoutParam(this.option, newSeriesOption, layoutMode);
+ }
+
+ var data = this.getInitialData(newSeriesOption, ecModel);
+ // TODO Merge data?
+ if (data) {
+ set(this, 'data', data);
+ set(this, 'dataBeforeProcessed', data.cloneShallow());
+ }
+ },
+
+ fillDataTextStyle: function (data) {
+ // Default data label emphasis `position` and `show`
+ // FIXME Tree structure data ?
+ // FIXME Performance ?
+ if (data) {
+ for (var i = 0; i < data.length; i++) {
+ if (data[i] && data[i].label) {
+ modelUtil.defaultEmphasis(data[i].label, modelUtil.LABEL_OPTIONS);
+ }
+ }
+ }
+ },
+
+ /**
+ * Init a data structure from data related option in series
+ * Must be overwritten
+ */
+ getInitialData: function () {},
+
+ /**
+ * @param {string} [dataType]
+ * @return {module:echarts/data/List}
+ */
+ getData: function (dataType) {
+ var data = get(this, 'data');
+ return dataType == null ? data : data.getLinkedData(dataType);
+ },
+
+ /**
+ * @param {module:echarts/data/List} data
+ */
+ setData: function (data) {
+ set(this, 'data', data);
+ },
+
+ /**
+ * Get data before processed
+ * @return {module:echarts/data/List}
+ */
+ getRawData: function () {
+ return get(this, 'dataBeforeProcessed');
+ },
+
+ /**
+ * Coord dimension to data dimension.
+ *
+ * By default the result is the same as dimensions of series data.
+ * But in some series data dimensions are different from coord dimensions (i.e.
+ * candlestick and boxplot). Override this method to handle those cases.
+ *
+ * Coord dimension to data dimension can be one-to-many
+ *
+ * @param {string} coordDim
+ * @return {Array.} dimensions on the axis.
+ */
+ coordDimToDataDim: function (coordDim) {
+ return modelUtil.coordDimToDataDim(this.getData(), coordDim);
+ },
+
+ /**
+ * Convert data dimension to coord dimension.
+ *
+ * @param {string|number} dataDim
+ * @return {string}
+ */
+ dataDimToCoordDim: function (dataDim) {
+ return modelUtil.dataDimToCoordDim(this.getData(), dataDim);
+ },
+
+ /**
+ * Get base axis if has coordinate system and has axis.
+ * By default use coordSys.getBaseAxis();
+ * Can be overrided for some chart.
+ * @return {type} description
+ */
+ getBaseAxis: function () {
+ var coordSys = this.coordinateSystem;
+ return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
+ },
+
+ // FIXME
+ /**
+ * Default tooltip formatter
+ *
+ * @param {number} dataIndex
+ * @param {boolean} [multipleSeries=false]
+ * @param {number} [dataType]
+ */
+ formatTooltip: function (dataIndex, multipleSeries, dataType) {
+ function formatArrayValue(value) {
+ var vertially = zrUtil.reduce(value, function (vertially, val, idx) {
+ var dimItem = data.getDimensionInfo(idx);
+ return vertially |= dimItem && dimItem.tooltip !== false && dimItem.tooltipName != null;
+ }, 0);
+
+ var result = [];
+ var tooltipDims = modelUtil.otherDimToDataDim(data, 'tooltip');
+
+ tooltipDims.length
+ ? zrUtil.each(tooltipDims, function (dimIdx) {
+ setEachItem(data.get(dimIdx, dataIndex), dimIdx);
+ })
+ // By default, all dims is used on tooltip.
+ : zrUtil.each(value, setEachItem);
+
+ function setEachItem(val, dimIdx) {
+ var dimInfo = data.getDimensionInfo(dimIdx);
+ // If `dimInfo.tooltip` is not set, show tooltip.
+ if (!dimInfo || dimInfo.otherDims.tooltip === false) {
+ return;
+ }
+ var dimType = dimInfo.type;
+ var valStr = (vertially ? '- ' + (dimInfo.tooltipName || dimInfo.name) + ': ' : '')
+ + (dimType === 'ordinal'
+ ? val + ''
+ : dimType === 'time'
+ ? (multipleSeries ? '' : formatUtil.formatTime('yyyy/MM/dd hh:mm:ss', val))
+ : addCommas(val)
+ );
+ valStr && result.push(encodeHTML(valStr));
+ }
+
+ return (vertially ? '
' : '') + result.join(vertially ? '
' : ', ');
+ }
+
+ var data = get(this, 'data');
+
+ var value = this.getRawValue(dataIndex);
+ var formattedValue = zrUtil.isArray(value)
+ ? formatArrayValue(value) : encodeHTML(addCommas(value));
+ var name = data.getName(dataIndex);
+
+ var color = data.getItemVisual(dataIndex, 'color');
+ if (zrUtil.isObject(color) && color.colorStops) {
+ color = (color.colorStops[0] || {}).color;
+ }
+ color = color || 'transparent';
+
+ var colorEl = formatUtil.getTooltipMarker(color);
+
+ var seriesName = this.name;
+ // FIXME
+ if (seriesName === '\0-') {
+ // Not show '-'
+ seriesName = '';
+ }
+ seriesName = seriesName
+ ? encodeHTML(seriesName) + (!multipleSeries ? '
' : ': ')
+ : '';
+ return !multipleSeries
+ ? seriesName + colorEl
+ + (name
+ ? encodeHTML(name) + ': ' + formattedValue
+ : formattedValue
+ )
+ : colorEl + seriesName + formattedValue;
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isAnimationEnabled: function () {
+ if (env.node) {
+ return false;
+ }
+
+ var animationEnabled = this.getShallow('animation');
+ if (animationEnabled) {
+ if (this.getData().count() > this.getShallow('animationThreshold')) {
+ animationEnabled = false;
+ }
+ }
+ return animationEnabled;
+ },
+
+ restoreData: function () {
+ set(this, 'data', get(this, 'dataBeforeProcessed').cloneShallow());
+ },
+
+ getColorFromPalette: function (name, scope) {
+ var ecModel = this.ecModel;
+ // PENDING
+ var color = colorPaletteMixin.getColorFromPalette.call(this, name, scope);
+ if (!color) {
+ color = ecModel.getColorFromPalette(name, scope);
+ }
+ return color;
+ },
+
+ /**
+ * Get data indices for show tooltip content. See tooltip.
+ * @abstract
+ * @param {Array.|string} dim
+ * @param {Array.} value
+ * @param {module:echarts/coord/single/SingleAxis} baseAxis
+ * @return {Object} {dataIndices, nestestValue}.
+ */
+ getAxisTooltipData: null,
+
+ /**
+ * See tooltip.
+ * @abstract
+ * @param {number} dataIndex
+ * @return {Array.} Point of tooltip. null/undefined can be returned.
+ */
+ getTooltipPosition: null
+ });
+
+ zrUtil.mixin(SeriesModel, modelUtil.dataFormatMixin);
+ zrUtil.mixin(SeriesModel, colorPaletteMixin);
+
+ module.exports = SeriesModel;
+
+
+/***/ },
+/* 79 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var Group = __webpack_require__(48);
+ var componentUtil = __webpack_require__(70);
+ var clazzUtil = __webpack_require__(13);
+
+ 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});
+
+ module.exports = Component;
+
+
+/***/ },
+/* 80 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var Group = __webpack_require__(48);
+ var componentUtil = __webpack_require__(70);
+ var clazzUtil = __webpack_require__(13);
+ var modelUtil = __webpack_require__(5);
+ var zrUtil = __webpack_require__(4);
+
+ 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 () {}
+
+ /**
+ * The view contains the given point.
+ * @interface
+ * @param {Array.} point
+ * @return {boolean}
+ */
+ // containPoint: 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) {
+ var dataIndex = modelUtil.queryDataIndex(data, payload);
+
+ if (dataIndex != null) {
+ zrUtil.each(modelUtil.normalizeToArray(dataIndex), function (dataIdx) {
+ elSetState(data.getItemGraphicEl(dataIdx), state);
+ });
+ }
+ else {
+ data.eachItemGraphicEl(function (el) {
+ elSetState(el, state);
+ });
+ }
+ }
+
+ // Enable Chart.extend.
+ clazzUtil.enableClassExtend(Chart, ['dispose']);
+
+ // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
+ clazzUtil.enableClassManagement(Chart, {registerWhenExtend: true});
+
+ module.exports = Chart;
+
+
+/***/ },
+/* 81 */
+/***/ function(module, exports) {
+
+
+
+ var lib = {};
+
+ var ORIGIN_METHOD = '\0__throttleOriginMethod';
+ var RATE = '\0__throttleRate';
+ var THROTTLE_TYPE = '\0__throttleType';
+
+ /**
+ * @public
+ * @param {(Function)} fn
+ * @param {number} [delay=0] Unit: ms.
+ * @param {boolean} [debounce=false]
+ * true: If call interval less than `delay`, only the last call works.
+ * false: If call interval less than `delay, call works on fixed rate.
+ * @return {(Function)} throttled fn.
+ */
+ lib.throttle = function (fn, delay, debounce) {
+
+ var currCall;
+ var lastCall = 0;
+ var lastExec = 0;
+ var timer = null;
+ var diff;
+ var scope;
+ var args;
+ var debounceNextCall;
+
+ delay = delay || 0;
+
+ function exec() {
+ lastExec = (new Date()).getTime();
+ timer = null;
+ fn.apply(scope, args || []);
+ }
+
+ var cb = function () {
+ currCall = (new Date()).getTime();
+ scope = this;
+ args = arguments;
+ var thisDelay = debounceNextCall || delay;
+ var thisDebounce = debounceNextCall || debounce;
+ debounceNextCall = null;
+ diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;
+
+ clearTimeout(timer);
+
+ if (thisDebounce) {
+ timer = setTimeout(exec, thisDelay);
+ }
+ else {
+ if (diff >= 0) {
+ exec();
+ }
+ else {
+ timer = setTimeout(exec, -diff);
+ }
+ }
+
+ lastCall = currCall;
+ };
+
+ /**
+ * Clear throttle.
+ * @public
+ */
+ cb.clear = function () {
+ if (timer) {
+ clearTimeout(timer);
+ timer = null;
+ }
+ };
+
+ /**
+ * Enable debounce once.
+ */
+ cb.debounceNextCall = function (debounceDelay) {
+ debounceNextCall = debounceDelay;
+ };
+
+ return cb;
+ };
+
+ /**
+ * Create throttle method or update throttle rate.
+ *
+ * @example
+ * ComponentView.prototype.render = function () {
+ * ...
+ * throttle.createOrUpdate(
+ * this,
+ * '_dispatchAction',
+ * this.model.get('throttle'),
+ * 'fixRate'
+ * );
+ * };
+ * ComponentView.prototype.remove = function () {
+ * throttle.clear(this, '_dispatchAction');
+ * };
+ * ComponentView.prototype.dispose = function () {
+ * throttle.clear(this, '_dispatchAction');
+ * };
+ *
+ * @public
+ * @param {Object} obj
+ * @param {string} fnAttr
+ * @param {number} [rate]
+ * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce'
+ * @return {Function} throttled function.
+ */
+ lib.createOrUpdate = function (obj, fnAttr, rate, throttleType) {
+ var fn = obj[fnAttr];
+
+ if (!fn) {
+ return;
+ }
+
+ var originFn = fn[ORIGIN_METHOD] || fn;
+ var lastThrottleType = fn[THROTTLE_TYPE];
+ var lastRate = fn[RATE];
+
+ if (lastRate !== rate || lastThrottleType !== throttleType) {
+ if (rate == null || !throttleType) {
+ return (obj[fnAttr] = originFn);
+ }
+
+ fn = obj[fnAttr] = lib.throttle(
+ originFn, rate, throttleType === 'debounce'
+ );
+ fn[ORIGIN_METHOD] = originFn;
+ fn[THROTTLE_TYPE] = throttleType;
+ fn[RATE] = rate;
+ }
+
+ return fn;
+ };
+
+ /**
+ * Clear throttle. Example see throttle.createOrUpdate.
+ *
+ * @public
+ * @param {Object} obj
+ * @param {string} fnAttr
+ */
+ lib.clear = function (obj, fnAttr) {
+ var fn = obj[fnAttr];
+ if (fn && fn[ORIGIN_METHOD]) {
+ obj[fnAttr] = fn[ORIGIN_METHOD];
+ }
+ };
+
+ module.exports = lib;
+
+
+
+/***/ },
+/* 82 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /*!
+ * ZRender, a high performance 2d drawing library.
+ *
+ * Copyright (c) 2013, Baidu Inc.
+ * All rights reserved.
+ *
+ * LICENSE
+ * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
+ */
+ // Global defines
+
+ var guid = __webpack_require__(24);
+ var env = __webpack_require__(2);
+ var zrUtil = __webpack_require__(4);
+
+ var Handler = __webpack_require__(83);
+ var Storage = __webpack_require__(85);
+ var Animation = __webpack_require__(87);
+ var HandlerProxy = __webpack_require__(90);
+
+ var useVML = !env.canvasSupported;
+
+ var painterCtors = {
+ canvas: __webpack_require__(92)
+ };
+
+ var instances = {}; // ZRender实例map索引
+
+ var zrender = {};
+
+ /**
+ * @type {string}
+ */
+ zrender.version = '3.5.2';
+
+ /**
+ * Initializing a zrender instance
+ * @param {HTMLElement} dom
+ * @param {Object} opts
+ * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
+ * @param {number} [opts.devicePixelRatio]
+ * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
+ * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
+ * @return {module:zrender/ZRender}
+ */
+ zrender.init = function(dom, opts) {
+ var zr = new ZRender(guid(), dom, opts);
+ instances[zr.id] = zr;
+ return zr;
+ };
+
+ /**
+ * Dispose zrender instance
+ * @param {module:zrender/ZRender} zr
+ */
+ zrender.dispose = function (zr) {
+ if (zr) {
+ zr.dispose();
+ }
+ else {
+ for (var key in instances) {
+ if (instances.hasOwnProperty(key)) {
+ instances[key].dispose();
+ }
+ }
+ instances = {};
+ }
+
+ return zrender;
+ };
+
+ /**
+ * Get zrender instance by id
+ * @param {string} id zrender instance id
+ * @return {module:zrender/ZRender}
+ */
+ zrender.getInstance = function (id) {
+ return instances[id];
+ };
+
+ zrender.registerPainter = function (name, Ctor) {
+ painterCtors[name] = Ctor;
+ };
+
+ function delInstance(id) {
+ delete instances[id];
+ }
+
+ /**
+ * @module zrender/ZRender
+ */
+ /**
+ * @constructor
+ * @alias module:zrender/ZRender
+ * @param {string} id
+ * @param {HTMLDomElement} dom
+ * @param {Object} opts
+ * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
+ * @param {number} [opts.devicePixelRatio]
+ * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
+ * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
+ */
+ var ZRender = function(id, dom, opts) {
+
+ opts = opts || {};
+
+ /**
+ * @type {HTMLDomElement}
+ */
+ this.dom = dom;
+
+ /**
+ * @type {string}
+ */
+ this.id = id;
+
+ var self = this;
+ var storage = new Storage();
+
+ var rendererType = opts.renderer;
+ // TODO WebGL
+ if (useVML) {
+ if (!painterCtors.vml) {
+ throw new Error('You need to require \'zrender/vml/vml\' to support IE8');
+ }
+ rendererType = 'vml';
+ }
+ else if (!rendererType || !painterCtors[rendererType]) {
+ rendererType = 'canvas';
+ }
+ var painter = new painterCtors[rendererType](dom, storage, opts);
+
+ this.storage = storage;
+ this.painter = painter;
+
+ var handerProxy = !env.node ? new HandlerProxy(painter.getViewportRoot()) : null;
+ this.handler = new Handler(storage, painter, handerProxy, painter.root);
+
+ /**
+ * @type {module:zrender/animation/Animation}
+ */
+ this.animation = new Animation({
+ stage: {
+ update: zrUtil.bind(this.flush, this)
+ }
+ });
+ this.animation.start();
+
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this._needsRefresh;
+
+ // 修改 storage.delFromStorage, 每次删除元素之前删除动画
+ // FIXME 有点ugly
+ var oldDelFromStorage = storage.delFromStorage;
+ var oldAddToStorage = storage.addToStorage;
+
+ storage.delFromStorage = function (el) {
+ oldDelFromStorage.call(storage, el);
+
+ el && el.removeSelfFromZr(self);
+ };
+
+ storage.addToStorage = function (el) {
+ oldAddToStorage.call(storage, el);
+
+ el.addSelfToZr(self);
+ };
+ };
+
+ ZRender.prototype = {
+
+ constructor: ZRender,
+ /**
+ * 获取实例唯一标识
+ * @return {string}
+ */
+ getId: function () {
+ return this.id;
+ },
+
+ /**
+ * 添加元素
+ * @param {module:zrender/Element} el
+ */
+ add: function (el) {
+ this.storage.addRoot(el);
+ this._needsRefresh = true;
+ },
+
+ /**
+ * 删除元素
+ * @param {module:zrender/Element} el
+ */
+ remove: function (el) {
+ this.storage.delRoot(el);
+ this._needsRefresh = true;
+ },
+
+ /**
+ * Change configuration of layer
+ * @param {string} zLevel
+ * @param {Object} config
+ * @param {string} [config.clearColor=0] Clear color
+ * @param {string} [config.motionBlur=false] If enable motion blur
+ * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer
+ */
+ configLayer: function (zLevel, config) {
+ this.painter.configLayer(zLevel, config);
+ this._needsRefresh = true;
+ },
+
+ /**
+ * Repaint the canvas immediately
+ */
+ refreshImmediately: function () {
+ // Clear needsRefresh ahead to avoid something wrong happens in refresh
+ // Or it will cause zrender refreshes again and again.
+ this._needsRefresh = false;
+ this.painter.refresh();
+ /**
+ * Avoid trigger zr.refresh in Element#beforeUpdate hook
+ */
+ this._needsRefresh = false;
+ },
+
+ /**
+ * Mark and repaint the canvas in the next frame of browser
+ */
+ refresh: function() {
+ this._needsRefresh = true;
+ },
+
+ /**
+ * Perform all refresh
+ */
+ flush: function () {
+ if (this._needsRefresh) {
+ this.refreshImmediately();
+ }
+ if (this._needsRefreshHover) {
+ this.refreshHoverImmediately();
+ }
+ },
+
+ /**
+ * Add element to hover layer
+ * @param {module:zrender/Element} el
+ * @param {Object} style
+ */
+ addHover: function (el, style) {
+ if (this.painter.addHover) {
+ this.painter.addHover(el, style);
+ this.refreshHover();
+ }
+ },
+
+ /**
+ * Add element from hover layer
+ * @param {module:zrender/Element} el
+ */
+ removeHover: function (el) {
+ if (this.painter.removeHover) {
+ this.painter.removeHover(el);
+ this.refreshHover();
+ }
+ },
+
+ /**
+ * Clear all hover elements in hover layer
+ * @param {module:zrender/Element} el
+ */
+ clearHover: function () {
+ if (this.painter.clearHover) {
+ this.painter.clearHover();
+ this.refreshHover();
+ }
+ },
+
+ /**
+ * Refresh hover in next frame
+ */
+ refreshHover: function () {
+ this._needsRefreshHover = true;
+ },
+
+ /**
+ * Refresh hover immediately
+ */
+ refreshHoverImmediately: function () {
+ this._needsRefreshHover = false;
+ this.painter.refreshHover && this.painter.refreshHover();
+ },
+
+ /**
+ * Resize the canvas.
+ * Should be invoked when container size is changed
+ * @param {Object} [opts]
+ * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
+ * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
+ */
+ resize: function(opts) {
+ opts = opts || {};
+ this.painter.resize(opts.width, opts.height);
+ this.handler.resize();
+ },
+
+ /**
+ * Stop and clear all animation immediately
+ */
+ clearAnimation: function () {
+ this.animation.clear();
+ },
+
+ /**
+ * Get container width
+ */
+ getWidth: function() {
+ return this.painter.getWidth();
+ },
+
+ /**
+ * Get container height
+ */
+ getHeight: function() {
+ return this.painter.getHeight();
+ },
+
+ /**
+ * Export the canvas as Base64 URL
+ * @param {string} type
+ * @param {string} [backgroundColor='#fff']
+ * @return {string} Base64 URL
+ */
+ // toDataURL: function(type, backgroundColor) {
+ // return this.painter.getRenderedCanvas({
+ // backgroundColor: backgroundColor
+ // }).toDataURL(type);
+ // },
+
+ /**
+ * Converting a path to image.
+ * It has much better performance of drawing image rather than drawing a vector path.
+ * @param {module:zrender/graphic/Path} e
+ * @param {number} width
+ * @param {number} height
+ */
+ pathToImage: function(e, dpr) {
+ return this.painter.pathToImage(e, dpr);
+ },
+
+ /**
+ * Set default cursor
+ * @param {string} [cursorStyle='default'] 例如 crosshair
+ */
+ setCursorStyle: function (cursorStyle) {
+ this.handler.setCursorStyle(cursorStyle);
+ },
+
+ /**
+ * Find hovered element
+ * @param {number} x
+ * @param {number} y
+ * @return {Object} {target, topTarget}
+ */
+ findHover: function (x, y) {
+ return this.handler.findHover(x, y);
+ },
+
+ /**
+ * Bind event
+ *
+ * @param {string} eventName Event name
+ * @param {Function} eventHandler Handler function
+ * @param {Object} [context] Context object
+ */
+ on: function(eventName, eventHandler, context) {
+ this.handler.on(eventName, eventHandler, context);
+ },
+
+ /**
+ * Unbind event
+ * @param {string} eventName Event name
+ * @param {Function} [eventHandler] Handler function
+ */
+ off: function(eventName, eventHandler) {
+ this.handler.off(eventName, eventHandler);
+ },
+
+ /**
+ * Trigger event manually
+ *
+ * @param {string} eventName Event name
+ * @param {event=} event Event object
+ */
+ trigger: function (eventName, event) {
+ this.handler.trigger(eventName, event);
+ },
+
+
+ /**
+ * Clear all objects and the canvas.
+ */
+ clear: function () {
+ this.storage.delRoot();
+ this.painter.clear();
+ },
+
+ /**
+ * Dispose self.
+ */
+ dispose: function () {
+ this.animation.stop();
+
+ this.clear();
+ this.storage.dispose();
+ this.painter.dispose();
+ this.handler.dispose();
+
+ this.animation =
+ this.storage =
+ this.painter =
+ this.handler = null;
+
+ delInstance(this.id);
+ }
+ };
+
+ module.exports = zrender;
+
+
+
+/***/ },
+/* 83 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * Handler
+ * @module zrender/Handler
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * errorrik (errorrik@gmail.com)
+ * pissang (shenyi.914@gmail.com)
+ */
+
+
+ var util = __webpack_require__(4);
+ var Draggable = __webpack_require__(84);
+
+ var Eventful = __webpack_require__(25);
+
+ var SILENT = 'silent';
+
+ function makeEventPacket(eveType, targetInfo, event) {
+ return {
+ type: eveType,
+ event: event,
+ // target can only be an element that is not silent.
+ target: targetInfo.target,
+ // topTarget can be a silent element.
+ topTarget: targetInfo.topTarget,
+ cancelBubble: false,
+ offsetX: event.zrX,
+ offsetY: event.zrY,
+ gestureEvent: event.gestureEvent,
+ pinchX: event.pinchX,
+ pinchY: event.pinchY,
+ pinchScale: event.pinchScale,
+ wheelDelta: event.zrDelta,
+ zrByTouch: event.zrByTouch
+ };
+ }
+
+ function EmptyProxy () {}
+ EmptyProxy.prototype.dispose = function () {};
+
+ var handlerNames = [
+ 'click', 'dblclick', 'mousewheel', 'mouseout',
+ 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
+ ];
+ /**
+ * @alias module:zrender/Handler
+ * @constructor
+ * @extends module:zrender/mixin/Eventful
+ * @param {module:zrender/Storage} storage Storage instance.
+ * @param {module:zrender/Painter} painter Painter instance.
+ * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance.
+ * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()).
+ */
+ var Handler = function(storage, painter, proxy, painterRoot) {
+ Eventful.call(this);
+
+ this.storage = storage;
+
+ this.painter = painter;
+
+ this.painterRoot = painterRoot;
+
+ proxy = proxy || new EmptyProxy();
+
+ /**
+ * Proxy of event. can be Dom, WebGLSurface, etc.
+ */
+ this.proxy = proxy;
+
+ // Attach handler
+ proxy.handler = this;
+
+ /**
+ * {target, topTarget}
+ * @private
+ * @type {Object}
+ */
+ this._hovered = {};
+
+ /**
+ * @private
+ * @type {Date}
+ */
+ this._lastTouchMoment;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this._lastX;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this._lastY;
+
+
+ Draggable.call(this);
+
+ util.each(handlerNames, function (name) {
+ proxy.on && proxy.on(name, this[name], this);
+ }, this);
+ };
+
+ Handler.prototype = {
+
+ constructor: Handler,
+
+ mousemove: function (event) {
+ var x = event.zrX;
+ var y = event.zrY;
+
+ var lastHovered = this._hovered;
+ var hovered = this._hovered = this.findHover(x, y);
+ var hoveredTarget = hovered.target;
+ var lastHoveredTarget = lastHovered.target;
+
+ var proxy = this.proxy;
+ proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default');
+
+ // Mouse out on previous hovered element
+ if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget && lastHoveredTarget.__zr) {
+ this.dispatchToElement(lastHovered, 'mouseout', event);
+ }
+
+ // Mouse moving on one element
+ this.dispatchToElement(hovered, 'mousemove', event);
+
+ // Mouse over on a new element
+ if (hoveredTarget && hoveredTarget !== lastHoveredTarget) {
+ this.dispatchToElement(hovered, 'mouseover', event);
+ }
+ },
+
+ mouseout: function (event) {
+ this.dispatchToElement(this._hovered, 'mouseout', event);
+
+ // There might be some doms created by upper layer application
+ // at the same level of painter.getViewportRoot() (e.g., tooltip
+ // dom created by echarts), where 'globalout' event should not
+ // be triggered when mouse enters these doms. (But 'mouseout'
+ // should be triggered at the original hovered element as usual).
+ var element = event.toElement || event.relatedTarget;
+ var innerDom;
+ do {
+ element = element && element.parentNode;
+ }
+ while (element && element.nodeType != 9 && !(
+ innerDom = element === this.painterRoot
+ ));
+
+ !innerDom && this.trigger('globalout', {event: event});
+ },
+
+ /**
+ * Resize
+ */
+ resize: function (event) {
+ this._hovered = {};
+ },
+
+ /**
+ * Dispatch event
+ * @param {string} eventName
+ * @param {event=} eventArgs
+ */
+ dispatch: function (eventName, eventArgs) {
+ var handler = this[eventName];
+ handler && handler.call(this, eventArgs);
+ },
+
+ /**
+ * Dispose
+ */
+ dispose: function () {
+
+ this.proxy.dispose();
+
+ this.storage =
+ this.proxy =
+ this.painter = null;
+ },
+
+ /**
+ * 设置默认的cursor style
+ * @param {string} [cursorStyle='default'] 例如 crosshair
+ */
+ setCursorStyle: function (cursorStyle) {
+ var proxy = this.proxy;
+ proxy.setCursor && proxy.setCursor(cursorStyle);
+ },
+
+ /**
+ * 事件分发代理
+ *
+ * @private
+ * @param {Object} targetInfo {target, topTarget} 目标图形元素
+ * @param {string} eventName 事件名称
+ * @param {Object} event 事件对象
+ */
+ dispatchToElement: function (targetInfo, eventName, event) {
+ targetInfo = targetInfo || {};
+ var eventHandler = 'on' + eventName;
+ var eventPacket = makeEventPacket(eventName, targetInfo, event);
+
+ var el = targetInfo.target;
+ while (el) {
+ el[eventHandler]
+ && (eventPacket.cancelBubble = el[eventHandler].call(el, eventPacket));
+
+ el.trigger(eventName, eventPacket);
+
+ el = el.parent;
+
+ if (eventPacket.cancelBubble) {
+ break;
+ }
+ }
+
+ if (!eventPacket.cancelBubble) {
+ // 冒泡到顶级 zrender 对象
+ this.trigger(eventName, eventPacket);
+ // 分发事件到用户自定义层
+ // 用户有可能在全局 click 事件中 dispose,所以需要判断下 painter 是否存在
+ this.painter && this.painter.eachOtherLayer(function (layer) {
+ if (typeof(layer[eventHandler]) == 'function') {
+ layer[eventHandler].call(layer, eventPacket);
+ }
+ if (layer.trigger) {
+ layer.trigger(eventName, eventPacket);
+ }
+ });
+ }
+ },
+
+ /**
+ * @private
+ * @param {number} x
+ * @param {number} y
+ * @param {module:zrender/graphic/Displayable} exclude
+ * @return {model:zrender/Element}
+ * @method
+ */
+ findHover: function(x, y, exclude) {
+ var list = this.storage.getDisplayList();
+ var out = {};
+
+ for (var i = list.length - 1; i >= 0 ; i--) {
+ var hoverCheckResult;
+ if (list[i] !== exclude
+ // getDisplayList may include ignored item in VML mode
+ && !list[i].ignore
+ && (hoverCheckResult = isHover(list[i], x, y))
+ ) {
+ !out.topTarget && (out.topTarget = list[i]);
+ if (hoverCheckResult !== SILENT) {
+ out.target = list[i];
+ break;
+ }
+ }
+ }
+
+ return out;
+ }
+ };
+
+ // Common handlers
+ util.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
+ Handler.prototype[name] = function (event) {
+ // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover
+ var hovered = this.findHover(event.zrX, event.zrY);
+ var hoveredTarget = hovered.target;
+
+ if (name === 'mousedown') {
+ this._downel = hoveredTarget;
+ // In case click triggered before mouseup
+ this._upel = hoveredTarget;
+ }
+ else if (name === 'mosueup') {
+ this._upel = hoveredTarget;
+ }
+ else if (name === 'click') {
+ if (this._downel !== this._upel) {
+ return;
+ }
+ }
+
+ this.dispatchToElement(hovered, name, event);
+ };
+ });
+
+ function isHover(displayable, x, y) {
+ if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) {
+ var el = displayable;
+ var isSilent;
+ while (el) {
+ // If clipped by ancestor.
+ // FIXME: If clipPath has neither stroke nor fill,
+ // el.clipPath.contain(x, y) will always return false.
+ if (el.clipPath && !el.clipPath.contain(x, y)) {
+ return false;
+ }
+ if (el.silent) {
+ isSilent = true;
+ }
+ el = el.parent;
+ }
+ return isSilent ? SILENT : true;
+ }
+
+ return false;
+ }
+
+ util.mixin(Handler, Eventful);
+ util.mixin(Handler, Draggable);
+
+ module.exports = Handler;
+
+
+
+/***/ },
+/* 84 */
+/***/ function(module, exports) {
+
+ // TODO Draggable for group
+ // FIXME Draggable on element which has parent rotation or scale
+
+ function Draggable() {
+
+ this.on('mousedown', this._dragStart, this);
+ this.on('mousemove', this._drag, this);
+ this.on('mouseup', this._dragEnd, this);
+ this.on('globalout', this._dragEnd, this);
+ // this._dropTarget = null;
+ // this._draggingTarget = null;
+
+ // this._x = 0;
+ // this._y = 0;
+ }
+
+ Draggable.prototype = {
+
+ constructor: Draggable,
+
+ _dragStart: function (e) {
+ var draggingTarget = e.target;
+ if (draggingTarget && draggingTarget.draggable) {
+ this._draggingTarget = draggingTarget;
+ draggingTarget.dragging = true;
+ this._x = e.offsetX;
+ this._y = e.offsetY;
+
+ this.dispatchToElement(param(draggingTarget, e), 'dragstart', e.event);
+ }
+ },
+
+ _drag: function (e) {
+ var draggingTarget = this._draggingTarget;
+ if (draggingTarget) {
+
+ var x = e.offsetX;
+ var y = e.offsetY;
+
+ var dx = x - this._x;
+ var dy = y - this._y;
+ this._x = x;
+ this._y = y;
+
+ draggingTarget.drift(dx, dy, e);
+ this.dispatchToElement(param(draggingTarget, e), 'drag', e.event);
+
+ var dropTarget = this.findHover(x, y, draggingTarget).target;
+ var lastDropTarget = this._dropTarget;
+ this._dropTarget = dropTarget;
+
+ if (draggingTarget !== dropTarget) {
+ if (lastDropTarget && dropTarget !== lastDropTarget) {
+ this.dispatchToElement(param(lastDropTarget, e), 'dragleave', e.event);
+ }
+ if (dropTarget && dropTarget !== lastDropTarget) {
+ this.dispatchToElement(param(dropTarget, e), 'dragenter', e.event);
+ }
+ }
+ }
+ },
+
+ _dragEnd: function (e) {
+ var draggingTarget = this._draggingTarget;
+
+ if (draggingTarget) {
+ draggingTarget.dragging = false;
+ }
+
+ this.dispatchToElement(param(draggingTarget, e), 'dragend', e.event);
+
+ if (this._dropTarget) {
+ this.dispatchToElement(param(this._dropTarget, e), 'drop', e.event);
+ }
+
+ this._draggingTarget = null;
+ this._dropTarget = null;
+ }
+
+ };
+
+ function param(target, e) {
+ return {target: target, topTarget: e && e.topTarget};
+ }
+
+ module.exports = Draggable;
+
+
+/***/ },
+/* 85 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * Storage内容仓库模块
+ * @module zrender/Storage
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * @author errorrik (errorrik@gmail.com)
+ * @author pissang (https://github.com/pissang/)
+ */
+
+
+ var util = __webpack_require__(4);
+ var env = __webpack_require__(2);
+
+ var Group = __webpack_require__(48);
+
+ // Use timsort because in most case elements are partially sorted
+ // https://jsfiddle.net/pissang/jr4x7mdm/8/
+ var timsort = __webpack_require__(86);
+
+ function shapeCompareFunc(a, b) {
+ if (a.zlevel === b.zlevel) {
+ if (a.z === b.z) {
+ // if (a.z2 === b.z2) {
+ // // FIXME Slow has renderidx compare
+ // // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement
+ // // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012
+ // return a.__renderidx - b.__renderidx;
+ // }
+ return a.z2 - b.z2;
+ }
+ return a.z - b.z;
+ }
+ return a.zlevel - b.zlevel;
+ }
+ /**
+ * 内容仓库 (M)
+ * @alias module:zrender/Storage
+ * @constructor
+ */
+ var Storage = function () {
+ this._roots = [];
+
+ this._displayList = [];
+
+ this._displayListLen = 0;
+ };
+
+ Storage.prototype = {
+
+ constructor: Storage,
+
+ /**
+ * @param {Function} cb
+ *
+ */
+ traverse: function (cb, context) {
+ for (var i = 0; i < this._roots.length; i++) {
+ this._roots[i].traverse(cb, context);
+ }
+ },
+
+ /**
+ * 返回所有图形的绘制队列
+ * @param {boolean} [update=false] 是否在返回前更新该数组
+ * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效
+ *
+ * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}
+ * @return {Array.}
+ */
+ getDisplayList: function (update, includeIgnore) {
+ includeIgnore = includeIgnore || false;
+ if (update) {
+ this.updateDisplayList(includeIgnore);
+ }
+ return this._displayList;
+ },
+
+ /**
+ * 更新图形的绘制队列。
+ * 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,
+ * 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列
+ * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组
+ */
+ updateDisplayList: function (includeIgnore) {
+ this._displayListLen = 0;
+ var roots = this._roots;
+ var displayList = this._displayList;
+ for (var i = 0, len = roots.length; i < len; i++) {
+ this._updateAndAddDisplayable(roots[i], null, includeIgnore);
+ }
+ displayList.length = this._displayListLen;
+
+ // for (var i = 0, len = displayList.length; i < len; i++) {
+ // displayList[i].__renderidx = i;
+ // }
+
+ // displayList.sort(shapeCompareFunc);
+ env.canvasSupported && timsort(displayList, shapeCompareFunc);
+ },
+
+ _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) {
+
+ if (el.ignore && !includeIgnore) {
+ return;
+ }
+
+ el.beforeUpdate();
+
+ if (el.__dirty) {
+
+ el.update();
+
+ }
+
+ el.afterUpdate();
+
+ var userSetClipPath = el.clipPath;
+ if (userSetClipPath) {
+
+ // FIXME 效率影响
+ if (clipPaths) {
+ clipPaths = clipPaths.slice();
+ }
+ else {
+ clipPaths = [];
+ }
+
+ var currentClipPath = userSetClipPath;
+ var parentClipPath = el;
+ // Recursively add clip path
+ while (currentClipPath) {
+ // clipPath 的变换是基于使用这个 clipPath 的元素
+ currentClipPath.parent = parentClipPath;
+ currentClipPath.updateTransform();
+
+ clipPaths.push(currentClipPath);
+
+ parentClipPath = currentClipPath;
+ currentClipPath = currentClipPath.clipPath;
+ }
+ }
+
+ if (el.isGroup) {
+ var children = el._children;
+
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+
+ // Force to mark as dirty if group is dirty
+ // FIXME __dirtyPath ?
+ if (el.__dirty) {
+ child.__dirty = true;
+ }
+
+ this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
+ }
+
+ // Mark group clean here
+ el.__dirty = false;
+
+ }
+ else {
+ el.__clipPaths = clipPaths;
+
+ this._displayList[this._displayListLen++] = el;
+ }
+ },
+
+ /**
+ * 添加图形(Shape)或者组(Group)到根节点
+ * @param {module:zrender/Element} el
+ */
+ addRoot: function (el) {
+ if (el.__storage === this) {
+ return;
+ }
+
+ if (el instanceof Group) {
+ el.addChildrenToStorage(this);
+ }
+
+ this.addToStorage(el);
+ this._roots.push(el);
+ },
+
+ /**
+ * 删除指定的图形(Shape)或者组(Group)
+ * @param {string|Array.} [el] 如果为空清空整个Storage
+ */
+ delRoot: function (el) {
+ if (el == null) {
+ // 不指定el清空
+ for (var i = 0; i < this._roots.length; i++) {
+ var root = this._roots[i];
+ if (root instanceof Group) {
+ root.delChildrenFromStorage(this);
+ }
+ }
+
+ this._roots = [];
+ this._displayList = [];
+ this._displayListLen = 0;
+
+ return;
+ }
+
+ if (el instanceof Array) {
+ for (var i = 0, l = el.length; i < l; i++) {
+ this.delRoot(el[i]);
+ }
+ return;
+ }
+
+
+ var idx = util.indexOf(this._roots, el);
+ if (idx >= 0) {
+ this.delFromStorage(el);
+ this._roots.splice(idx, 1);
+ if (el instanceof Group) {
+ el.delChildrenFromStorage(this);
+ }
+ }
+ },
+
+ addToStorage: function (el) {
+ el.__storage = this;
+ el.dirty(false);
+
+ return this;
+ },
+
+ delFromStorage: function (el) {
+ if (el) {
+ el.__storage = null;
+ }
+
+ return this;
+ },
+
+ /**
+ * 清空并且释放Storage
+ */
+ dispose: function () {
+ this._renderList =
+ this._roots = null;
+ },
+
+ displayableSortFunc: shapeCompareFunc
+ };
+
+ module.exports = Storage;
+
+
+
+/***/ },
+/* 86 */
+/***/ function(module, exports) {
+
+ // https://github.com/mziccard/node-timsort
+
+ var DEFAULT_MIN_MERGE = 32;
+
+ var DEFAULT_MIN_GALLOPING = 7;
+
+ var DEFAULT_TMP_STORAGE_LENGTH = 256;
+
+ function minRunLength(n) {
+ var r = 0;
+
+ while (n >= DEFAULT_MIN_MERGE) {
+ r |= n & 1;
+ n >>= 1;
+ }
+
+ return n + r;
+ }
+
+ function makeAscendingRun(array, lo, hi, compare) {
+ var runHi = lo + 1;
+
+ if (runHi === hi) {
+ return 1;
+ }
+
+ if (compare(array[runHi++], array[lo]) < 0) {
+ while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
+ runHi++;
+ }
+
+ reverseRun(array, lo, runHi);
+ }
+ else {
+ while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
+ runHi++;
+ }
+ }
+
+ return runHi - lo;
+ }
+
+ function reverseRun(array, lo, hi) {
+ hi--;
+
+ while (lo < hi) {
+ var t = array[lo];
+ array[lo++] = array[hi];
+ array[hi--] = t;
+ }
+ }
+
+ function binaryInsertionSort(array, lo, hi, start, compare) {
+ if (start === lo) {
+ start++;
+ }
+
+ for (; start < hi; start++) {
+ var pivot = array[start];
+
+ var left = lo;
+ var right = start;
+ var mid;
+
+ while (left < right) {
+ mid = left + right >>> 1;
+
+ if (compare(pivot, array[mid]) < 0) {
+ right = mid;
+ }
+ else {
+ left = mid + 1;
+ }
+ }
+
+ var n = start - left;
+
+ switch (n) {
+ case 3:
+ array[left + 3] = array[left + 2];
+
+ case 2:
+ array[left + 2] = array[left + 1];
+
+ case 1:
+ array[left + 1] = array[left];
+ break;
+ default:
+ while (n > 0) {
+ array[left + n] = array[left + n - 1];
+ n--;
+ }
+ }
+
+ array[left] = pivot;
+ }
+ }
+
+ function gallopLeft(value, array, start, length, hint, compare) {
+ var lastOffset = 0;
+ var maxOffset = 0;
+ var offset = 1;
+
+ if (compare(value, array[start + hint]) > 0) {
+ maxOffset = length - hint;
+
+ while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
+ lastOffset = offset;
+ offset = (offset << 1) + 1;
+
+ if (offset <= 0) {
+ offset = maxOffset;
+ }
+ }
+
+ if (offset > maxOffset) {
+ offset = maxOffset;
+ }
+
+ lastOffset += hint;
+ offset += hint;
+ }
+ else {
+ maxOffset = hint + 1;
+ while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
+ lastOffset = offset;
+ offset = (offset << 1) + 1;
+
+ if (offset <= 0) {
+ offset = maxOffset;
+ }
+ }
+ if (offset > maxOffset) {
+ offset = maxOffset;
+ }
+
+ var tmp = lastOffset;
+ lastOffset = hint - offset;
+ offset = hint - tmp;
+ }
+
+ lastOffset++;
+ while (lastOffset < offset) {
+ var m = lastOffset + (offset - lastOffset >>> 1);
+
+ if (compare(value, array[start + m]) > 0) {
+ lastOffset = m + 1;
+ }
+ else {
+ offset = m;
+ }
+ }
+ return offset;
+ }
+
+ function gallopRight(value, array, start, length, hint, compare) {
+ var lastOffset = 0;
+ var maxOffset = 0;
+ var offset = 1;
+
+ if (compare(value, array[start + hint]) < 0) {
+ maxOffset = hint + 1;
+
+ while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
+ lastOffset = offset;
+ offset = (offset << 1) + 1;
+
+ if (offset <= 0) {
+ offset = maxOffset;
+ }
+ }
+
+ if (offset > maxOffset) {
+ offset = maxOffset;
+ }
+
+ var tmp = lastOffset;
+ lastOffset = hint - offset;
+ offset = hint - tmp;
+ }
+ else {
+ maxOffset = length - hint;
+
+ while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
+ lastOffset = offset;
+ offset = (offset << 1) + 1;
+
+ if (offset <= 0) {
+ offset = maxOffset;
+ }
+ }
+
+ if (offset > maxOffset) {
+ offset = maxOffset;
+ }
+
+ lastOffset += hint;
+ offset += hint;
+ }
+
+ lastOffset++;
+
+ while (lastOffset < offset) {
+ var m = lastOffset + (offset - lastOffset >>> 1);
+
+ if (compare(value, array[start + m]) < 0) {
+ offset = m;
+ }
+ else {
+ lastOffset = m + 1;
+ }
+ }
+
+ return offset;
+ }
+
+ function TimSort(array, compare) {
+ var minGallop = DEFAULT_MIN_GALLOPING;
+ var length = 0;
+ var tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
+ var stackLength = 0;
+ var runStart;
+ var runLength;
+ var stackSize = 0;
+
+ length = array.length;
+
+ if (length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
+ tmpStorageLength = length >>> 1;
+ }
+
+ var tmp = [];
+
+ stackLength = length < 120 ? 5 : length < 1542 ? 10 : length < 119151 ? 19 : 40;
+
+ runStart = [];
+ runLength = [];
+
+ function pushRun(_runStart, _runLength) {
+ runStart[stackSize] = _runStart;
+ runLength[stackSize] = _runLength;
+ stackSize += 1;
+ }
+
+ function mergeRuns() {
+ while (stackSize > 1) {
+ var n = stackSize - 2;
+
+ if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) {
+ if (runLength[n - 1] < runLength[n + 1]) {
+ n--;
+ }
+ }
+ else if (runLength[n] > runLength[n + 1]) {
+ break;
+ }
+ mergeAt(n);
+ }
+ }
+
+ function forceMergeRuns() {
+ while (stackSize > 1) {
+ var n = stackSize - 2;
+
+ if (n > 0 && runLength[n - 1] < runLength[n + 1]) {
+ n--;
+ }
+
+ mergeAt(n);
+ }
+ }
+
+ function mergeAt(i) {
+ var start1 = runStart[i];
+ var length1 = runLength[i];
+ var start2 = runStart[i + 1];
+ var length2 = runLength[i + 1];
+
+ runLength[i] = length1 + length2;
+
+ if (i === stackSize - 3) {
+ runStart[i + 1] = runStart[i + 2];
+ runLength[i + 1] = runLength[i + 2];
+ }
+
+ stackSize--;
+
+ var k = gallopRight(array[start2], array, start1, length1, 0, compare);
+ start1 += k;
+ length1 -= k;
+
+ if (length1 === 0) {
+ return;
+ }
+
+ length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
+
+ if (length2 === 0) {
+ return;
+ }
+
+ if (length1 <= length2) {
+ mergeLow(start1, length1, start2, length2);
+ }
+ else {
+ mergeHigh(start1, length1, start2, length2);
+ }
+ }
+
+ function mergeLow(start1, length1, start2, length2) {
+ var i = 0;
+
+ for (i = 0; i < length1; i++) {
+ tmp[i] = array[start1 + i];
+ }
+
+ var cursor1 = 0;
+ var cursor2 = start2;
+ var dest = start1;
+
+ array[dest++] = array[cursor2++];
+
+ if (--length2 === 0) {
+ for (i = 0; i < length1; i++) {
+ array[dest + i] = tmp[cursor1 + i];
+ }
+ return;
+ }
+
+ if (length1 === 1) {
+ for (i = 0; i < length2; i++) {
+ array[dest + i] = array[cursor2 + i];
+ }
+ array[dest + length2] = tmp[cursor1];
+ return;
+ }
+
+ var _minGallop = minGallop;
+ var count1, count2, exit;
+
+ while (1) {
+ count1 = 0;
+ count2 = 0;
+ exit = false;
+
+ do {
+ if (compare(array[cursor2], tmp[cursor1]) < 0) {
+ array[dest++] = array[cursor2++];
+ count2++;
+ count1 = 0;
+
+ if (--length2 === 0) {
+ exit = true;
+ break;
+ }
+ }
+ else {
+ array[dest++] = tmp[cursor1++];
+ count1++;
+ count2 = 0;
+ if (--length1 === 1) {
+ exit = true;
+ break;
+ }
+ }
+ } while ((count1 | count2) < _minGallop);
+
+ if (exit) {
+ break;
+ }
+
+ do {
+ count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
+
+ if (count1 !== 0) {
+ for (i = 0; i < count1; i++) {
+ array[dest + i] = tmp[cursor1 + i];
+ }
+
+ dest += count1;
+ cursor1 += count1;
+ length1 -= count1;
+ if (length1 <= 1) {
+ exit = true;
+ break;
+ }
+ }
+
+ array[dest++] = array[cursor2++];
+
+ if (--length2 === 0) {
+ exit = true;
+ break;
+ }
+
+ count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
+
+ if (count2 !== 0) {
+ for (i = 0; i < count2; i++) {
+ array[dest + i] = array[cursor2 + i];
+ }
+
+ dest += count2;
+ cursor2 += count2;
+ length2 -= count2;
+
+ if (length2 === 0) {
+ exit = true;
+ break;
+ }
+ }
+ array[dest++] = tmp[cursor1++];
+
+ if (--length1 === 1) {
+ exit = true;
+ break;
+ }
+
+ _minGallop--;
+ } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
+
+ if (exit) {
+ break;
+ }
+
+ if (_minGallop < 0) {
+ _minGallop = 0;
+ }
+
+ _minGallop += 2;
+ }
+
+ minGallop = _minGallop;
+
+ minGallop < 1 && (minGallop = 1);
+
+ if (length1 === 1) {
+ for (i = 0; i < length2; i++) {
+ array[dest + i] = array[cursor2 + i];
+ }
+ array[dest + length2] = tmp[cursor1];
+ }
+ else if (length1 === 0) {
+ throw new Error();
+ // throw new Error('mergeLow preconditions were not respected');
+ }
+ else {
+ for (i = 0; i < length1; i++) {
+ array[dest + i] = tmp[cursor1 + i];
+ }
+ }
+ }
+
+ function mergeHigh (start1, length1, start2, length2) {
+ var i = 0;
+
+ for (i = 0; i < length2; i++) {
+ tmp[i] = array[start2 + i];
+ }
+
+ var cursor1 = start1 + length1 - 1;
+ var cursor2 = length2 - 1;
+ var dest = start2 + length2 - 1;
+ var customCursor = 0;
+ var customDest = 0;
+
+ array[dest--] = array[cursor1--];
+
+ if (--length1 === 0) {
+ customCursor = dest - (length2 - 1);
+
+ for (i = 0; i < length2; i++) {
+ array[customCursor + i] = tmp[i];
+ }
+
+ return;
+ }
+
+ if (length2 === 1) {
+ dest -= length1;
+ cursor1 -= length1;
+ customDest = dest + 1;
+ customCursor = cursor1 + 1;
+
+ for (i = length1 - 1; i >= 0; i--) {
+ array[customDest + i] = array[customCursor + i];
+ }
+
+ array[dest] = tmp[cursor2];
+ return;
+ }
+
+ var _minGallop = minGallop;
+
+ while (true) {
+ var count1 = 0;
+ var count2 = 0;
+ var exit = false;
+
+ do {
+ if (compare(tmp[cursor2], array[cursor1]) < 0) {
+ array[dest--] = array[cursor1--];
+ count1++;
+ count2 = 0;
+ if (--length1 === 0) {
+ exit = true;
+ break;
+ }
+ }
+ else {
+ array[dest--] = tmp[cursor2--];
+ count2++;
+ count1 = 0;
+ if (--length2 === 1) {
+ exit = true;
+ break;
+ }
+ }
+ } while ((count1 | count2) < _minGallop);
+
+ if (exit) {
+ break;
+ }
+
+ do {
+ count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
+
+ if (count1 !== 0) {
+ dest -= count1;
+ cursor1 -= count1;
+ length1 -= count1;
+ customDest = dest + 1;
+ customCursor = cursor1 + 1;
+
+ for (i = count1 - 1; i >= 0; i--) {
+ array[customDest + i] = array[customCursor + i];
+ }
+
+ if (length1 === 0) {
+ exit = true;
+ break;
+ }
+ }
+
+ array[dest--] = tmp[cursor2--];
+
+ if (--length2 === 1) {
+ exit = true;
+ break;
+ }
+
+ count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
+
+ if (count2 !== 0) {
+ dest -= count2;
+ cursor2 -= count2;
+ length2 -= count2;
+ customDest = dest + 1;
+ customCursor = cursor2 + 1;
+
+ for (i = 0; i < count2; i++) {
+ array[customDest + i] = tmp[customCursor + i];
+ }
+
+ if (length2 <= 1) {
+ exit = true;
+ break;
+ }
+ }
+
+ array[dest--] = array[cursor1--];
+
+ if (--length1 === 0) {
+ exit = true;
+ break;
+ }
+
+ _minGallop--;
+ } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
+
+ if (exit) {
+ break;
+ }
+
+ if (_minGallop < 0) {
+ _minGallop = 0;
+ }
+
+ _minGallop += 2;
+ }
+
+ minGallop = _minGallop;
+
+ if (minGallop < 1) {
+ minGallop = 1;
+ }
+
+ if (length2 === 1) {
+ dest -= length1;
+ cursor1 -= length1;
+ customDest = dest + 1;
+ customCursor = cursor1 + 1;
+
+ for (i = length1 - 1; i >= 0; i--) {
+ array[customDest + i] = array[customCursor + i];
+ }
+
+ array[dest] = tmp[cursor2];
+ }
+ else if (length2 === 0) {
+ throw new Error();
+ // throw new Error('mergeHigh preconditions were not respected');
+ }
+ else {
+ customCursor = dest - (length2 - 1);
+ for (i = 0; i < length2; i++) {
+ array[customCursor + i] = tmp[i];
+ }
+ }
+ }
+
+ this.mergeRuns = mergeRuns;
+ this.forceMergeRuns = forceMergeRuns;
+ this.pushRun = pushRun;
+ }
+
+ function sort(array, compare, lo, hi) {
+ if (!lo) {
+ lo = 0;
+ }
+ if (!hi) {
+ hi = array.length;
+ }
+
+ var remaining = hi - lo;
+
+ if (remaining < 2) {
+ return;
+ }
+
+ var runLength = 0;
+
+ if (remaining < DEFAULT_MIN_MERGE) {
+ runLength = makeAscendingRun(array, lo, hi, compare);
+ binaryInsertionSort(array, lo, hi, lo + runLength, compare);
+ return;
+ }
+
+ var ts = new TimSort(array, compare);
+
+ var minRun = minRunLength(remaining);
+
+ do {
+ runLength = makeAscendingRun(array, lo, hi, compare);
+ if (runLength < minRun) {
+ var force = remaining;
+ if (force > minRun) {
+ force = minRun;
+ }
+
+ binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
+ runLength = force;
+ }
+
+ ts.pushRun(lo, runLength);
+ ts.mergeRuns();
+
+ remaining -= runLength;
+ lo += runLength;
+ } while (remaining !== 0);
+
+ ts.forceMergeRuns();
+ }
+
+ module.exports = sort;
+
+
+/***/ },
+/* 87 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 动画主类, 调度和管理所有动画控制器
+ *
+ * @module zrender/animation/Animation
+ * @author pissang(https://github.com/pissang)
+ */
+ // TODO Additive animation
+ // http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/
+ // https://developer.apple.com/videos/wwdc2014/#236
+
+
+ var util = __webpack_require__(4);
+ var Dispatcher = __webpack_require__(88).Dispatcher;
+
+ var requestAnimationFrame = __webpack_require__(89);
+
+ var Animator = __webpack_require__(28);
+ /**
+ * @typedef {Object} IZRenderStage
+ * @property {Function} update
+ */
+
+ /**
+ * @alias module:zrender/animation/Animation
+ * @constructor
+ * @param {Object} [options]
+ * @param {Function} [options.onframe]
+ * @param {IZRenderStage} [options.stage]
+ * @example
+ * var animation = new Animation();
+ * var obj = {
+ * x: 100,
+ * y: 100
+ * };
+ * animation.animate(node.position)
+ * .when(1000, {
+ * x: 500,
+ * y: 500
+ * })
+ * .when(2000, {
+ * x: 100,
+ * y: 100
+ * })
+ * .start('spline');
+ */
+ var Animation = function (options) {
+
+ options = options || {};
+
+ this.stage = options.stage || {};
+
+ this.onframe = options.onframe || function() {};
+
+ // private properties
+ this._clips = [];
+
+ this._running = false;
+
+ this._time;
+
+ this._pausedTime;
+
+ this._pauseStart;
+
+ this._paused = false;
+
+ Dispatcher.call(this);
+ };
+
+ Animation.prototype = {
+
+ constructor: Animation,
+ /**
+ * 添加 clip
+ * @param {module:zrender/animation/Clip} clip
+ */
+ addClip: function (clip) {
+ this._clips.push(clip);
+ },
+ /**
+ * 添加 animator
+ * @param {module:zrender/animation/Animator} animator
+ */
+ addAnimator: function (animator) {
+ animator.animation = this;
+ var clips = animator.getClips();
+ for (var i = 0; i < clips.length; i++) {
+ this.addClip(clips[i]);
+ }
+ },
+ /**
+ * 删除动画片段
+ * @param {module:zrender/animation/Clip} clip
+ */
+ removeClip: function(clip) {
+ var idx = util.indexOf(this._clips, clip);
+ if (idx >= 0) {
+ this._clips.splice(idx, 1);
+ }
+ },
+
+ /**
+ * 删除动画片段
+ * @param {module:zrender/animation/Animator} animator
+ */
+ removeAnimator: function (animator) {
+ var clips = animator.getClips();
+ for (var i = 0; i < clips.length; i++) {
+ this.removeClip(clips[i]);
+ }
+ animator.animation = null;
+ },
+
+ _update: function() {
+
+ var time = new Date().getTime() - this._pausedTime;
+ var delta = time - this._time;
+ var clips = this._clips;
+ var len = clips.length;
+
+ var deferredEvents = [];
+ var deferredClips = [];
+ for (var i = 0; i < len; i++) {
+ var clip = clips[i];
+ var e = clip.step(time, delta);
+ // Throw out the events need to be called after
+ // stage.update, like destroy
+ if (e) {
+ deferredEvents.push(e);
+ deferredClips.push(clip);
+ }
+ }
+
+ // Remove the finished clip
+ for (var i = 0; i < len;) {
+ if (clips[i]._needsRemove) {
+ clips[i] = clips[len - 1];
+ clips.pop();
+ len--;
+ }
+ else {
+ i++;
+ }
+ }
+
+ len = deferredEvents.length;
+ for (var i = 0; i < len; i++) {
+ deferredClips[i].fire(deferredEvents[i]);
+ }
+
+ this._time = time;
+
+ this.onframe(delta);
+
+ this.trigger('frame', delta);
+
+ if (this.stage.update) {
+ this.stage.update();
+ }
+ },
+
+ _startLoop: function () {
+ var self = this;
+
+ this._running = true;
+
+ function step() {
+ if (self._running) {
+
+ requestAnimationFrame(step);
+
+ !self._paused && self._update();
+ }
+ }
+
+ requestAnimationFrame(step);
+ },
+
+ /**
+ * 开始运行动画
+ */
+ start: function () {
+
+ this._time = new Date().getTime();
+ this._pausedTime = 0;
+
+ this._startLoop();
+ },
+ /**
+ * 停止运行动画
+ */
+ stop: function () {
+ this._running = false;
+ },
+
+ /**
+ * Pause
+ */
+ pause: function () {
+ if (!this._paused) {
+ this._pauseStart = new Date().getTime();
+ this._paused = true;
+ }
+ },
+
+ /**
+ * Resume
+ */
+ resume: function () {
+ if (this._paused) {
+ this._pausedTime += (new Date().getTime()) - this._pauseStart;
+ this._paused = false;
+ }
+ },
+
+ /**
+ * 清除所有动画片段
+ */
+ clear: function () {
+ this._clips = [];
+ },
+ /**
+ * 对一个目标创建一个animator对象,可以指定目标中的属性使用动画
+ * @param {Object} target
+ * @param {Object} options
+ * @param {boolean} [options.loop=false] 是否循环播放动画
+ * @param {Function} [options.getter=null]
+ * 如果指定getter函数,会通过getter函数取属性值
+ * @param {Function} [options.setter=null]
+ * 如果指定setter函数,会通过setter函数设置属性值
+ * @return {module:zrender/animation/Animation~Animator}
+ */
+ // TODO Gap
+ animate: function (target, options) {
+ options = options || {};
+
+ var animator = new Animator(
+ target,
+ options.loop,
+ options.getter,
+ options.setter
+ );
+
+ this.addAnimator(animator);
+
+ return animator;
+ }
+ };
+
+ util.mixin(Animation, Dispatcher);
+
+ module.exports = Animation;
+
+
+
+/***/ },
+/* 88 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * 事件辅助类
+ * @module zrender/core/event
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ */
+
+
+ var Eventful = __webpack_require__(25);
+ var env = __webpack_require__(2);
+
+ var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
+
+ function getBoundingClientRect(el) {
+ // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect
+ return el.getBoundingClientRect ? el.getBoundingClientRect() : {left: 0, top: 0};
+ }
+
+ // `calculate` is optional, default false
+ function clientToLocal(el, e, out, calculate) {
+ out = out || {};
+
+ // According to the W3C Working Draft, offsetX and offsetY should be relative
+ // to the padding edge of the target element. The only browser using this convention
+ // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does
+ // not support the properties.
+ // (see http://www.jacklmoore.com/notes/mouse-position/)
+ // In zr painter.dom, padding edge equals to border edge.
+
+ // FIXME
+ // When mousemove event triggered on ec tooltip, target is not zr painter.dom, and
+ // offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y
+ // is too complex. So css-transfrom dont support in this case temporarily.
+ if (calculate || !env.canvasSupported) {
+ defaultGetZrXY(el, e, out);
+ }
+ // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned
+ // ancestor element, so we should make sure el is positioned (e.g., not position:static).
+ // BTW1, Webkit don't return the same results as FF in non-simple cases (like add
+ // zoom-factor, overflow / opacity layers, transforms ...)
+ // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.
+ //
+ // BTW3, In ff, offsetX/offsetY is always 0.
+ else if (env.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) {
+ out.zrX = e.layerX;
+ out.zrY = e.layerY;
+ }
+ // For IE6+, chrome, safari, opera. (When will ff support offsetX?)
+ else if (e.offsetX != null) {
+ out.zrX = e.offsetX;
+ out.zrY = e.offsetY;
+ }
+ // For some other device, e.g., IOS safari.
+ else {
+ defaultGetZrXY(el, e, out);
+ }
+
+ return out;
+ }
+
+ function defaultGetZrXY(el, e, out) {
+ // This well-known method below does not support css transform.
+ var box = getBoundingClientRect(el);
+ out.zrX = e.clientX - box.left;
+ out.zrY = e.clientY - box.top;
+ }
+
+ /**
+ * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标.
+ * `calculate` is optional, default false.
+ */
+ function normalizeEvent(el, e, calculate) {
+
+ e = e || window.event;
+
+ if (e.zrX != null) {
+ return e;
+ }
+
+ var eventType = e.type;
+ var isTouch = eventType && eventType.indexOf('touch') >= 0;
+
+ if (!isTouch) {
+ clientToLocal(el, e, e, calculate);
+ e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3;
+ }
+ else {
+ var touch = eventType != 'touchend'
+ ? e.targetTouches[0]
+ : e.changedTouches[0];
+ touch && clientToLocal(el, touch, e, calculate);
+ }
+
+ return e;
+ }
+
+ function addEventListener(el, name, handler) {
+ if (isDomLevel2) {
+ el.addEventListener(name, handler);
+ }
+ else {
+ el.attachEvent('on' + name, handler);
+ }
+ }
+
+ function removeEventListener(el, name, handler) {
+ if (isDomLevel2) {
+ el.removeEventListener(name, handler);
+ }
+ else {
+ el.detachEvent('on' + name, handler);
+ }
+ }
+
+ /**
+ * preventDefault and stopPropagation.
+ * Notice: do not do that in zrender. Upper application
+ * do that if necessary.
+ *
+ * @memberOf module:zrender/core/event
+ * @method
+ * @param {Event} e : event对象
+ */
+ var stop = isDomLevel2
+ ? function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ e.cancelBubble = true;
+ }
+ : function (e) {
+ e.returnValue = false;
+ e.cancelBubble = true;
+ };
+
+ module.exports = {
+ clientToLocal: clientToLocal,
+ normalizeEvent: normalizeEvent,
+ addEventListener: addEventListener,
+ removeEventListener: removeEventListener,
+
+ stop: stop,
+ // 做向上兼容
+ Dispatcher: Eventful
+ };
+
+
+
+/***/ },
+/* 89 */
+/***/ function(module, exports) {
+
+
+
+ module.exports = (typeof window !== 'undefined' &&
+ ((window.requestAnimationFrame && window.requestAnimationFrame.bind(window))
+ // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809
+ || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window))
+ || window.mozRequestAnimationFrame
+ || window.webkitRequestAnimationFrame)
+ )
+ || function (func) {
+ setTimeout(func, 16);
+ };
+
+
+
+/***/ },
+/* 90 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var eventTool = __webpack_require__(88);
+ var zrUtil = __webpack_require__(4);
+ var Eventful = __webpack_require__(25);
+ var env = __webpack_require__(2);
+ var GestureMgr = __webpack_require__(91);
+
+ var addEventListener = eventTool.addEventListener;
+ var removeEventListener = eventTool.removeEventListener;
+ var normalizeEvent = eventTool.normalizeEvent;
+
+ var TOUCH_CLICK_DELAY = 300;
+
+ var mouseHandlerNames = [
+ 'click', 'dblclick', 'mousewheel', 'mouseout',
+ 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
+ ];
+
+ var touchHandlerNames = [
+ 'touchstart', 'touchend', 'touchmove'
+ ];
+
+ var pointerEventNames = {
+ pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
+ };
+
+ var pointerHandlerNames = zrUtil.map(mouseHandlerNames, function (name) {
+ var nm = name.replace('mouse', 'pointer');
+ return pointerEventNames[nm] ? nm : name;
+ });
+
+ function eventNameFix(name) {
+ return (name === 'mousewheel' && env.browser.firefox) ? 'DOMMouseScroll' : name;
+ }
+
+ function processGesture(proxy, event, stage) {
+ var gestureMgr = proxy._gestureMgr;
+
+ stage === 'start' && gestureMgr.clear();
+
+ var gestureInfo = gestureMgr.recognize(
+ event,
+ proxy.handler.findHover(event.zrX, event.zrY, null).target,
+ proxy.dom
+ );
+
+ stage === 'end' && gestureMgr.clear();
+
+ // Do not do any preventDefault here. Upper application do that if necessary.
+ if (gestureInfo) {
+ var type = gestureInfo.type;
+ event.gestureEvent = type;
+
+ proxy.handler.dispatchToElement({target: gestureInfo.target}, type, gestureInfo.event);
+ }
+ }
+
+ // function onMSGestureChange(proxy, event) {
+ // if (event.translationX || event.translationY) {
+ // // mousemove is carried by MSGesture to reduce the sensitivity.
+ // proxy.handler.dispatchToElement(event.target, 'mousemove', event);
+ // }
+ // if (event.scale !== 1) {
+ // event.pinchX = event.offsetX;
+ // event.pinchY = event.offsetY;
+ // event.pinchScale = event.scale;
+ // proxy.handler.dispatchToElement(event.target, 'pinch', event);
+ // }
+ // }
+
+ /**
+ * Prevent mouse event from being dispatched after Touch Events action
+ * @see
+ * 1. Mobile browsers dispatch mouse events 300ms after touchend.
+ * 2. Chrome for Android dispatch mousedown for long-touch about 650ms
+ * Result: Blocking Mouse Events for 700ms.
+ */
+ function setTouchTimer(instance) {
+ instance._touching = true;
+ clearTimeout(instance._touchTimer);
+ instance._touchTimer = setTimeout(function () {
+ instance._touching = false;
+ }, 700);
+ }
+
+
+ var domHandlers = {
+ /**
+ * Mouse move handler
+ * @inner
+ * @param {Event} event
+ */
+ mousemove: function (event) {
+ event = normalizeEvent(this.dom, event);
+
+ this.trigger('mousemove', event);
+ },
+
+ /**
+ * Mouse out handler
+ * @inner
+ * @param {Event} event
+ */
+ mouseout: function (event) {
+ event = normalizeEvent(this.dom, event);
+
+ var element = event.toElement || event.relatedTarget;
+ if (element != this.dom) {
+ while (element && element.nodeType != 9) {
+ // 忽略包含在root中的dom引起的mouseOut
+ if (element === this.dom) {
+ return;
+ }
+
+ element = element.parentNode;
+ }
+ }
+
+ this.trigger('mouseout', event);
+ },
+
+ /**
+ * Touch开始响应函数
+ * @inner
+ * @param {Event} event
+ */
+ touchstart: function (event) {
+ // Default mouse behaviour should not be disabled here.
+ // For example, page may needs to be slided.
+ event = normalizeEvent(this.dom, event);
+
+ // Mark touch, which is useful in distinguish touch and
+ // mouse event in upper applicatoin.
+ event.zrByTouch = true;
+
+ this._lastTouchMoment = new Date();
+
+ processGesture(this, event, 'start');
+
+ // In touch device, trigger `mousemove`(`mouseover`) should
+ // be triggered, and must before `mousedown` triggered.
+ domHandlers.mousemove.call(this, event);
+
+ domHandlers.mousedown.call(this, event);
+
+ setTouchTimer(this);
+ },
+
+ /**
+ * Touch移动响应函数
+ * @inner
+ * @param {Event} event
+ */
+ touchmove: function (event) {
+
+ event = normalizeEvent(this.dom, event);
+
+ // Mark touch, which is useful in distinguish touch and
+ // mouse event in upper applicatoin.
+ event.zrByTouch = true;
+
+ processGesture(this, event, 'change');
+
+ // Mouse move should always be triggered no matter whether
+ // there is gestrue event, because mouse move and pinch may
+ // be used at the same time.
+ domHandlers.mousemove.call(this, event);
+
+ setTouchTimer(this);
+ },
+
+ /**
+ * Touch结束响应函数
+ * @inner
+ * @param {Event} event
+ */
+ touchend: function (event) {
+
+ event = normalizeEvent(this.dom, event);
+
+ // Mark touch, which is useful in distinguish touch and
+ // mouse event in upper applicatoin.
+ event.zrByTouch = true;
+
+ processGesture(this, event, 'end');
+
+ domHandlers.mouseup.call(this, event);
+
+ // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is
+ // triggered in `touchstart`. This seems to be illogical, but by this mechanism,
+ // we can conveniently implement "hover style" in both PC and touch device just
+ // by listening to `mouseover` to add "hover style" and listening to `mouseout`
+ // to remove "hover style" on an element, without any additional code for
+ // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover
+ // style" will remain for user view)
+
+ // click event should always be triggered no matter whether
+ // there is gestrue event. System click can not be prevented.
+ if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) {
+ domHandlers.click.call(this, event);
+ }
+
+ setTouchTimer(this);
+ },
+
+ pointerdown: function (event) {
+ domHandlers.mousedown.call(this, event);
+
+ // if (useMSGuesture(this, event)) {
+ // this._msGesture.addPointer(event.pointerId);
+ // }
+ },
+
+ pointermove: function (event) {
+ // FIXME
+ // pointermove is so sensitive that it always triggered when
+ // tap(click) on touch screen, which affect some judgement in
+ // upper application. So, we dont support mousemove on MS touch
+ // device yet.
+ if (!isPointerFromTouch(event)) {
+ domHandlers.mousemove.call(this, event);
+ }
+ },
+
+ pointerup: function (event) {
+ domHandlers.mouseup.call(this, event);
+ },
+
+ pointerout: function (event) {
+ // pointerout will be triggered when tap on touch screen
+ // (IE11+/Edge on MS Surface) after click event triggered,
+ // which is inconsistent with the mousout behavior we defined
+ // in touchend. So we unify them.
+ // (check domHandlers.touchend for detailed explanation)
+ if (!isPointerFromTouch(event)) {
+ domHandlers.mouseout.call(this, event);
+ }
+ }
+ };
+
+ function isPointerFromTouch(event) {
+ var pointerType = event.pointerType;
+ return pointerType === 'pen' || pointerType === 'touch';
+ }
+
+ // function useMSGuesture(handlerProxy, event) {
+ // return isPointerFromTouch(event) && !!handlerProxy._msGesture;
+ // }
+
+ // Common handlers
+ zrUtil.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
+ domHandlers[name] = function (event) {
+ event = normalizeEvent(this.dom, event);
+ this.trigger(name, event);
+ };
+ });
+
+ /**
+ * 为控制类实例初始化dom 事件处理函数
+ *
+ * @inner
+ * @param {module:zrender/Handler} instance 控制类实例
+ */
+ function initDomHandler(instance) {
+ zrUtil.each(touchHandlerNames, function (name) {
+ instance._handlers[name] = zrUtil.bind(domHandlers[name], instance);
+ });
+
+ zrUtil.each(pointerHandlerNames, function (name) {
+ instance._handlers[name] = zrUtil.bind(domHandlers[name], instance);
+ });
+
+ zrUtil.each(mouseHandlerNames, function (name) {
+ instance._handlers[name] = makeMouseHandler(domHandlers[name], instance);
+ });
+
+ function makeMouseHandler(fn, instance) {
+ return function () {
+ if (instance._touching) {
+ return;
+ }
+ return fn.apply(instance, arguments);
+ };
+ }
+ }
+
+
+ function HandlerDomProxy(dom) {
+ Eventful.call(this);
+
+ this.dom = dom;
+
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this._touching = false;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this._touchTimer;
+
+ /**
+ * @private
+ * @type {module:zrender/core/GestureMgr}
+ */
+ this._gestureMgr = new GestureMgr();
+
+ this._handlers = {};
+
+ initDomHandler(this);
+
+ if (env.pointerEventsSupported) { // Only IE11+/Edge
+ // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240),
+ // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event
+ // at the same time.
+ // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on
+ // screen, which do not occurs in pointer event.
+ // So we use pointer event to both detect touch gesture and mouse behavior.
+ mountHandlers(pointerHandlerNames, this);
+
+ // FIXME
+ // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,
+ // which does not prevent defuault behavior occasionally (which may cause view port
+ // zoomed in but use can not zoom it back). And event.preventDefault() does not work.
+ // So we have to not to use MSGesture and not to support touchmove and pinch on MS
+ // touch screen. And we only support click behavior on MS touch screen now.
+
+ // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+.
+ // We dont support touch on IE on win7.
+ // See
+ // if (typeof MSGesture === 'function') {
+ // (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line
+ // dom.addEventListener('MSGestureChange', onMSGestureChange);
+ // }
+ }
+ else {
+ if (env.touchEventsSupported) {
+ mountHandlers(touchHandlerNames, this);
+ // Handler of 'mouseout' event is needed in touch mode, which will be mounted below.
+ // addEventListener(root, 'mouseout', this._mouseoutHandler);
+ }
+
+ // 1. Considering some devices that both enable touch and mouse event (like on MS Surface
+ // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise
+ // mouse event can not be handle in those devices.
+ // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent
+ // mouseevent after touch event triggered, see `setTouchTimer`.
+ mountHandlers(mouseHandlerNames, this);
+ }
+
+ function mountHandlers(handlerNames, instance) {
+ zrUtil.each(handlerNames, function (name) {
+ addEventListener(dom, eventNameFix(name), instance._handlers[name]);
+ }, instance);
+ }
+ }
+
+ var handlerDomProxyProto = HandlerDomProxy.prototype;
+ handlerDomProxyProto.dispose = function () {
+ var handlerNames = mouseHandlerNames.concat(touchHandlerNames);
+
+ for (var i = 0; i < handlerNames.length; i++) {
+ var name = handlerNames[i];
+ removeEventListener(this.dom, eventNameFix(name), this._handlers[name]);
+ }
+ };
+
+ handlerDomProxyProto.setCursor = function (cursorStyle) {
+ this.dom.style.cursor = cursorStyle || 'default';
+ };
+
+ zrUtil.mixin(HandlerDomProxy, Eventful);
+
+ module.exports = HandlerDomProxy;
+
+
+/***/ },
+/* 91 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * Only implements needed gestures for mobile.
+ */
+
+
+ var eventUtil = __webpack_require__(88);
+
+ var GestureMgr = function () {
+
+ /**
+ * @private
+ * @type {Array.}
+ */
+ this._track = [];
+ };
+
+ GestureMgr.prototype = {
+
+ constructor: GestureMgr,
+
+ recognize: function (event, target, root) {
+ this._doTrack(event, target, root);
+ return this._recognize(event);
+ },
+
+ clear: function () {
+ this._track.length = 0;
+ return this;
+ },
+
+ _doTrack: function (event, target, root) {
+ var touches = event.touches;
+
+ if (!touches) {
+ return;
+ }
+
+ var trackItem = {
+ points: [],
+ touches: [],
+ target: target,
+ event: event
+ };
+
+ for (var i = 0, len = touches.length; i < len; i++) {
+ var touch = touches[i];
+ var pos = eventUtil.clientToLocal(root, touch, {});
+ trackItem.points.push([pos.zrX, pos.zrY]);
+ trackItem.touches.push(touch);
+ }
+
+ this._track.push(trackItem);
+ },
+
+ _recognize: function (event) {
+ for (var eventName in recognizers) {
+ if (recognizers.hasOwnProperty(eventName)) {
+ var gestureInfo = recognizers[eventName](this._track, event);
+ if (gestureInfo) {
+ return gestureInfo;
+ }
+ }
+ }
+ }
+ };
+
+ function dist(pointPair) {
+ var dx = pointPair[1][0] - pointPair[0][0];
+ var dy = pointPair[1][1] - pointPair[0][1];
+
+ return Math.sqrt(dx * dx + dy * dy);
+ }
+
+ function center(pointPair) {
+ return [
+ (pointPair[0][0] + pointPair[1][0]) / 2,
+ (pointPair[0][1] + pointPair[1][1]) / 2
+ ];
+ }
+
+ var recognizers = {
+
+ pinch: function (track, event) {
+ var trackLen = track.length;
+
+ if (!trackLen) {
+ return;
+ }
+
+ var pinchEnd = (track[trackLen - 1] || {}).points;
+ var pinchPre = (track[trackLen - 2] || {}).points || pinchEnd;
+
+ if (pinchPre
+ && pinchPre.length > 1
+ && pinchEnd
+ && pinchEnd.length > 1
+ ) {
+ var pinchScale = dist(pinchEnd) / dist(pinchPre);
+ !isFinite(pinchScale) && (pinchScale = 1);
+
+ event.pinchScale = pinchScale;
+
+ var pinchCenter = center(pinchEnd);
+ event.pinchX = pinchCenter[0];
+ event.pinchY = pinchCenter[1];
+
+ return {
+ type: 'pinch',
+ target: track[0].target,
+ event: event
+ };
+ }
+ }
+
+ // Only pinch currently.
+ };
+
+ module.exports = GestureMgr;
+
+
+
+/***/ },
+/* 92 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+ /**
+ * Default canvas painter
+ * @module zrender/Painter
+ * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
+ * errorrik (errorrik@gmail.com)
+ * pissang (https://www.github.com/pissang)
+ */
+
+
+ var config = __webpack_require__(34);
+ var util = __webpack_require__(4);
+ var log = __webpack_require__(33);
+ var BoundingRect = __webpack_require__(9);
+ var timsort = __webpack_require__(86);
+
+ var Layer = __webpack_require__(93);
+
+ var requestAnimationFrame = __webpack_require__(89);
+
+ // PENDIGN
+ // Layer exceeds MAX_PROGRESSIVE_LAYER_NUMBER may have some problem when flush directly second time.
+ //
+ // Maximum progressive layer. When exceeding this number. All elements will be drawed in the last layer.
+ var MAX_PROGRESSIVE_LAYER_NUMBER = 5;
+
+ function parseInt10(val) {
+ return parseInt(val, 10);
+ }
+
+ function isLayerValid(layer) {
+ if (!layer) {
+ return false;
+ }
+
+ if (layer.__builtin__) {
+ return true;
+ }
+
+ if (typeof(layer.resize) !== 'function'
+ || typeof(layer.refresh) !== 'function'
+ ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function preProcessLayer(layer) {
+ layer.__unusedCount++;
+ }
+
+ function postProcessLayer(layer) {
+ if (layer.__unusedCount == 1) {
+ layer.clear();
+ }
+ }
+
+ var tmpRect = new BoundingRect(0, 0, 0, 0);
+ var viewRect = new BoundingRect(0, 0, 0, 0);
+ function isDisplayableCulled(el, width, height) {
+ tmpRect.copy(el.getBoundingRect());
+ if (el.transform) {
+ tmpRect.applyTransform(el.transform);
+ }
+ viewRect.width = width;
+ viewRect.height = height;
+ return !tmpRect.intersect(viewRect);
+ }
+
+ function isClipPathChanged(clipPaths, prevClipPaths) {
+ if (clipPaths == prevClipPaths) { // Can both be null or undefined
+ return false;
+ }
+
+ if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) {
+ return true;
+ }
+ for (var i = 0; i < clipPaths.length; i++) {
+ if (clipPaths[i] !== prevClipPaths[i]) {
+ return true;
+ }
+ }
+ }
+
+ function doClip(clipPaths, ctx) {
+ for (var i = 0; i < clipPaths.length; i++) {
+ var clipPath = clipPaths[i];
+
+ clipPath.setTransform(ctx);
+ ctx.beginPath();
+ clipPath.buildPath(ctx, clipPath.shape);
+ ctx.clip();
+ // Transform back
+ clipPath.restoreTransform(ctx);
+ }
+ }
+
+ function createRoot(width, height) {
+ var domRoot = document.createElement('div');
+
+ // domRoot.onselectstart = returnFalse; // 避免页面选中的尴尬
+ domRoot.style.cssText = [
+ 'position:relative',
+ 'overflow:hidden',
+ 'width:' + width + 'px',
+ 'height:' + height + 'px',
+ 'padding:0',
+ 'margin:0',
+ 'border-width:0'
+ ].join(';') + ';';
+
+ return domRoot;
+ }
+
+ /**
+ * @alias module:zrender/Painter
+ * @constructor
+ * @param {HTMLElement} root 绘图容器
+ * @param {module:zrender/Storage} storage
+ * @param {Ojbect} opts
+ */
+ var Painter = function (root, storage, opts) {
+ // In node environment using node-canvas
+ var singleCanvas = !root.nodeName // In node ?
+ || root.nodeName.toUpperCase() === 'CANVAS';
+
+ this._opts = opts = util.extend({}, opts || {});
+
+ /**
+ * @type {number}
+ */
+ this.dpr = opts.devicePixelRatio || config.devicePixelRatio;
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this._singleCanvas = singleCanvas;
+ /**
+ * 绘图容器
+ * @type {HTMLElement}
+ */
+ this.root = root;
+
+ var rootStyle = root.style;
+
+ if (rootStyle) {
+ rootStyle['-webkit-tap-highlight-color'] = 'transparent';
+ rootStyle['-webkit-user-select'] =
+ rootStyle['user-select'] =
+ rootStyle['-webkit-touch-callout'] = 'none';
+
+ root.innerHTML = '';
+ }
+
+ /**
+ * @type {module:zrender/Storage}
+ */
+ this.storage = storage;
+
+ /**
+ * @type {Array.}
+ * @private
+ */
+ var zlevelList = this._zlevelList = [];
+
+ /**
+ * @type {Object.}
+ * @private
+ */
+ var layers = this._layers = {};
+
+ /**
+ * @type {Object.}
+ * @type {private}
+ */
+ this._layerConfig = {};
+
+ if (!singleCanvas) {
+ this._width = this._getSize(0);
+ this._height = this._getSize(1);
+
+ var domRoot = this._domRoot = createRoot(
+ this._width, this._height
+ );
+ root.appendChild(domRoot);
+ }
+ else {
+ if (opts.width != null) {
+ root.width = opts.width;
+ }
+ if (opts.height != null) {
+ root.height = opts.height;
+ }
+ // Use canvas width and height directly
+ var width = root.width;
+ var height = root.height;
+ this._width = width;
+ this._height = height;
+
+ // Create layer if only one given canvas
+ // Device pixel ratio is fixed to 1 because given canvas has its specified width and height
+ var mainLayer = new Layer(root, this, 1);
+ mainLayer.initContext();
+ // FIXME Use canvas width and height
+ // mainLayer.resize(width, height);
+ layers[0] = mainLayer;
+ zlevelList.push(0);
+
+ this._domRoot = root;
+ }
+
+ // Layers for progressive rendering
+ this._progressiveLayers = [];
+
+ /**
+ * @type {module:zrender/Layer}
+ * @private
+ */
+ this._hoverlayer;
+
+ this._hoverElements = [];
+ };
+
+ Painter.prototype = {
+
+ constructor: Painter,
+
+ /**
+ * If painter use a single canvas
+ * @return {boolean}
+ */
+ isSingleCanvas: function () {
+ return this._singleCanvas;
+ },
+ /**
+ * @return {HTMLDivElement}
+ */
+ getViewportRoot: function () {
+ return this._domRoot;
+ },
+
+ /**
+ * 刷新
+ * @param {boolean} [paintAll=false] 强制绘制所有displayable
+ */
+ refresh: function (paintAll) {
+
+ var list = this.storage.getDisplayList(true);
+
+ var zlevelList = this._zlevelList;
+
+ this._paintList(list, paintAll);
+
+ // Paint custum layers
+ for (var i = 0; i < zlevelList.length; i++) {
+ var z = zlevelList[i];
+ var layer = this._layers[z];
+ if (!layer.__builtin__ && layer.refresh) {
+ layer.refresh();
+ }
+ }
+
+ this.refreshHover();
+
+ if (this._progressiveLayers.length) {
+ this._startProgessive();
+ }
+
+ return this;
+ },
+
+ addHover: function (el, hoverStyle) {
+ if (el.__hoverMir) {
+ return;
+ }
+ var elMirror = new el.constructor({
+ style: el.style,
+ shape: el.shape
+ });
+ elMirror.__from = el;
+ el.__hoverMir = elMirror;
+ elMirror.setStyle(hoverStyle);
+ this._hoverElements.push(elMirror);
+ },
+
+ removeHover: function (el) {
+ var elMirror = el.__hoverMir;
+ var hoverElements = this._hoverElements;
+ var idx = util.indexOf(hoverElements, elMirror);
+ if (idx >= 0) {
+ hoverElements.splice(idx, 1);
+ }
+ el.__hoverMir = null;
+ },
+
+ clearHover: function (el) {
+ var hoverElements = this._hoverElements;
+ for (var i = 0; i < hoverElements.length; i++) {
+ var from = hoverElements[i].__from;
+ if (from) {
+ from.__hoverMir = null;
+ }
+ }
+ hoverElements.length = 0;
+ },
+
+ refreshHover: function () {
+ var hoverElements = this._hoverElements;
+ var len = hoverElements.length;
+ var hoverLayer = this._hoverlayer;
+ hoverLayer && hoverLayer.clear();
+
+ if (!len) {
+ return;
+ }
+ timsort(hoverElements, this.storage.displayableSortFunc);
+
+ // Use a extream large zlevel
+ // FIXME?
+ if (!hoverLayer) {
+ hoverLayer = this._hoverlayer = this.getLayer(1e5);
+ }
+
+ var scope = {};
+ hoverLayer.ctx.save();
+ for (var i = 0; i < len;) {
+ var el = hoverElements[i];
+ var originalEl = el.__from;
+ // Original el is removed
+ // PENDING
+ if (!(originalEl && originalEl.__zr)) {
+ hoverElements.splice(i, 1);
+ originalEl.__hoverMir = null;
+ len--;
+ continue;
+ }
+ i++;
+
+ // Use transform
+ // FIXME style and shape ?
+ if (!originalEl.invisible) {
+ el.transform = originalEl.transform;
+ el.invTransform = originalEl.invTransform;
+ el.__clipPaths = originalEl.__clipPaths;
+ // el.
+ this._doPaintEl(el, hoverLayer, true, scope);
+ }
+ }
+ hoverLayer.ctx.restore();
+ },
+
+ _startProgessive: function () {
+ var self = this;
+
+ if (!self._furtherProgressive) {
+ return;
+ }
+
+ // Use a token to stop progress steps triggered by
+ // previous zr.refresh calling.
+ var token = self._progressiveToken = +new Date();
+
+ self._progress++;
+ requestAnimationFrame(step);
+
+ function step() {
+ // In case refreshed or disposed
+ if (token === self._progressiveToken && self.storage) {
+
+ self._doPaintList(self.storage.getDisplayList());
+
+ if (self._furtherProgressive) {
+ self._progress++;
+ requestAnimationFrame(step);
+ }
+ else {
+ self._progressiveToken = -1;
+ }
+ }
+ }
+ },
+
+ _clearProgressive: function () {
+ this._progressiveToken = -1;
+ this._progress = 0;
+ util.each(this._progressiveLayers, function (layer) {
+ layer.__dirty && layer.clear();
+ });
+ },
+
+ _paintList: function (list, paintAll) {
+
+ if (paintAll == null) {
+ paintAll = false;
+ }
+
+ this._updateLayerStatus(list);
+
+ this._clearProgressive();
+
+ this.eachBuiltinLayer(preProcessLayer);
+
+ this._doPaintList(list, paintAll);
+
+ this.eachBuiltinLayer(postProcessLayer);
+ },
+
+ _doPaintList: function (list, paintAll) {
+ var currentLayer;
+ var currentZLevel;
+ var ctx;
+
+ // var invTransform = [];
+ var scope;
+
+ var progressiveLayerIdx = 0;
+ var currentProgressiveLayer;
+
+ var width = this._width;
+ var height = this._height;
+ var layerProgress;
+ var frame = this._progress;
+ function flushProgressiveLayer(layer) {
+ var dpr = ctx.dpr || 1;
+ ctx.save();
+ ctx.globalAlpha = 1;
+ ctx.shadowBlur = 0;
+ // Avoid layer don't clear in next progressive frame
+ currentLayer.__dirty = true;
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.drawImage(layer.dom, 0, 0, width * dpr, height * dpr);
+ ctx.restore();
+ }
+
+ for (var i = 0, l = list.length; i < l; i++) {
+ var el = list[i];
+ var elZLevel = this._singleCanvas ? 0 : el.zlevel;
+
+ var elFrame = el.__frame;
+
+ // Flush at current context
+ // PENDING
+ if (elFrame < 0 && currentProgressiveLayer) {
+ flushProgressiveLayer(currentProgressiveLayer);
+ currentProgressiveLayer = null;
+ }
+
+ // Change draw layer
+ if (currentZLevel !== elZLevel) {
+ if (ctx) {
+ ctx.restore();
+ }
+
+ // Reset scope
+ scope = {};
+
+ // Only 0 zlevel if only has one canvas
+ currentZLevel = elZLevel;
+ currentLayer = this.getLayer(currentZLevel);
+
+ if (!currentLayer.__builtin__) {
+ log(
+ 'ZLevel ' + currentZLevel
+ + ' has been used by unkown layer ' + currentLayer.id
+ );
+ }
+
+ ctx = currentLayer.ctx;
+ ctx.save();
+
+ // Reset the count
+ currentLayer.__unusedCount = 0;
+
+ if (currentLayer.__dirty || paintAll) {
+ currentLayer.clear();
+ }
+ }
+
+ if (!(currentLayer.__dirty || paintAll)) {
+ continue;
+ }
+
+ if (elFrame >= 0) {
+ // Progressive layer changed
+ if (!currentProgressiveLayer) {
+ currentProgressiveLayer = this._progressiveLayers[
+ Math.min(progressiveLayerIdx++, MAX_PROGRESSIVE_LAYER_NUMBER - 1)
+ ];
+
+ currentProgressiveLayer.ctx.save();
+ currentProgressiveLayer.renderScope = {};
+
+ if (currentProgressiveLayer
+ && (currentProgressiveLayer.__progress > currentProgressiveLayer.__maxProgress)
+ ) {
+ // flushProgressiveLayer(currentProgressiveLayer);
+ // Quick jump all progressive elements
+ // All progressive element are not dirty, jump over and flush directly
+ i = currentProgressiveLayer.__nextIdxNotProg - 1;
+ // currentProgressiveLayer = null;
+ continue;
+ }
+
+ layerProgress = currentProgressiveLayer.__progress;
+
+ if (!currentProgressiveLayer.__dirty) {
+ // Keep rendering
+ frame = layerProgress;
+ }
+
+ currentProgressiveLayer.__progress = frame + 1;
+ }
+
+ if (elFrame === frame) {
+ this._doPaintEl(el, currentProgressiveLayer, true, currentProgressiveLayer.renderScope);
+ }
+ }
+ else {
+ this._doPaintEl(el, currentLayer, paintAll, scope);
+ }
+
+ el.__dirty = false;
+ }
+
+ if (currentProgressiveLayer) {
+ flushProgressiveLayer(currentProgressiveLayer);
+ }
+
+ // Restore the lastLayer ctx
+ ctx && ctx.restore();
+ // If still has clipping state
+ // if (scope.prevElClipPaths) {
+ // ctx.restore();
+ // }
+
+ this._furtherProgressive = false;
+ util.each(this._progressiveLayers, function (layer) {
+ if (layer.__maxProgress >= layer.__progress) {
+ this._furtherProgressive = true;
+ }
+ }, this);
+ },
+
+ _doPaintEl: function (el, currentLayer, forcePaint, scope) {
+ var ctx = currentLayer.ctx;
+ var m = el.transform;
+ if (
+ (currentLayer.__dirty || forcePaint)
+ // Ignore invisible element
+ && !el.invisible
+ // Ignore transparent element
+ && el.style.opacity !== 0
+ // Ignore scale 0 element, in some environment like node-canvas
+ // Draw a scale 0 element can cause all following draw wrong
+ // And setTransform with scale 0 will cause set back transform failed.
+ && !(m && !m[0] && !m[3])
+ // Ignore culled element
+ && !(el.culling && isDisplayableCulled(el, this._width, this._height))
+ ) {
+
+ var clipPaths = el.__clipPaths;
+
+ // Optimize when clipping on group with several elements
+ if (scope.prevClipLayer !== currentLayer
+ || isClipPathChanged(clipPaths, scope.prevElClipPaths)
+ ) {
+ // If has previous clipping state, restore from it
+ if (scope.prevElClipPaths) {
+ scope.prevClipLayer.ctx.restore();
+ scope.prevClipLayer = scope.prevElClipPaths = null;
+
+ // Reset prevEl since context has been restored
+ scope.prevEl = null;
+ }
+ // New clipping state
+ if (clipPaths) {
+ ctx.save();
+ doClip(clipPaths, ctx);
+ scope.prevClipLayer = currentLayer;
+ scope.prevElClipPaths = clipPaths;
+ }
+ }
+ el.beforeBrush && el.beforeBrush(ctx);
+
+ el.brush(ctx, scope.prevEl || null);
+ scope.prevEl = el;
+
+ el.afterBrush && el.afterBrush(ctx);
+ }
+ },
+
+ /**
+ * 获取 zlevel 所在层,如果不存在则会创建一个新的层
+ * @param {number} zlevel
+ * @return {module:zrender/Layer}
+ */
+ getLayer: function (zlevel) {
+ if (this._singleCanvas) {
+ return this._layers[0];
+ }
+
+ var layer = this._layers[zlevel];
+ if (!layer) {
+ // Create a new layer
+ layer = new Layer('zr_' + zlevel, this, this.dpr);
+ layer.__builtin__ = true;
+
+ if (this._layerConfig[zlevel]) {
+ util.merge(layer, this._layerConfig[zlevel], true);
+ }
+
+ this.insertLayer(zlevel, layer);
+
+ // Context is created after dom inserted to document
+ // Or excanvas will get 0px clientWidth and clientHeight
+ layer.initContext();
+ }
+
+ return layer;
+ },
+
+ insertLayer: function (zlevel, layer) {
+
+ var layersMap = this._layers;
+ var zlevelList = this._zlevelList;
+ var len = zlevelList.length;
+ var prevLayer = null;
+ var i = -1;
+ var domRoot = this._domRoot;
+
+ if (layersMap[zlevel]) {
+ log('ZLevel ' + zlevel + ' has been used already');
+ return;
+ }
+ // Check if is a valid layer
+ if (!isLayerValid(layer)) {
+ log('Layer of zlevel ' + zlevel + ' is not valid');
+ return;
+ }
+
+ if (len > 0 && zlevel > zlevelList[0]) {
+ for (i = 0; i < len - 1; i++) {
+ if (
+ zlevelList[i] < zlevel
+ && zlevelList[i + 1] > zlevel
+ ) {
+ break;
+ }
+ }
+ prevLayer = layersMap[zlevelList[i]];
+ }
+ zlevelList.splice(i + 1, 0, zlevel);
+
+ layersMap[zlevel] = layer;
+
+ // Vitual layer will not directly show on the screen.
+ // (It can be a WebGL layer and assigned to a ZImage element)
+ // But it still under management of zrender.
+ if (!layer.virtual) {
+ if (prevLayer) {
+ var prevDom = prevLayer.dom;
+ if (prevDom.nextSibling) {
+ domRoot.insertBefore(
+ layer.dom,
+ prevDom.nextSibling
+ );
+ }
+ else {
+ domRoot.appendChild(layer.dom);
+ }
+ }
+ else {
+ if (domRoot.firstChild) {
+ domRoot.insertBefore(layer.dom, domRoot.firstChild);
+ }
+ else {
+ domRoot.appendChild(layer.dom);
+ }
+ }
+ }
+ },
+
+ // Iterate each layer
+ eachLayer: function (cb, context) {
+ var zlevelList = this._zlevelList;
+ var z;
+ var i;
+ for (i = 0; i < zlevelList.length; i++) {
+ z = zlevelList[i];
+ cb.call(context, this._layers[z], z);
+ }
+ },
+
+ // Iterate each buildin layer
+ eachBuiltinLayer: function (cb, context) {
+ var zlevelList = this._zlevelList;
+ var layer;
+ var z;
+ var i;
+ for (i = 0; i < zlevelList.length; i++) {
+ z = zlevelList[i];
+ layer = this._layers[z];
+ if (layer.__builtin__) {
+ cb.call(context, layer, z);
+ }
+ }
+ },
+
+ // Iterate each other layer except buildin layer
+ eachOtherLayer: function (cb, context) {
+ var zlevelList = this._zlevelList;
+ var layer;
+ var z;
+ var i;
+ for (i = 0; i < zlevelList.length; i++) {
+ z = zlevelList[i];
+ layer = this._layers[z];
+ if (!layer.__builtin__) {
+ cb.call(context, layer, z);
+ }
+ }
+ },
+
+ /**
+ * 获取所有已创建的层
+ * @param {Array.} [prevLayer]
+ */
+ getLayers: function () {
+ return this._layers;
+ },
+
+ _updateLayerStatus: function (list) {
+
+ var layers = this._layers;
+ var progressiveLayers = this._progressiveLayers;
+
+ var elCountsLastFrame = {};
+ var progressiveElCountsLastFrame = {};
+
+ this.eachBuiltinLayer(function (layer, z) {
+ elCountsLastFrame[z] = layer.elCount;
+ layer.elCount = 0;
+ layer.__dirty = false;
+ });
+
+ util.each(progressiveLayers, function (layer, idx) {
+ progressiveElCountsLastFrame[idx] = layer.elCount;
+ layer.elCount = 0;
+ layer.__dirty = false;
+ });
+
+ var progressiveLayerCount = 0;
+ var currentProgressiveLayer;
+ var lastProgressiveKey;
+ var frameCount = 0;
+ for (var i = 0, l = list.length; i < l; i++) {
+ var el = list[i];
+ var zlevel = this._singleCanvas ? 0 : el.zlevel;
+ var layer = layers[zlevel];
+ var elProgress = el.progressive;
+ if (layer) {
+ layer.elCount++;
+ layer.__dirty = layer.__dirty || el.__dirty;
+ }
+
+ /////// Update progressive
+ if (elProgress >= 0) {
+ // Fix wrong progressive sequence problem.
+ if (lastProgressiveKey !== elProgress) {
+ lastProgressiveKey = elProgress;
+ frameCount++;
+ }
+ var elFrame = el.__frame = frameCount - 1;
+ if (!currentProgressiveLayer) {
+ var idx = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER - 1);
+ currentProgressiveLayer = progressiveLayers[idx];
+ if (!currentProgressiveLayer) {
+ currentProgressiveLayer = progressiveLayers[idx] = new Layer(
+ 'progressive', this, this.dpr
+ );
+ currentProgressiveLayer.initContext();
+ }
+ currentProgressiveLayer.__maxProgress = 0;
+ }
+ currentProgressiveLayer.__dirty = currentProgressiveLayer.__dirty || el.__dirty;
+ currentProgressiveLayer.elCount++;
+
+ currentProgressiveLayer.__maxProgress = Math.max(
+ currentProgressiveLayer.__maxProgress, elFrame
+ );
+
+ if (currentProgressiveLayer.__maxProgress >= currentProgressiveLayer.__progress) {
+ // Should keep rendering this layer because progressive rendering is not finished yet
+ layer.__dirty = true;
+ }
+ }
+ else {
+ el.__frame = -1;
+
+ if (currentProgressiveLayer) {
+ currentProgressiveLayer.__nextIdxNotProg = i;
+ progressiveLayerCount++;
+ currentProgressiveLayer = null;
+ }
+ }
+ }
+
+ if (currentProgressiveLayer) {
+ progressiveLayerCount++;
+ currentProgressiveLayer.__nextIdxNotProg = i;
+ }
+
+ // 层中的元素数量有发生变化
+ this.eachBuiltinLayer(function (layer, z) {
+ if (elCountsLastFrame[z] !== layer.elCount) {
+ layer.__dirty = true;
+ }
+ });
+
+ progressiveLayers.length = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER);
+ util.each(progressiveLayers, function (layer, idx) {
+ if (progressiveElCountsLastFrame[idx] !== layer.elCount) {
+ el.__dirty = true;
+ }
+ if (layer.__dirty) {
+ layer.__progress = 0;
+ }
+ });
+ },
+
+ /**
+ * 清除hover层外所有内容
+ */
+ clear: function () {
+ this.eachBuiltinLayer(this._clearLayer);
+ return this;
+ },
+
+ _clearLayer: function (layer) {
+ layer.clear();
+ },
+
+ /**
+ * 修改指定zlevel的绘制参数
+ *
+ * @param {string} zlevel
+ * @param {Object} config 配置对象
+ * @param {string} [config.clearColor=0] 每次清空画布的颜色
+ * @param {string} [config.motionBlur=false] 是否开启动态模糊
+ * @param {number} [config.lastFrameAlpha=0.7]
+ * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显
+ */
+ configLayer: function (zlevel, config) {
+ if (config) {
+ var layerConfig = this._layerConfig;
+ if (!layerConfig[zlevel]) {
+ layerConfig[zlevel] = config;
+ }
+ else {
+ util.merge(layerConfig[zlevel], config, true);
+ }
+
+ var layer = this._layers[zlevel];
+
+ if (layer) {
+ util.merge(layer, layerConfig[zlevel], true);
+ }
+ }
+ },
+
+ /**
+ * 删除指定层
+ * @param {number} zlevel 层所在的zlevel
+ */
+ delLayer: function (zlevel) {
+ var layers = this._layers;
+ var zlevelList = this._zlevelList;
+ var layer = layers[zlevel];
+ if (!layer) {
+ return;
+ }
+ layer.dom.parentNode.removeChild(layer.dom);
+ delete layers[zlevel];
+
+ zlevelList.splice(util.indexOf(zlevelList, zlevel), 1);
+ },
+
+ /**
+ * 区域大小变化后重绘
+ */
+ resize: function (width, height) {
+ var domRoot = this._domRoot;
+ // FIXME Why ?
+ domRoot.style.display = 'none';
+
+ // Save input w/h
+ var opts = this._opts;
+ width != null && (opts.width = width);
+ height != null && (opts.height = height);
+
+ width = this._getSize(0);
+ height = this._getSize(1);
+
+ domRoot.style.display = '';
+
+ // 优化没有实际改变的resize
+ if (this._width != width || height != this._height) {
+ domRoot.style.width = width + 'px';
+ domRoot.style.height = height + 'px';
+
+ for (var id in this._layers) {
+ if (this._layers.hasOwnProperty(id)) {
+ this._layers[id].resize(width, height);
+ }
+ }
+ util.each(this._progressiveLayers, function (layer) {
+ layer.resize(width, height);
+ });
+
+ this.refresh(true);
+ }
+
+ this._width = width;
+ this._height = height;
+
+ return this;
+ },
+
+ /**
+ * 清除单独的一个层
+ * @param {number} zlevel
+ */
+ clearLayer: function (zlevel) {
+ var layer = this._layers[zlevel];
+ if (layer) {
+ layer.clear();
+ }
+ },
+
+ /**
+ * 释放
+ */
+ dispose: function () {
+ this.root.innerHTML = '';
+
+ this.root =
+ this.storage =
+
+ this._domRoot =
+ this._layers = null;
+ },
+
+ /**
+ * Get canvas which has all thing rendered
+ * @param {Object} opts
+ * @param {string} [opts.backgroundColor]
+ */
+ getRenderedCanvas: function (opts) {
+ opts = opts || {};
+ if (this._singleCanvas) {
+ return this._layers[0].dom;
+ }
+
+ var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr);
+ imageLayer.initContext();
+
+ imageLayer.clearColor = opts.backgroundColor;
+ imageLayer.clear();
+
+ var displayList = this.storage.getDisplayList(true);
+
+ var scope = {};
+ var zlevel;
+
+ var self = this;
+ function findAndDrawOtherLayer(smaller, larger) {
+ var zlevelList = self._zlevelList;
+ if (smaller == null) {
+ smaller = -Infinity;
+ }
+ var intermediateLayer;
+ for (var i = 0; i < zlevelList.length; i++) {
+ var z = zlevelList[i];
+ var layer = self._layers[z];
+ if (!layer.__builtin__ && z > smaller && z < larger) {
+ intermediateLayer = layer;
+ break;
+ }
+ }
+ if (intermediateLayer && intermediateLayer.renderToCanvas) {
+ imageLayer.ctx.save();
+ intermediateLayer.renderToCanvas(imageLayer.ctx);
+ imageLayer.ctx.restore();
+ }
+ }
+ for (var i = 0; i < displayList.length; i++) {
+ var el = displayList[i];
+
+ if (el.zlevel !== zlevel) {
+ findAndDrawOtherLayer(zlevel, el.zlevel);
+ zlevel = el.zlevel;
+ }
+ this._doPaintEl(el, imageLayer, true, scope);
+ }
+
+ findAndDrawOtherLayer(zlevel, Infinity);
+
+ return imageLayer.dom;
+ },
+ /**
+ * 获取绘图区域宽度
+ */
+ getWidth: function () {
+ return this._width;
+ },
+
+ /**
+ * 获取绘图区域高度
+ */
+ getHeight: function () {
+ return this._height;
+ },
+
+ _getSize: function (whIdx) {
+ var opts = this._opts;
+ var wh = ['width', 'height'][whIdx];
+ var cwh = ['clientWidth', 'clientHeight'][whIdx];
+ var plt = ['paddingLeft', 'paddingTop'][whIdx];
+ var prb = ['paddingRight', 'paddingBottom'][whIdx];
+
+ if (opts[wh] != null && opts[wh] !== 'auto') {
+ return parseFloat(opts[wh]);
+ }
+
+ var root = this.root;
+ var stl = document.defaultView.getComputedStyle(root);
+
+ return (
+ (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh]))
+ - (parseInt10(stl[plt]) || 0)
+ - (parseInt10(stl[prb]) || 0)
+ ) | 0;
+ },
+
+ pathToImage: function (path, dpr) {
+ dpr = dpr || this.dpr;
+
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('2d');
+ var rect = path.getBoundingRect();
+ var style = path.style;
+ var shadowBlurSize = style.shadowBlur;
+ var shadowOffsetX = style.shadowOffsetX;
+ var shadowOffsetY = style.shadowOffsetY;
+ var lineWidth = style.hasStroke() ? style.lineWidth : 0;
+
+ var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize);
+ var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize);
+ var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize);
+ var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize);
+ var width = rect.width + leftMargin + rightMargin;
+ var height = rect.height + topMargin + bottomMargin;
+
+ canvas.width = width * dpr;
+ canvas.height = height * dpr;
+
+ ctx.scale(dpr, dpr);
+ ctx.clearRect(0, 0, width, height);
+ ctx.dpr = dpr;
+
+ var pathTransform = {
+ position: path.position,
+ rotation: path.rotation,
+ scale: path.scale
+ };
+ path.position = [leftMargin - rect.x, topMargin - rect.y];
+ path.rotation = 0;
+ path.scale = [1, 1];
+ path.updateTransform();
+ if (path) {
+ path.brush(ctx);
+ }
+
+ var ImageShape = __webpack_require__(49);
+ var imgShape = new ImageShape({
+ style: {
+ x: 0,
+ y: 0,
+ image: canvas
+ }
+ });
+
+ if (pathTransform.position != null) {
+ imgShape.position = path.position = pathTransform.position;
+ }
+
+ if (pathTransform.rotation != null) {
+ imgShape.rotation = path.rotation = pathTransform.rotation;
+ }
+
+ if (pathTransform.scale != null) {
+ imgShape.scale = path.scale = pathTransform.scale;
+ }
+
+ return imgShape;
+ }
+ };
+
+ module.exports = Painter;
+
+
+
+/***/ },
+/* 93 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @module zrender/Layer
+ * @author pissang(https://www.github.com/pissang)
+ */
+
+
+ var util = __webpack_require__(4);
+ var config = __webpack_require__(34);
+ var Style = __webpack_require__(22);
+ var Pattern = __webpack_require__(46);
+
+ function returnFalse() {
+ return false;
+ }
+
+ /**
+ * 创建dom
+ *
+ * @inner
+ * @param {string} id dom id 待用
+ * @param {string} type dom type,such as canvas, div etc.
+ * @param {Painter} painter painter instance
+ * @param {number} number
+ */
+ function createDom(id, type, painter, dpr) {
+ var newDom = document.createElement(type);
+ var width = painter.getWidth();
+ var height = painter.getHeight();
+
+ var newDomStyle = newDom.style;
+ // 没append呢,请原谅我这样写,清晰~
+ newDomStyle.position = 'absolute';
+ newDomStyle.left = 0;
+ newDomStyle.top = 0;
+ newDomStyle.width = width + 'px';
+ newDomStyle.height = height + 'px';
+ newDom.width = width * dpr;
+ newDom.height = height * dpr;
+
+ // id不作为索引用,避免可能造成的重名,定义为私有属性
+ newDom.setAttribute('data-zr-dom-id', id);
+ return newDom;
+ }
+
+ /**
+ * @alias module:zrender/Layer
+ * @constructor
+ * @extends module:zrender/mixin/Transformable
+ * @param {string} id
+ * @param {module:zrender/Painter} painter
+ * @param {number} [dpr]
+ */
+ var Layer = function(id, painter, dpr) {
+ var dom;
+ dpr = dpr || config.devicePixelRatio;
+ if (typeof id === 'string') {
+ dom = createDom(id, 'canvas', painter, dpr);
+ }
+ // Not using isDom because in node it will return false
+ else if (util.isObject(id)) {
+ dom = id;
+ id = dom.id;
+ }
+ this.id = id;
+ this.dom = dom;
+
+ var domStyle = dom.style;
+ if (domStyle) { // Not in node
+ dom.onselectstart = returnFalse; // 避免页面选中的尴尬
+ domStyle['-webkit-user-select'] = 'none';
+ domStyle['user-select'] = 'none';
+ domStyle['-webkit-touch-callout'] = 'none';
+ domStyle['-webkit-tap-highlight-color'] = 'rgba(0,0,0,0)';
+ domStyle['padding'] = 0;
+ domStyle['margin'] = 0;
+ domStyle['border-width'] = 0;
+ }
+
+ this.domBack = null;
+ this.ctxBack = null;
+
+ this.painter = painter;
+
+ this.config = null;
+
+ // Configs
+ /**
+ * 每次清空画布的颜色
+ * @type {string}
+ * @default 0
+ */
+ this.clearColor = 0;
+ /**
+ * 是否开启动态模糊
+ * @type {boolean}
+ * @default false
+ */
+ this.motionBlur = false;
+ /**
+ * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显
+ * @type {number}
+ * @default 0.7
+ */
+ this.lastFrameAlpha = 0.7;
+
+ /**
+ * Layer dpr
+ * @type {number}
+ */
+ this.dpr = dpr;
+ };
+
+ Layer.prototype = {
+
+ constructor: Layer,
+
+ elCount: 0,
+
+ __dirty: true,
+
+ initContext: function () {
+ this.ctx = this.dom.getContext('2d');
+
+ this.ctx.dpr = this.dpr;
+ },
+
+ createBackBuffer: function () {
+ var dpr = this.dpr;
+
+ this.domBack = createDom('back-' + this.id, 'canvas', this.painter, dpr);
+ this.ctxBack = this.domBack.getContext('2d');
+
+ if (dpr != 1) {
+ this.ctxBack.scale(dpr, dpr);
+ }
+ },
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ */
+ resize: function (width, height) {
+ var dpr = this.dpr;
+
+ var dom = this.dom;
+ var domStyle = dom.style;
+ var domBack = this.domBack;
+
+ domStyle.width = width + 'px';
+ domStyle.height = height + 'px';
+
+ dom.width = width * dpr;
+ dom.height = height * dpr;
+
+ if (domBack) {
+ domBack.width = width * dpr;
+ domBack.height = height * dpr;
+
+ if (dpr != 1) {
+ this.ctxBack.scale(dpr, dpr);
+ }
+ }
+ },
+
+ /**
+ * 清空该层画布
+ * @param {boolean} clearAll Clear all with out motion blur
+ */
+ clear: function (clearAll) {
+ var dom = this.dom;
+ var ctx = this.ctx;
+ var width = dom.width;
+ var height = dom.height;
+
+ var clearColor = this.clearColor;
+ var haveMotionBLur = this.motionBlur && !clearAll;
+ var lastFrameAlpha = this.lastFrameAlpha;
+
+ var dpr = this.dpr;
+
+ if (haveMotionBLur) {
+ if (!this.domBack) {
+ this.createBackBuffer();
+ }
+
+ this.ctxBack.globalCompositeOperation = 'copy';
+ this.ctxBack.drawImage(
+ dom, 0, 0,
+ width / dpr,
+ height / dpr
+ );
+ }
+
+ ctx.clearRect(0, 0, width, height);
+ if (clearColor) {
+ var clearColorGradientOrPattern;
+ // Gradient
+ if (clearColor.colorStops) {
+ // Cache canvas gradient
+ clearColorGradientOrPattern = clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, {
+ x: 0,
+ y: 0,
+ width: width,
+ height: height
+ });
+
+ clearColor.__canvasGradient = clearColorGradientOrPattern;
+ }
+ // Pattern
+ else if (clearColor.image) {
+ clearColorGradientOrPattern = Pattern.prototype.getCanvasPattern.call(clearColor, ctx);
+ }
+ ctx.save();
+ ctx.fillStyle = clearColorGradientOrPattern || clearColor;
+ ctx.fillRect(0, 0, width, height);
+ ctx.restore();
+ }
+
+ if (haveMotionBLur) {
+ var domBack = this.domBack;
+ ctx.save();
+ ctx.globalAlpha = lastFrameAlpha;
+ ctx.drawImage(domBack, 0, 0, width, height);
+ ctx.restore();
+ }
+ }
+ };
+
+ module.exports = Layer;
+
+
+/***/ },
+/* 94 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+ var Gradient = __webpack_require__(66);
+ module.exports = function (ecModel) {
+ function encodeColor(seriesModel) {
+ var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.normal.color').split('.');
+ var data = seriesModel.getData();
+ var color = seriesModel.get(colorAccessPath) // Set in itemStyle
+ || seriesModel.getColorFromPalette(seriesModel.get('name')); // Default color
+
+ // FIXME Set color function or use the platte color
+ data.setVisual('color', color);
+
+ // Only visible series has each data be visual encoded
+ if (!ecModel.isSeriesFiltered(seriesModel)) {
+ if (typeof color === 'function' && !(color instanceof Gradient)) {
+ data.each(function (idx) {
+ data.setItemVisual(
+ idx, 'color', color(seriesModel.getDataParams(idx))
+ );
+ });
+ }
+
+ // itemStyle in each data item
+ data.each(function (idx) {
+ var itemModel = data.getItemModel(idx);
+ var color = itemModel.get(colorAccessPath, true);
+ if (color != null) {
+ data.setItemVisual(idx, 'color', color);
+ }
+ });
+ }
+ }
+ ecModel.eachRawSeries(encodeColor);
+ };
+
+
+/***/ },
+/* 95 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // Compatitable with 2.0
+
+
+ var zrUtil = __webpack_require__(4);
+ var compatStyle = __webpack_require__(96);
+
+ function get(opt, path) {
+ path = path.split(',');
+ var obj = opt;
+ for (var i = 0; i < path.length; i++) {
+ obj = obj && obj[path[i]];
+ if (obj == null) {
+ break;
+ }
+ }
+ return obj;
+ }
+
+ function set(opt, path, val, overwrite) {
+ path = path.split(',');
+ var obj = opt;
+ var key;
+ for (var i = 0; i < path.length - 1; i++) {
+ key = path[i];
+ if (obj[key] == null) {
+ obj[key] = {};
+ }
+ obj = obj[key];
+ }
+ if (overwrite || obj[path[i]] == null) {
+ obj[path[i]] = val;
+ }
+ }
+
+ function compatLayoutProperties(option) {
+ each(LAYOUT_PROPERTIES, function (prop) {
+ if (prop[0] in option && !(prop[1] in option)) {
+ option[prop[1]] = option[prop[0]];
+ }
+ });
+ }
+
+ var LAYOUT_PROPERTIES = [
+ ['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']
+ ];
+
+ var COMPATITABLE_COMPONENTS = [
+ 'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline'
+ ];
+
+ var COMPATITABLE_SERIES = [
+ 'bar', 'boxplot', 'candlestick', 'chord', 'effectScatter',
+ 'funnel', 'gauge', 'lines', 'graph', 'heatmap', 'line', 'map', 'parallel',
+ 'pie', 'radar', 'sankey', 'scatter', 'treemap'
+ ];
+
+ var each = zrUtil.each;
+
+ module.exports = function (option) {
+ each(option.series, function (seriesOpt) {
+ if (!zrUtil.isObject(seriesOpt)) {
+ return;
+ }
+
+ var seriesType = seriesOpt.type;
+
+ compatStyle(seriesOpt);
+
+ if (seriesType === 'pie' || seriesType === 'gauge') {
+ if (seriesOpt.clockWise != null) {
+ seriesOpt.clockwise = seriesOpt.clockWise;
+ }
+ }
+ if (seriesType === 'gauge') {
+ var pointerColor = get(seriesOpt, 'pointer.color');
+ pointerColor != null
+ && set(seriesOpt, 'itemStyle.normal.color', pointerColor);
+ }
+
+ for (var i = 0; i < COMPATITABLE_SERIES.length; i++) {
+ if (COMPATITABLE_SERIES[i] === seriesOpt.type) {
+ compatLayoutProperties(seriesOpt);
+ break;
+ }
+ }
+ });
+
+ // dataRange has changed to visualMap
+ if (option.dataRange) {
+ option.visualMap = option.dataRange;
+ }
+
+ each(COMPATITABLE_COMPONENTS, function (componentName) {
+ var options = option[componentName];
+ if (options) {
+ if (!zrUtil.isArray(options)) {
+ options = [options];
+ }
+ each(options, function (option) {
+ compatLayoutProperties(option);
+ });
+ }
+ });
+ };
+
+
+/***/ },
+/* 96 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var zrUtil = __webpack_require__(4);
+
+ var POSSIBLE_STYLES = [
+ 'areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle',
+ 'chordStyle', 'label', 'labelLine'
+ ];
+
+ function compatItemStyle(opt) {
+ var itemStyleOpt = opt && opt.itemStyle;
+ if (itemStyleOpt) {
+ zrUtil.each(POSSIBLE_STYLES, function (styleName) {
+ var normalItemStyleOpt = itemStyleOpt.normal;
+ var emphasisItemStyleOpt = itemStyleOpt.emphasis;
+ if (normalItemStyleOpt && normalItemStyleOpt[styleName]) {
+ opt[styleName] = opt[styleName] || {};
+ if (!opt[styleName].normal) {
+ opt[styleName].normal = normalItemStyleOpt[styleName];
+ }
+ else {
+ zrUtil.merge(opt[styleName].normal, normalItemStyleOpt[styleName]);
+ }
+ normalItemStyleOpt[styleName] = null;
+ }
+ if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) {
+ opt[styleName] = opt[styleName] || {};
+ if (!opt[styleName].emphasis) {
+ opt[styleName].emphasis = emphasisItemStyleOpt[styleName];
+ }
+ else {
+ zrUtil.merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]);
+ }
+ emphasisItemStyleOpt[styleName] = null;
+ }
+ });
+ }
+ }
+
+ module.exports = function (seriesOpt) {
+ if (!seriesOpt) {
+ return;
+ }
+ compatItemStyle(seriesOpt);
+ compatItemStyle(seriesOpt.markPoint);
+ compatItemStyle(seriesOpt.markLine);
+ var data = seriesOpt.data;
+ if (data) {
+ for (var i = 0; i < data.length; i++) {
+ compatItemStyle(data[i]);
+ }
+ // mark point data
+ var markPoint = seriesOpt.markPoint;
+ if (markPoint && markPoint.data) {
+ var mpData = markPoint.data;
+ for (var i = 0; i < mpData.length; i++) {
+ compatItemStyle(mpData[i]);
+ }
+ }
+ // mark line data
+ var markLine = seriesOpt.markLine;
+ if (markLine && markLine.data) {
+ var mlData = markLine.data;
+ for (var i = 0; i < mlData.length; i++) {
+ if (zrUtil.isArray(mlData[i])) {
+ compatItemStyle(mlData[i][0]);
+ compatItemStyle(mlData[i][1]);
+ }
+ else {
+ compatItemStyle(mlData[i]);
+ }
+ }
+ }
+ }
+ };
+
+
+/***/ },
+/* 97 */
+/***/ function(module, exports, __webpack_require__) {
+
+
+
+ var graphic = __webpack_require__(18);
+ var zrUtil = __webpack_require__(4);
+ var PI = Math.PI;
+ /**
+ * @param {module:echarts/ExtensionAPI} api
+ * @param {Object} [opts]
+ * @param {string} [opts.text]
+ * @param {string} [opts.color]
+ * @param {string} [opts.textColor]
+ * @return {module:zrender/Element}
+ */
+ module.exports = function (api, opts) {
+ opts = opts || {};
+ zrUtil.defaults(opts, {
+ text: 'loading',
+ color: '#c23531',
+ textColor: '#000',
+ maskColor: 'rgba(255, 255, 255, 0.8)',
+ zlevel: 0
+ });
+ var mask = new graphic.Rect({
+ style: {
+ fill: opts.maskColor
+ },
+ zlevel: opts.zlevel,
+ z: 10000
+ });
+ var arc = new graphic.Arc({
+ shape: {
+ startAngle: -PI / 2,
+ endAngle: -PI / 2 + 0.1,
+ r: 10
+ },
+ style: {
+ stroke: opts.color,
+ lineCap: 'round',
+ lineWidth: 5
+ },
+ zlevel: opts.zlevel,
+ z: 10001
+ });
+ var labelRect = new graphic.Rect({
+ style: {
+ fill: 'none',
+ text: opts.text,
+ textPosition: 'right',
+ textDistance: 10,
+ textFill: opts.textColor
+ },
+ zlevel: opts.zlevel,
+ z: 10001
+ });
+
+ arc.animateShape(true)
+ .when(1000, {
+ endAngle: PI * 3 / 2
+ })
+ .start('circularInOut');
+ arc.animateShape(true)
+ .when(1000, {
+ startAngle: PI * 3 / 2
+ })
+ .delay(300)
+ .start('circularInOut');
+
+ var group = new graphic.Group();
+ group.add(arc);
+ group.add(labelRect);
+ group.add(mask);
+ // Inject resize
+ group.resize = function () {
+ var cx = api.getWidth() / 2;
+ var cy = api.getHeight() / 2;
+ arc.setShape({
+ cx: cx,
+ cy: cy
+ });
+ var r = arc.shape.r;
+ labelRect.setShape({
+ x: cx - r,
+ y: cy - r,
+ width: r * 2,
+ height: r * 2
+ });
+
+ mask.setShape({
+ x: 0,
+ y: 0,
+ width: api.getWidth(),
+ height: api.getHeight()
+ });
+ };
+ group.resize();
+ return group;
+ };
+
+
+/***/ },
+/* 98 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* WEBPACK VAR INJECTION */(function(global) {/**
+ * List for data storage
+ * @module echarts/data/List
+ */
+
+
+ var UNDEFINED = 'undefined';
+ var globalObj = typeof window === 'undefined' ? global : window;
+ var Float64Array = typeof globalObj.Float64Array === UNDEFINED
+ ? Array : globalObj.Float64Array;
+ var Int32Array = typeof globalObj.Int32Array === UNDEFINED
+ ? Array : globalObj.Int32Array;
+
+ var dataCtors = {
+ 'float': Float64Array,
+ 'int': Int32Array,
+ // Ordinal data type can be string or int
+ 'ordinal': Array,
+ 'number': Array,
+ 'time': Array
+ };
+
+ var Model = __webpack_require__(12);
+ var DataDiffer = __webpack_require__(99);
+
+ var zrUtil = __webpack_require__(4);
+ var modelUtil = __webpack_require__(5);
+ var isObject = zrUtil.isObject;
+
+ var TRANSFERABLE_PROPERTIES = [
+ 'stackedOn', 'hasItemOption', '_nameList', '_idList', '_rawData'
+ ];
+
+ function transferProperties(a, b) {
+ zrUtil.each(TRANSFERABLE_PROPERTIES.concat(b.__wrappedMethods || []), function (propName) {
+ if (b.hasOwnProperty(propName)) {
+ a[propName] = b[propName];
+ }
+ });
+
+ a.__wrappedMethods = b.__wrappedMethods;
+ }
+
+ function DefaultDataProvider(dataArray) {
+ this._array = dataArray || [];
+ }
+
+ DefaultDataProvider.prototype.pure = false;
+
+ DefaultDataProvider.prototype.count = function () {
+ return this._array.length;
+ };
+ DefaultDataProvider.prototype.getItem = function (idx) {
+ return this._array[idx];
+ };
+
+ /**
+ * @constructor
+ * @alias module:echarts/data/List
+ *
+ * @param {Array.} dimensions
+ * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
+ * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
+ * @param {module:echarts/model/Model} hostModel
+ */
+ var List = function (dimensions, hostModel) {
+
+ dimensions = dimensions || ['x', 'y'];
+
+ var dimensionInfos = {};
+ var dimensionNames = [];
+ for (var i = 0; i < dimensions.length; i++) {
+ var dimensionName;
+ var dimensionInfo = {};
+ if (typeof dimensions[i] === 'string') {
+ dimensionName = dimensions[i];
+ dimensionInfo = {
+ name: dimensionName,
+ coordDim: dimensionName,
+ coordDimIndex: 0,
+ stackable: false,
+ // Type can be 'float', 'int', 'number'
+ // Default is number, Precision of float may not enough
+ type: 'number'
+ };
+ }
+ else {
+ dimensionInfo = dimensions[i];
+ dimensionName = dimensionInfo.name;
+ dimensionInfo.type = dimensionInfo.type || 'number';
+ if (!dimensionInfo.coordDim) {
+ dimensionInfo.coordDim = dimensionName;
+ dimensionInfo.coordDimIndex = 0;
+ }
+ }
+ dimensionInfo.otherDims = dimensionInfo.otherDims || {};
+ dimensionNames.push(dimensionName);
+ dimensionInfos[dimensionName] = dimensionInfo;
+ }
+
+ /**
+ * @readOnly
+ * @type {Array.}
+ */
+ this.dimensions = dimensionNames;
+
+ /**
+ * Infomation of each data dimension, like data type.
+ * @type {Object}
+ */
+ this._dimensionInfos = dimensionInfos;
+
+ /**
+ * @type {module:echarts/model/Model}
+ */
+ this.hostModel = hostModel;
+
+ /**
+ * @type {module:echarts/model/Model}
+ */
+ this.dataType;
+
+ /**
+ * Indices stores the indices of data subset after filtered.
+ * This data subset will be used in chart.
+ * @type {Array.}
+ * @readOnly
+ */
+ this.indices = [];
+
+ /**
+ * Data storage
+ * @type {Object.}
+ * @private
+ */
+ this._storage = {};
+
+ /**
+ * @type {Array.}
+ */
+ this._nameList = [];
+ /**
+ * @type {Array.}
+ */
+ this._idList = [];
+
+ /**
+ * Models of data option is stored sparse for optimizing memory cost
+ * @type {Array.}
+ * @private
+ */
+ this._optionModels = [];
+
+ /**
+ * @param {module:echarts/data/List}
+ */
+ this.stackedOn = null;
+
+ /**
+ * Global visual properties after visual coding
+ * @type {Object}
+ * @private
+ */
+ this._visual = {};
+
+ /**
+ * Globel layout properties.
+ * @type {Object}
+ * @private
+ */
+ this._layout = {};
+
+ /**
+ * Item visual properties after visual coding
+ * @type {Array.