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

[echarts] branch release-dev updated: release 5.2.1

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

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


The following commit(s) were added to refs/heads/release-dev by this push:
     new 21d6317  release 5.2.1
21d6317 is described below

commit 21d6317eec76abb9dd17ced5be83424816f7e7d2
Author: pissang <bm...@gmail.com>
AuthorDate: Fri Sep 17 10:44:38 2021 +0800

    release 5.2.1
---
 dist/echarts.common.js         | 509 +++++++++++++++++++++++++++--------------
 dist/echarts.common.js.map     |   2 +-
 dist/echarts.common.min.js     |   4 +-
 dist/echarts.esm.js            | 427 ++++++++++++++++++++--------------
 dist/echarts.esm.js.map        |   2 +-
 dist/echarts.esm.min.js        |   4 +-
 dist/echarts.js                | 427 ++++++++++++++++++++--------------
 dist/echarts.js.map            |   2 +-
 dist/echarts.min.js            |   4 +-
 dist/echarts.simple.js         | 427 +++++++++++++++++++++++++++++-----
 dist/echarts.simple.js.map     |   2 +-
 dist/echarts.simple.min.js     |   4 +-
 dist/extension/dataTool.js.map |   2 +-
 i18n/langPT-br-obj.js          | 174 ++++++++++++++
 i18n/langPT-br.js              | 170 ++++++++++++++
 package-lock.json              |   8 +-
 package.json                   |   4 +-
 src/core/echarts.ts            |   4 +-
 18 files changed, 1577 insertions(+), 599 deletions(-)

diff --git a/dist/echarts.common.js b/dist/echarts.common.js
index 2036b13..9903c55 100644
--- a/dist/echarts.common.js
+++ b/dist/echarts.common.js
@@ -188,6 +188,7 @@
     var nativeMap = arrayProto.map;
     var ctorFunction = function () { }.constructor;
     var protoFunction = ctorFunction ? ctorFunction.prototype : null;
+    var protoKey = '__proto__';
     var methods = {};
     function $override(name, fn) {
         methods[name] = fn;
@@ -236,7 +237,7 @@
         else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
             result = {};
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     result[key] = clone(source[key]);
                 }
             }
@@ -248,7 +249,7 @@
             return overwrite ? clone(source) : target;
         }
         for (var key in source) {
-            if (source.hasOwnProperty(key)) {
+            if (source.hasOwnProperty(key) && key !== protoKey) {
                 var targetProp = target[key];
                 var sourceProp = source[key];
                 if (isObject(sourceProp)
@@ -283,7 +284,7 @@
         }
         else {
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     target[key] = source[key];
                 }
             }
@@ -1221,6 +1222,7 @@
             calculateZrXY(el, e, out);
         }
         else if (env.browser.firefox
+            && env.browser.version < '39'
             && e.layerX != null
             && e.layerX !== e.offsetX) {
             out.zrX = e.layerX;
@@ -2181,7 +2183,7 @@
         ts.forceMergeRuns();
     }
 
-    var REDARAW_BIT = 1;
+    var REDRAW_BIT = 1;
     var STYLE_CHANGED_BIT = 2;
     var SHAPE_CHANGED_BIT = 4;
 
@@ -2265,7 +2267,7 @@
                 for (var i = 0; i < children.length; i++) {
                     var child = children[i];
                     if (el.__dirty) {
-                        child.__dirty |= REDARAW_BIT;
+                        child.__dirty |= REDRAW_BIT;
                     }
                     this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
                 }
@@ -5326,7 +5328,7 @@
                     innerTextDefaultStyle.verticalAlign = textVerticalAlign;
                     textEl.setDefaultTextStyle(innerTextDefaultStyle);
                 }
-                textEl.__dirty |= REDARAW_BIT;
+                textEl.__dirty |= REDRAW_BIT;
                 if (textStyleChanged) {
                     textEl.dirtyStyle(true);
                 }
@@ -5503,7 +5505,7 @@
             this.markRedraw();
             if (!useHoverLayer && this.__inHover) {
                 this._toggleHoverLayerFlag(false);
-                this.__dirty &= ~REDARAW_BIT;
+                this.__dirty &= ~REDRAW_BIT;
             }
             return state;
         };
@@ -5562,7 +5564,7 @@
                 this.markRedraw();
                 if (!useHoverLayer && this.__inHover) {
                     this._toggleHoverLayerFlag(false);
-                    this.__dirty &= ~REDARAW_BIT;
+                    this.__dirty &= ~REDRAW_BIT;
                 }
             }
         };
@@ -5773,7 +5775,7 @@
             }
         };
         Element.prototype.markRedraw = function () {
-            this.__dirty |= REDARAW_BIT;
+            this.__dirty |= REDRAW_BIT;
             var zr = this.__zr;
             if (zr) {
                 if (this.__inHover) {
@@ -5922,7 +5924,7 @@
             elProto.dragging = false;
             elProto.ignoreClip = false;
             elProto.__inHover = false;
-            elProto.__dirty = REDARAW_BIT;
+            elProto.__dirty = REDRAW_BIT;
             var logs = {};
             function logDeprecatedError(key, xKey, yKey) {
                 if (!logs[key + xKey + yKey]) {
@@ -6593,7 +6595,7 @@
     function registerPainter(name, Ctor) {
         painterCtors[name] = Ctor;
     }
-    var version = '5.2.0';
+    var version = '5.2.1';
 
     var zrender = /*#__PURE__*/Object.freeze({
         __proto__: null,
@@ -9086,7 +9088,7 @@
             dispProto.incremental = false;
             dispProto._rect = null;
             dispProto.dirtyRectTolerance = 0;
-            dispProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT;
+            dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
         })();
         return Displayable;
     }(Element));
@@ -10867,7 +10869,7 @@
                 for (var i = 0; i < pathCopyParams.length; ++i) {
                     decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
                 }
-                decalEl.__dirty |= REDARAW_BIT;
+                decalEl.__dirty |= REDRAW_BIT;
             }
             else if (this._decalEl) {
                 this._decalEl = null;
@@ -11193,7 +11195,7 @@
             pathProto.segmentIgnoreThreshold = 0;
             pathProto.subPixelOptimize = false;
             pathProto.autoBatch = false;
-            pathProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
+            pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
         })();
         return Path;
     }(Displayable));
@@ -26829,7 +26831,7 @@
     function brush(ctx, el, scope, isLast) {
         var m = el.transform;
         if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
-            el.__dirty &= ~REDARAW_BIT;
+            el.__dirty &= ~REDRAW_BIT;
             el.__isRendered = false;
             return;
         }
@@ -27701,7 +27703,7 @@
                     inheritStyle(parentGroup, img);
                     parseAttributes(xmlNode, img, this._defsUsePending, false, false);
                     img.setStyle({
-                        image: xmlNode.getAttribute('xlink:href'),
+                        image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'),
                         x: +xmlNode.getAttribute('x'),
                         y: +xmlNode.getAttribute('y'),
                         width: +xmlNode.getAttribute('width'),
@@ -29101,9 +29103,9 @@
     var lifecycle = new Eventful();
 
     var hasWindow = typeof window !== 'undefined';
-    var version$1 = '5.2.0';
+    var version$1 = '5.2.1';
     var dependencies = {
-      zrender: '5.2.0'
+      zrender: '5.2.1'
     };
     var TEST_FRAME_REMAIN_TIME = 1;
     var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
@@ -36315,7 +36317,8 @@
     // `scale.setExtent` or `scale.unionExtentFromData`;
 
 
-    function niceScaleExtent(scale, model) {
+    function niceScaleExtent(scale, inModel) {
+      var model = inModel;
       var extentInfo = getScaleExtent(scale, model);
       var extent = extentInfo.extent;
       var splitNumber = model.get('splitNumber');
@@ -36880,6 +36883,7 @@
       return {
         labels: map(ticks, function (tick, idx) {
           return {
+            level: tick.level,
             formattedLabel: labelFormatter(tick, idx),
             rawLabel: axis.scale.getLabel(tick),
             tickValue: tick.value
@@ -37679,6 +37683,46 @@
       return statesModels;
     }
 
+    function prepareLayoutList(input) {
+      var list = [];
+
+      for (var i = 0; i < input.length; i++) {
+        var rawItem = input[i];
+
+        if (rawItem.defaultAttr.ignore) {
+          continue;
+        }
+
+        var label = rawItem.label;
+        var transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el.
+
+        var localRect = label.getBoundingRect();
+        var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5;
+        var minMargin = label.style.margin || 0;
+        var globalRect = localRect.clone();
+        globalRect.applyTransform(transform);
+        globalRect.x -= minMargin / 2;
+        globalRect.y -= minMargin / 2;
+        globalRect.width += minMargin;
+        globalRect.height += minMargin;
+        var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
+        list.push({
+          label: label,
+          labelLine: rawItem.labelLine,
+          rect: globalRect,
+          localRect: localRect,
+          obb: obb,
+          priority: rawItem.priority,
+          defaultAttr: rawItem.defaultAttr,
+          layoutOption: rawItem.computedLayoutOption,
+          axisAligned: isAxisAligned,
+          transform: transform
+        });
+      }
+
+      return list;
+    }
+
     function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) {
       var len = list.length;
 
@@ -37847,6 +37891,83 @@
     balanceShift) {
       return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift);
     }
+    function hideOverlap(labelList) {
+      var displayedLabels = []; // TODO, render overflow visible first, put in the displayedLabels.
+
+      labelList.sort(function (a, b) {
+        return b.priority - a.priority;
+      });
+      var globalRect = new BoundingRect(0, 0, 0, 0);
+
+      function hideEl(el) {
+        if (!el.ignore) {
+          // Show on emphasis.
+          var emphasisState = el.ensureState('emphasis');
+
+          if (emphasisState.ignore == null) {
+            emphasisState.ignore = false;
+          }
+        }
+
+        el.ignore = true;
+      }
+
+      for (var i = 0; i < labelList.length; i++) {
+        var labelItem = labelList[i];
+        var isAxisAligned = labelItem.axisAligned;
+        var localRect = labelItem.localRect;
+        var transform = labelItem.transform;
+        var label = labelItem.label;
+        var labelLine = labelItem.labelLine;
+        globalRect.copy(labelItem.rect); // Add a threshold because layout may be aligned precisely.
+
+        globalRect.width -= 0.1;
+        globalRect.height -= 0.1;
+        globalRect.x += 0.05;
+        globalRect.y += 0.05;
+        var obb = labelItem.obb;
+        var overlapped = false;
+
+        for (var j = 0; j < displayedLabels.length; j++) {
+          var existsTextCfg = displayedLabels[j]; // Fast rejection.
+
+          if (!globalRect.intersect(existsTextCfg.rect)) {
+            continue;
+          }
+
+          if (isAxisAligned && existsTextCfg.axisAligned) {
+            // Is overlapped
+            overlapped = true;
+            break;
+          }
+
+          if (!existsTextCfg.obb) {
+            // If self is not axis aligned. But other is.
+            existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform);
+          }
+
+          if (!obb) {
+            // If self is axis aligned. But other is not.
+            obb = new OrientedBoundingRect(localRect, transform);
+          }
+
+          if (obb.intersect(existsTextCfg.obb)) {
+            overlapped = true;
+            break;
+          }
+        } // TODO Callback to determine if this overlap should be handled?
+
+
+        if (overlapped) {
+          hideEl(label);
+          labelLine && hideEl(labelLine);
+        } else {
+          label.attr('ignore', labelItem.defaultAttr.ignore);
+          labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
+          displayedLabels.push(labelItem);
+        }
+      }
+    }
 
     function createElement(name) {
         return document.createElementNS('http://www.w3.org/2000/svg', name);
@@ -38062,7 +38183,7 @@
     function bindStyle(svgEl, style, el) {
         var opacity = style.opacity == null ? 1 : style.opacity;
         if (el instanceof ZRImage) {
-            svgEl.style.opacity = opacity + '';
+            attr(svgEl, 'opacity', opacity + '');
             return;
         }
         if (pathHasFill(style)) {
@@ -38103,7 +38224,7 @@
                 attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + '');
             }
             else {
-                attr(svgEl, 'stroke-dasharray', '');
+                attr(svgEl, 'stroke-dasharray', NONE);
             }
             style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap);
             style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin);
@@ -38893,7 +39014,7 @@
         ShadowManager.prototype.remove = function (svgElement, displayable) {
             if (displayable._shadowDom != null) {
                 displayable._shadowDom = null;
-                svgElement.style.filter = '';
+                svgElement.removeAttribute('filter');
             }
         };
         ShadowManager.prototype.updateDom = function (svgElement, displayable, shadowDom) {
@@ -38923,7 +39044,7 @@
             shadowDom.setAttribute('height', '300%');
             displayable._shadowDom = shadowDom;
             var id = shadowDom.getAttribute('id');
-            svgElement.style.filter = 'url(#' + id + ')';
+            svgElement.setAttribute('filter', 'url(#' + id + ')');
         };
         ShadowManager.prototype.removeUnused = function () {
             var defs = this.getDefs(false);
@@ -39412,13 +39533,13 @@
                 var el = displayList[i];
                 if (el) {
                     var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
-                    var prevRect = el.__isRendered && ((el.__dirty & REDARAW_BIT) || !shouldPaint)
+                    var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint)
                         ? el.getPrevPaintRect()
                         : null;
                     if (prevRect) {
                         addRectToMergePool(prevRect);
                     }
-                    var curRect = shouldPaint && ((el.__dirty & REDARAW_BIT) || !el.__isRendered)
+                    var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered)
                         ? el.getPaintRect()
                         : null;
                     if (curRect) {
@@ -40026,7 +40147,7 @@
                     updatePrevLayer(i);
                     prevLayer = layer;
                 }
-                if ((el.__dirty & REDARAW_BIT) && !el.__inHover) {
+                if ((el.__dirty & REDRAW_BIT) && !el.__inHover) {
                     layer.__dirty = true;
                     if (layer.incremental && layer.__drawIndex < 0) {
                         layer.__drawIndex = i;
@@ -41763,8 +41884,60 @@
       stepPoints.push(points[i++], points[i++]);
       return stepPoints;
     }
+    /**
+     * Clip color stops to edge. Avoid creating too large gradients.
+     * Which may lead to blurry when GPU acceleration is enabled. See #15680
+     *
+     * The stops has been sorted from small to large.
+     */
+
+
+    function clipColorStops(colorStops, maxSize) {
+      var newColorStops = [];
+      var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop.
+
+      var prevOutOfRangeColorStop;
+      var prevInRangeColorStop;
+
+      function lerpStop(stop0, stop1, clippedCoord) {
+        var coord0 = stop0.coord;
+        var p = (clippedCoord - coord0) / (stop1.coord - coord0);
+        var color = lerp$1(p, [stop0.color, stop1.color]);
+        return {
+          coord: clippedCoord,
+          color: color
+        };
+      }
+
+      for (var i = 0; i < len; i++) {
+        var stop_1 = colorStops[i];
+        var coord = stop_1.coord;
+
+        if (coord < 0) {
+          prevOutOfRangeColorStop = stop_1;
+        } else if (coord > maxSize) {
+          if (prevInRangeColorStop) {
+            newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize));
+          } // All following stop will be out of range. So just ignore them.
+
+
+          break;
+        } else {
+          if (prevOutOfRangeColorStop) {
+            newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset
+
+            prevOutOfRangeColorStop = null;
+          }
+
+          newColorStops.push(stop_1);
+          prevInRangeColorStop = stop_1;
+        }
+      }
+
+      return newColorStops;
+    }
 
-    function getVisualGradient(data, coordSys) {
+    function getVisualGradient(data, coordSys, api) {
       var visualMetaList = data.getVisual('visualMeta');
 
       if (!visualMetaList || !visualMetaList.length || !data.count()) {
@@ -41807,16 +41980,12 @@
       // LinearGradient to render `outerColors`.
 
 
-      var axis = coordSys.getAxis(coordDim);
-      var axisScaleExtent = axis.scale.getExtent(); // dataToCoord mapping may not be linear, but must be monotonic.
+      var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic.
 
       var colorStops = map(visualMeta.stops, function (stop) {
-        var coord = axis.toGlobalCoord(axis.dataToCoord(stop.value)); // normalize the infinite value
-
-        isNaN(coord) || isFinite(coord) || (coord = axis.toGlobalCoord(axis.dataToCoord(axisScaleExtent[+(coord < 0)])));
+        // offset will be calculated later.
         return {
-          offset: 0,
-          coord: coord,
+          coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
           color: stop.color
         };
       });
@@ -41828,32 +41997,37 @@
         outerColors.reverse();
       }
 
-      var tinyExtent = 10; // Arbitrary value: 10px
+      var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight());
+      var inRangeStopLen = colorStopsInRange.length;
+
+      if (!inRangeStopLen && stopLen) {
+        // All stops are out of range. All will be the same color.
+        return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color;
+      }
+
+      var tinyExtent = 0; // Arbitrary value: 10px
 
-      var minCoord = colorStops[0].coord - tinyExtent;
-      var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
+      var minCoord = colorStopsInRange[0].coord - tinyExtent;
+      var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent;
       var coordSpan = maxCoord - minCoord;
 
       if (coordSpan < 1e-3) {
         return 'transparent';
       }
 
-      each(colorStops, function (stop) {
+      each(colorStopsInRange, function (stop) {
         stop.offset = (stop.coord - minCoord) / coordSpan;
       });
-      colorStops.push({
-        offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
+      colorStopsInRange.push({
+        // NOTE: inRangeStopLen may still be 0 if stoplen is zero.
+        offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5,
         color: outerColors[1] || 'transparent'
       });
-      colorStops.unshift({
-        offset: stopLen ? colorStops[0].offset : 0.5,
+      colorStopsInRange.unshift({
+        offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5,
         color: outerColors[0] || 'transparent'
-      }); // zrUtil.each(colorStops, function (colorStop) {
-      //     // Make sure each offset has rounded px to avoid not sharp edge
-      //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
-      // });
-
-      var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
+      });
+      var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true);
       gradient[coordDim] = minCoord;
       gradient[coordDim + '2'] = maxCoord;
       return gradient;
@@ -42128,7 +42302,7 @@
         }
 
         this._clipShapeForSymbol = clipShapeForSymbol;
-        var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
+        var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
 
         if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
           showSymbol && symbolDraw.updateData(data, {
@@ -42178,9 +42352,19 @@
           } // Update clipPath
 
 
-          lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
+          var oldClipPath = lineGroup.getClipPath();
+
+          if (oldClipPath) {
+            var newClipPath = createLineClipPath(this, coordSys, false, seriesModel);
+            initProps(oldClipPath, {
+              shape: newClipPath.shape
+            }, seriesModel);
+          } else {
+            lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
+          } // Always update, or it is wrong in the case turning on legend
           // because points are not changed
 
+
           showSymbol && symbolDraw.updateData(data, {
             isIgnore: isIgnoreFunc,
             clipShape: clipShapeForSymbol,
@@ -42651,11 +42835,13 @@
 
 
         if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
+          polyline.stopAnimation();
           polyline.setShape({
             points: next
           });
 
           if (polygon) {
+            polygon.stopAnimation();
             polygon.setShape({
               points: next,
               stackedOnPoints: stackedOnNext
@@ -43927,16 +44113,9 @@
         return rect;
       },
       polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
-        // Keep the same logic with bar in catesion: use end value to control
-        // direction. Notice that if clockwise is true (by default), the sector
-        // will always draw clockwisely, no matter whether endAngle is greater
-        // or less than startAngle.
-        var clockwise = layout.startAngle < layout.endAngle;
         var ShapeClass = !isRadial && roundCap ? SausagePath : Sector;
         var sector = new ShapeClass({
-          shape: defaults({
-            clockwise: clockwise
-          }, layout),
+          shape: layout,
           z2: 1
         });
         sector.name = 'item';
@@ -44067,7 +44246,8 @@
           r0: layout.r0,
           r: layout.r,
           startAngle: layout.startAngle,
-          endAngle: layout.endAngle
+          endAngle: layout.endAngle,
+          clockwise: layout.clockwise
         };
       }
     };
@@ -47393,7 +47573,21 @@
         var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
         var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
         fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
-        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection);
+        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart.
+        // See https://github.com/apache/echarts/issues/14266 for more.
+
+        if (axisModel.get(['axisLabel', 'hideOverlap'])) {
+          var labelList = prepareLayoutList(map(labelEls, function (label) {
+            return {
+              label: label,
+              priority: label.z2,
+              defaultAttr: {
+                ignore: label.ignore
+              }
+            };
+          }));
+          hideOverlap(labelList);
+        }
       },
       axisName: function (opt, axisModel, group, transformGroup) {
         var name = retrieve(opt.axisName, axisModel.get('name'));
@@ -47716,7 +47910,7 @@
           y: opt.labelOffset + opt.labelDirection * labelMargin,
           rotation: labelLayout.rotation,
           silent: silent,
-          z2: 10,
+          z2: 10 + (labelItem.level || 0),
           style: createTextStyle(itemLabelModel, {
             text: formattedLabel,
             align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
@@ -55235,7 +55429,15 @@
 
         this._initGlobalListener();
 
-        this._keepShow();
+        this._keepShow(); // PENDING
+        // `mousemove` event will be triggered very frequently when the mouse moves fast,
+        // which causes that the updatePosition was also called very frequently.
+        // In Chrome with devtools open and Firefox, tooltip looks lagged and shaked around. See #14695.
+        // To avoid the frequent triggering,
+        // consider throttling it in 50ms. (the tested result may need to validate)
+
+
+        this._updatePosition = this._renderMode === 'html' ? throttle(bind$2(this._doUpdatePosition, this), 50) : this._doUpdatePosition;
       };
 
       TooltipView.prototype._initGlobalListener = function () {
@@ -55743,7 +55945,7 @@
         }
       };
 
-      TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x
+      TooltipView.prototype._doUpdatePosition = function (tooltipModel, positionExpr, x, // Mouse x
       y, // Mouse y
       content, params, el) {
         var viewWidth = this._api.getWidth();
@@ -56587,13 +56789,14 @@
       // Alwalys return true if there is no coordSys
       return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
     }
-    function dimValueGetter(item, dimName, dataIndex, dimIndex) {
-      // x, y, radius, angle
-      if (dimIndex < 2) {
-        return item.coord && item.coord[dimIndex];
-      }
-
-      return item.value;
+    function createMarkerDimValueGetter(inCoordSys, dims) {
+      return inCoordSys ? function (item, dimName, dataIndex, dimIndex) {
+        var rawVal = dimIndex < 2 // x, y, radius, angle
+        ? item.coord && item.coord[dimIndex] : item.value;
+        return parseDataValue(rawVal, dims[dimIndex]);
+      } : function (item, dimName, dataIndex, dimIndex) {
+        return parseDataValue(item.value, dims[dimIndex]);
+      };
     }
     function numCalculate(data, valueDataDim, type) {
       if (type === 'average') {
@@ -56830,9 +57033,8 @@
         dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys));
       }
 
-      mpData.initData(dataOpt, null, coordSys ? dimValueGetter : function (item) {
-        return item.value;
-      });
+      var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
+      mpData.initData(dataOpt, null, dimValueGetter);
       return mpData;
     }
 
@@ -57850,15 +58052,13 @@
         optData = filter(optData, curry(markLineFilter, coordSys));
       }
 
-      var dimValueGetter$1 = coordSys ? dimValueGetter : function (item) {
-        return item.value;
-      };
+      var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
       fromData.initData(map(optData, function (item) {
         return item[0];
-      }), null, dimValueGetter$1);
+      }), null, dimValueGetter);
       toData.initData(map(optData, function (item) {
         return item[1];
-      }), null, dimValueGetter$1);
+      }), null, dimValueGetter);
       lineData.initData(map(optData, function (item) {
         return item[2];
       }));
@@ -58185,12 +58385,12 @@
     }(MarkerView);
 
     function createList$2(coordSys, seriesModel, maModel) {
-      var coordDimsInfos;
       var areaData;
+      var dataDims;
       var dims = ['x0', 'y0', 'x1', 'y1'];
 
       if (coordSys) {
-        coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
+        var coordDimsInfos_1 = map(coordSys && coordSys.dimensions, function (coordDim) {
           var data = seriesModel.getData();
           var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
 
@@ -58200,18 +58400,19 @@
             ordinalMeta: null
           });
         });
-        areaData = new SeriesData(map(dims, function (dim, idx) {
+        dataDims = map(dims, function (dim, idx) {
           return {
             name: dim,
-            type: coordDimsInfos[idx % 2].type
+            type: coordDimsInfos_1[idx % 2].type
           };
-        }), maModel);
+        });
+        areaData = new SeriesData(dataDims, maModel);
       } else {
-        coordDimsInfos = [{
+        dataDims = [{
           name: 'value',
           type: 'float'
         }];
-        areaData = new SeriesData(coordDimsInfos, maModel);
+        areaData = new SeriesData(dataDims, maModel);
       }
 
       var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel));
@@ -58222,9 +58423,10 @@
 
       var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
         // TODO should convert to ParsedValue?
-        return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
-      } : function (item) {
-        return item.value;
+        var rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
+        return parseDataValue(rawVal, dataDims[dimIndex]);
+      } : function (item, dimName, dataIndex, dimIndex) {
+        return parseDataValue(item.value, dataDims[dimIndex]);
       };
       areaData.initData(optData, null, dimValueGetter);
       areaData.hasItemOption = true;
@@ -58482,17 +58684,13 @@
         itemWidth: 25,
         itemHeight: 14,
         symbolRotate: 'inherit',
+        symbolKeepAspect: true,
         inactiveColor: '#ccc',
         inactiveBorderColor: '#ccc',
         inactiveBorderWidth: 'auto',
         itemStyle: {
           color: 'inherit',
           opacity: 'inherit',
-          decal: 'inherit',
-          shadowBlur: 0,
-          shadowColor: null,
-          shadowOffsetX: 0,
-          shadowOffsetY: 0,
           borderColor: 'inherit',
           borderWidth: 'auto',
           borderCap: 'inherit',
@@ -58510,11 +58708,7 @@
           cap: 'inherit',
           join: 'inherit',
           dashOffset: 'inherit',
-          miterLimit: 'inherit',
-          shadowBlur: 0,
-          shadowColor: null,
-          shadowOffsetX: 0,
-          shadowOffsetY: 0
+          miterLimit: 'inherit'
         },
         textStyle: {
           color: '#333'
@@ -58526,7 +58720,7 @@
           borderRadius: 10,
           padding: [3, 5, 3, 5],
           fontSize: 12,
-          fontFamily: ' sans-serif',
+          fontFamily: 'sans-serif',
           color: '#666',
           borderWidth: 1,
           borderColor: '#666'
@@ -58772,10 +58966,10 @@
         var itemHeight = legendModel.get('itemHeight');
         var isSelected = legendModel.isSelected(name);
         var iconRotate = legendItemModel.get('symbolRotate');
+        var symbolKeepAspect = legendItemModel.get('symbolKeepAspect');
         var legendIconType = legendItemModel.get('icon');
         legendIcon = legendIconType || legendIcon || 'roundRect';
-        var legendLineStyle = legendModel.getModel('lineStyle');
-        var style = getLegendStyle(legendIcon, legendItemModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected);
+        var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected);
         var itemGroup = new Group$1();
         var textStyleModel = legendItemModel.getModel('textStyle');
 
@@ -58787,7 +58981,8 @@
             icon: legendIcon,
             iconRotate: iconRotate,
             itemStyle: style.itemStyle,
-            lineStyle: style.lineStyle
+            lineStyle: style.lineStyle,
+            symbolKeepAspect: symbolKeepAspect
           }));
         } else {
           // Use default legend icon policy for most series
@@ -58799,7 +58994,8 @@
             icon: legendIcon,
             iconRotate: rotate,
             itemStyle: style.itemStyle,
-            lineStyle: style.lineStyle
+            lineStyle: style.lineStyle,
+            symbolKeepAspect: symbolKeepAspect
           }));
         }
 
@@ -58915,77 +59111,56 @@
       return LegendView;
     }(ComponentView);
 
-    function getLegendStyle(iconType, legendModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
+    function getLegendStyle(iconType, legendModel, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
       /**
        * Use series style if is inherit;
        * elsewise, use legend style
        */
-      // itemStyle
+      function handleCommonProps(style, visualStyle) {
+        // If lineStyle.width is 'auto', it is set to be 2 if series has border
+        if (style.lineWidth === 'auto') {
+          style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0;
+        }
+
+        each$8(style, function (propVal, propName) {
+          style[propName] === 'inherit' && (style[propName] = visualStyle[propName]);
+        });
+      } // itemStyle
+
+
       var legendItemModel = legendModel.getModel('itemStyle');
-      var itemProperties = ITEM_STYLE_KEY_MAP.concat([['decal']]);
-      var itemStyle = {};
-
-      for (var i = 0; i < itemProperties.length; ++i) {
-        var propName = itemProperties[i][itemProperties[i].length - 1];
-        var visualName = itemProperties[i][0];
-        var value = legendItemModel.getShallow(propName);
-
-        if (value === 'inherit') {
-          switch (visualName) {
-            case 'fill':
-              /**
-               * Series with visualDrawType as 'stroke' should have
-               * series stroke as legend fill
-               */
-              itemStyle.fill = itemVisualStyle[drawType];
-              break;
+      var itemStyle = legendItemModel.getItemStyle();
+      var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke';
+      itemStyle.decal = itemVisualStyle.decal;
 
-            case 'stroke':
-              /**
-               * icon type with "emptyXXX" should use fill color
-               * in visual style
-               */
-              itemStyle.stroke = itemVisualStyle[iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'];
-              break;
+      if (itemStyle.fill === 'inherit') {
+        /**
+         * Series with visualDrawType as 'stroke' should have
+         * series stroke as legend fill
+         */
+        itemStyle.fill = itemVisualStyle[drawType];
+      }
 
-            case 'opacity':
-              /**
-               * Use lineStyle.opacity if drawType is stroke
-               */
-              itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
-              break;
+      if (itemStyle.stroke === 'inherit') {
+        /**
+         * icon type with "emptyXXX" should use fill color
+         * in visual style
+         */
+        itemStyle.stroke = itemVisualStyle[iconBrushType];
+      }
 
-            default:
-              itemStyle[visualName] = itemVisualStyle[visualName];
-          }
-        } else if (value === 'auto' && visualName === 'lineWidth') {
-          // If lineStyle.width is 'auto', it is set to be 2 if series has border
-          itemStyle.lineWidth = itemVisualStyle.lineWidth > 0 ? 2 : 0;
-        } else {
-          itemStyle[visualName] = value;
-        }
-      } // lineStyle
+      if (itemStyle.opacity === 'inherit') {
+        /**
+         * Use lineStyle.opacity if drawType is stroke
+         */
+        itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
+      }
 
+      handleCommonProps(itemStyle, itemVisualStyle); // lineStyle
 
       var legendLineModel = legendModel.getModel('lineStyle');
-      var lineProperties = LINE_STYLE_KEY_MAP.concat([['inactiveColor'], ['inactiveWidth']]);
-      var lineStyle = {};
-
-      for (var i = 0; i < lineProperties.length; ++i) {
-        var propName = lineProperties[i][1];
-        var visualName = lineProperties[i][0];
-        var value = legendLineModel.getShallow(propName);
-
-        if (value === 'inherit') {
-          lineStyle[visualName] = lineVisualStyle[visualName];
-        } else if (value === 'auto' && visualName === 'lineWidth') {
-          // If lineStyle.width is 'auto', it is set to be 2 if series has border
-          lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0;
-        } else {
-          lineStyle[visualName] = value;
-        }
-      } // Fix auto color to real color
-
+      var lineStyle = legendLineModel.getLineStyle();
+      handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color
 
       itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
       itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
@@ -58999,12 +59174,12 @@
          * use border only when series has border if is set to be auto
          */
 
-        var visualHasBorder = itemStyle[iconType.indexOf('empty') > -1 ? 'fill' : 'stroke'];
+        var visualHasBorder = itemStyle[iconBrushType];
         itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
         itemStyle.fill = legendModel.get('inactiveColor');
         itemStyle.stroke = legendModel.get('inactiveBorderColor');
-        lineStyle.stroke = legendLineStyle.get('inactiveColor');
-        lineStyle.lineWidth = legendLineStyle.get('inactiveWidth');
+        lineStyle.stroke = legendLineModel.get('inactiveColor');
+        lineStyle.lineWidth = legendLineModel.get('inactiveWidth');
       }
 
       return {
@@ -59015,7 +59190,7 @@
 
     function getDefaultLegendIcon(opt) {
       var symboType = opt.icon || 'roundRect';
-      var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill);
+      var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
       icon.setStyle(opt.itemStyle);
       icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
       icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
diff --git a/dist/echarts.common.js.map b/dist/echarts.common.js.map
index f4d8b9b..ee2380a 100644
--- a/dist/echarts.common.js.map
+++ b/dist/echarts.common.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.common.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
+{"version":3,"file":"echarts.common.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
diff --git a/dist/echarts.common.min.js b/dist/echarts.common.min.js
index 5931625..57f74ad 100644
--- a/dist/echarts.common.min.js
+++ b/dist/echarts.common.min.js
@@ -32,7 +32,7 @@
     LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     PERFORMANCE OF THIS SOFTWARE.
-    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
+    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
 /*!
     * ZRender, a high performance 2d drawing library.
     *
@@ -42,4 +42,4 @@
     * LICENSE
     * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
     */
-var Li=!a.canvasSupported,Ri={},Ni={};var Ei=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new _e,o=n.renderer||"canvas";if(Li)throw new Error("IE8 support has been dropped since 5.0");if(Ri[o]||(o=E(Ri)[0]),!Ri[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
+var Ri=!a.canvasSupported,Ni={},Ei={};var zi=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new xe,o=n.renderer||"canvas";if(Ri)throw new Error("IE8 support has been dropped since 5.0");if(Ni[o]||(o=z(Ni)[0]),!Ni[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
diff --git a/dist/echarts.esm.js b/dist/echarts.esm.js
index f801962..78c01f5 100644
--- a/dist/echarts.esm.js
+++ b/dist/echarts.esm.js
@@ -182,6 +182,7 @@ var nativeSlice = arrayProto.slice;
 var nativeMap = arrayProto.map;
 var ctorFunction = function () { }.constructor;
 var protoFunction = ctorFunction ? ctorFunction.prototype : null;
+var protoKey = '__proto__';
 var methods = {};
 function $override(name, fn) {
     methods[name] = fn;
@@ -230,7 +231,7 @@ function clone(source) {
     else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
         result = {};
         for (var key in source) {
-            if (source.hasOwnProperty(key)) {
+            if (source.hasOwnProperty(key) && key !== protoKey) {
                 result[key] = clone(source[key]);
             }
         }
@@ -242,7 +243,7 @@ function merge(target, source, overwrite) {
         return overwrite ? clone(source) : target;
     }
     for (var key in source) {
-        if (source.hasOwnProperty(key)) {
+        if (source.hasOwnProperty(key) && key !== protoKey) {
             var targetProp = target[key];
             var sourceProp = source[key];
             if (isObject(sourceProp)
@@ -277,7 +278,7 @@ function extend(target, source) {
     }
     else {
         for (var key in source) {
-            if (source.hasOwnProperty(key)) {
+            if (source.hasOwnProperty(key) && key !== protoKey) {
                 target[key] = source[key];
             }
         }
@@ -1215,6 +1216,7 @@ function clientToLocal(el, e, out, calculate) {
         calculateZrXY(el, e, out);
     }
     else if (env.browser.firefox
+        && env.browser.version < '39'
         && e.layerX != null
         && e.layerX !== e.offsetX) {
         out.zrX = e.layerX;
@@ -2175,7 +2177,7 @@ function sort(array, compare, lo, hi) {
     ts.forceMergeRuns();
 }
 
-var REDARAW_BIT = 1;
+var REDRAW_BIT = 1;
 var STYLE_CHANGED_BIT = 2;
 var SHAPE_CHANGED_BIT = 4;
 
@@ -2259,7 +2261,7 @@ var Storage = (function () {
             for (var i = 0; i < children.length; i++) {
                 var child = children[i];
                 if (el.__dirty) {
-                    child.__dirty |= REDARAW_BIT;
+                    child.__dirty |= REDRAW_BIT;
                 }
                 this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
             }
@@ -5320,7 +5322,7 @@ var Element = (function () {
                 innerTextDefaultStyle.verticalAlign = textVerticalAlign;
                 textEl.setDefaultTextStyle(innerTextDefaultStyle);
             }
-            textEl.__dirty |= REDARAW_BIT;
+            textEl.__dirty |= REDRAW_BIT;
             if (textStyleChanged) {
                 textEl.dirtyStyle(true);
             }
@@ -5497,7 +5499,7 @@ var Element = (function () {
         this.markRedraw();
         if (!useHoverLayer && this.__inHover) {
             this._toggleHoverLayerFlag(false);
-            this.__dirty &= ~REDARAW_BIT;
+            this.__dirty &= ~REDRAW_BIT;
         }
         return state;
     };
@@ -5556,7 +5558,7 @@ var Element = (function () {
             this.markRedraw();
             if (!useHoverLayer && this.__inHover) {
                 this._toggleHoverLayerFlag(false);
-                this.__dirty &= ~REDARAW_BIT;
+                this.__dirty &= ~REDRAW_BIT;
             }
         }
     };
@@ -5767,7 +5769,7 @@ var Element = (function () {
         }
     };
     Element.prototype.markRedraw = function () {
-        this.__dirty |= REDARAW_BIT;
+        this.__dirty |= REDRAW_BIT;
         var zr = this.__zr;
         if (zr) {
             if (this.__inHover) {
@@ -5916,7 +5918,7 @@ var Element = (function () {
         elProto.dragging = false;
         elProto.ignoreClip = false;
         elProto.__inHover = false;
-        elProto.__dirty = REDARAW_BIT;
+        elProto.__dirty = REDRAW_BIT;
         var logs = {};
         function logDeprecatedError(key, xKey, yKey) {
             if (!logs[key + xKey + yKey]) {
@@ -6587,7 +6589,7 @@ function getInstance(id) {
 function registerPainter(name, Ctor) {
     painterCtors[name] = Ctor;
 }
-var version = '5.2.0';
+var version = '5.2.1';
 
 var zrender = /*#__PURE__*/Object.freeze({
     __proto__: null,
@@ -9157,7 +9159,7 @@ var Displayable = (function (_super) {
         dispProto.incremental = false;
         dispProto._rect = null;
         dispProto.dirtyRectTolerance = 0;
-        dispProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT;
+        dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
     })();
     return Displayable;
 }(Element));
@@ -10938,7 +10940,7 @@ var Path = (function (_super) {
             for (var i = 0; i < pathCopyParams.length; ++i) {
                 decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
             }
-            decalEl.__dirty |= REDARAW_BIT;
+            decalEl.__dirty |= REDRAW_BIT;
         }
         else if (this._decalEl) {
             this._decalEl = null;
@@ -11264,7 +11266,7 @@ var Path = (function (_super) {
         pathProto.segmentIgnoreThreshold = 0;
         pathProto.subPixelOptimize = false;
         pathProto.autoBatch = false;
-        pathProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
+        pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
     })();
     return Path;
 }(Displayable));
@@ -27153,7 +27155,7 @@ function brushSingle(ctx, el) {
 function brush(ctx, el, scope, isLast) {
     var m = el.transform;
     if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
-        el.__dirty &= ~REDARAW_BIT;
+        el.__dirty &= ~REDRAW_BIT;
         el.__isRendered = false;
         return;
     }
@@ -28025,7 +28027,7 @@ var SVGParser = (function () {
                 inheritStyle(parentGroup, img);
                 parseAttributes(xmlNode, img, this._defsUsePending, false, false);
                 img.setStyle({
-                    image: xmlNode.getAttribute('xlink:href'),
+                    image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'),
                     x: +xmlNode.getAttribute('x'),
                     y: +xmlNode.getAttribute('y'),
                     width: +xmlNode.getAttribute('width'),
@@ -29425,9 +29427,9 @@ var geoSourceManager = {
 var lifecycle = new Eventful();
 
 var hasWindow = typeof window !== 'undefined';
-var version$1 = '5.2.0';
+var version$1 = '5.2.1';
 var dependencies = {
-  zrender: '5.2.0'
+  zrender: '5.2.1'
 };
 var TEST_FRAME_REMAIN_TIME = 1;
 var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
@@ -36674,7 +36676,8 @@ barWidthAndOffset) {
 // `scale.setExtent` or `scale.unionExtentFromData`;
 
 
-function niceScaleExtent(scale, model) {
+function niceScaleExtent(scale, inModel) {
+  var model = inModel;
   var extentInfo = getScaleExtent(scale, model);
   var extent = extentInfo.extent;
   var splitNumber = model.get('splitNumber');
@@ -37239,6 +37242,7 @@ function makeRealNumberLabels(axis) {
   return {
     labels: map(ticks, function (tick, idx) {
       return {
+        level: tick.level,
         formattedLabel: labelFormatter(tick, idx),
         rawLabel: axis.scale.getLabel(tick),
         tickValue: tick.value
@@ -39299,7 +39303,7 @@ function attrXML(el, key, val) {
 function bindStyle(svgEl, style, el) {
     var opacity = style.opacity == null ? 1 : style.opacity;
     if (el instanceof ZRImage) {
-        svgEl.style.opacity = opacity + '';
+        attr(svgEl, 'opacity', opacity + '');
         return;
     }
     if (pathHasFill(style)) {
@@ -39340,7 +39344,7 @@ function bindStyle(svgEl, style, el) {
             attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + '');
         }
         else {
-            attr(svgEl, 'stroke-dasharray', '');
+            attr(svgEl, 'stroke-dasharray', NONE);
         }
         style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap);
         style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin);
@@ -40130,7 +40134,7 @@ var ShadowManager = (function (_super) {
     ShadowManager.prototype.remove = function (svgElement, displayable) {
         if (displayable._shadowDom != null) {
             displayable._shadowDom = null;
-            svgElement.style.filter = '';
+            svgElement.removeAttribute('filter');
         }
     };
     ShadowManager.prototype.updateDom = function (svgElement, displayable, shadowDom) {
@@ -40160,7 +40164,7 @@ var ShadowManager = (function (_super) {
         shadowDom.setAttribute('height', '300%');
         displayable._shadowDom = shadowDom;
         var id = shadowDom.getAttribute('id');
-        svgElement.style.filter = 'url(#' + id + ')';
+        svgElement.setAttribute('filter', 'url(#' + id + ')');
     };
     ShadowManager.prototype.removeUnused = function () {
         var defs = this.getDefs(false);
@@ -40649,13 +40653,13 @@ var Layer = (function (_super) {
             var el = displayList[i];
             if (el) {
                 var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
-                var prevRect = el.__isRendered && ((el.__dirty & REDARAW_BIT) || !shouldPaint)
+                var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint)
                     ? el.getPrevPaintRect()
                     : null;
                 if (prevRect) {
                     addRectToMergePool(prevRect);
                 }
-                var curRect = shouldPaint && ((el.__dirty & REDARAW_BIT) || !el.__isRendered)
+                var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered)
                     ? el.getPaintRect()
                     : null;
                 if (curRect) {
@@ -41263,7 +41267,7 @@ var CanvasPainter = (function () {
                 updatePrevLayer(i);
                 prevLayer = layer;
             }
-            if ((el.__dirty & REDARAW_BIT) && !el.__inHover) {
+            if ((el.__dirty & REDRAW_BIT) && !el.__inHover) {
                 layer.__dirty = true;
                 if (layer.incremental && layer.__drawIndex < 0) {
                     layer.__drawIndex = i;
@@ -43000,8 +43004,60 @@ function turnPointsIntoStep(points, coordSys, stepTurnAt) {
   stepPoints.push(points[i++], points[i++]);
   return stepPoints;
 }
+/**
+ * Clip color stops to edge. Avoid creating too large gradients.
+ * Which may lead to blurry when GPU acceleration is enabled. See #15680
+ *
+ * The stops has been sorted from small to large.
+ */
+
+
+function clipColorStops(colorStops, maxSize) {
+  var newColorStops = [];
+  var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop.
+
+  var prevOutOfRangeColorStop;
+  var prevInRangeColorStop;
+
+  function lerpStop(stop0, stop1, clippedCoord) {
+    var coord0 = stop0.coord;
+    var p = (clippedCoord - coord0) / (stop1.coord - coord0);
+    var color = lerp$1(p, [stop0.color, stop1.color]);
+    return {
+      coord: clippedCoord,
+      color: color
+    };
+  }
+
+  for (var i = 0; i < len; i++) {
+    var stop_1 = colorStops[i];
+    var coord = stop_1.coord;
 
-function getVisualGradient(data, coordSys) {
+    if (coord < 0) {
+      prevOutOfRangeColorStop = stop_1;
+    } else if (coord > maxSize) {
+      if (prevInRangeColorStop) {
+        newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize));
+      } // All following stop will be out of range. So just ignore them.
+
+
+      break;
+    } else {
+      if (prevOutOfRangeColorStop) {
+        newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset
+
+        prevOutOfRangeColorStop = null;
+      }
+
+      newColorStops.push(stop_1);
+      prevInRangeColorStop = stop_1;
+    }
+  }
+
+  return newColorStops;
+}
+
+function getVisualGradient(data, coordSys, api) {
   var visualMetaList = data.getVisual('visualMeta');
 
   if (!visualMetaList || !visualMetaList.length || !data.count()) {
@@ -43044,16 +43100,12 @@ function getVisualGradient(data, coordSys) {
   // LinearGradient to render `outerColors`.
 
 
-  var axis = coordSys.getAxis(coordDim);
-  var axisScaleExtent = axis.scale.getExtent(); // dataToCoord mapping may not be linear, but must be monotonic.
+  var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic.
 
   var colorStops = map(visualMeta.stops, function (stop) {
-    var coord = axis.toGlobalCoord(axis.dataToCoord(stop.value)); // normalize the infinite value
-
-    isNaN(coord) || isFinite(coord) || (coord = axis.toGlobalCoord(axis.dataToCoord(axisScaleExtent[+(coord < 0)])));
+    // offset will be calculated later.
     return {
-      offset: 0,
-      coord: coord,
+      coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
       color: stop.color
     };
   });
@@ -43065,32 +43117,37 @@ function getVisualGradient(data, coordSys) {
     outerColors.reverse();
   }
 
-  var tinyExtent = 10; // Arbitrary value: 10px
+  var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight());
+  var inRangeStopLen = colorStopsInRange.length;
+
+  if (!inRangeStopLen && stopLen) {
+    // All stops are out of range. All will be the same color.
+    return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color;
+  }
+
+  var tinyExtent = 0; // Arbitrary value: 10px
 
-  var minCoord = colorStops[0].coord - tinyExtent;
-  var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
+  var minCoord = colorStopsInRange[0].coord - tinyExtent;
+  var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent;
   var coordSpan = maxCoord - minCoord;
 
   if (coordSpan < 1e-3) {
     return 'transparent';
   }
 
-  each(colorStops, function (stop) {
+  each(colorStopsInRange, function (stop) {
     stop.offset = (stop.coord - minCoord) / coordSpan;
   });
-  colorStops.push({
-    offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
+  colorStopsInRange.push({
+    // NOTE: inRangeStopLen may still be 0 if stoplen is zero.
+    offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5,
     color: outerColors[1] || 'transparent'
   });
-  colorStops.unshift({
-    offset: stopLen ? colorStops[0].offset : 0.5,
+  colorStopsInRange.unshift({
+    offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5,
     color: outerColors[0] || 'transparent'
-  }); // zrUtil.each(colorStops, function (colorStop) {
-  //     // Make sure each offset has rounded px to avoid not sharp edge
-  //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
-  // });
-
-  var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
+  });
+  var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true);
   gradient[coordDim] = minCoord;
   gradient[coordDim + '2'] = maxCoord;
   return gradient;
@@ -43365,7 +43422,7 @@ function (_super) {
     }
 
     this._clipShapeForSymbol = clipShapeForSymbol;
-    var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
+    var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
 
     if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
       showSymbol && symbolDraw.updateData(data, {
@@ -43415,9 +43472,19 @@ function (_super) {
       } // Update clipPath
 
 
-      lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
+      var oldClipPath = lineGroup.getClipPath();
+
+      if (oldClipPath) {
+        var newClipPath = createLineClipPath(this, coordSys, false, seriesModel);
+        initProps(oldClipPath, {
+          shape: newClipPath.shape
+        }, seriesModel);
+      } else {
+        lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
+      } // Always update, or it is wrong in the case turning on legend
       // because points are not changed
 
+
       showSymbol && symbolDraw.updateData(data, {
         isIgnore: isIgnoreFunc,
         clipShape: clipShapeForSymbol,
@@ -43888,11 +43955,13 @@ function (_super) {
 
 
     if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
+      polyline.stopAnimation();
       polyline.setShape({
         points: next
       });
 
       if (polygon) {
+        polygon.stopAnimation();
         polygon.setShape({
           points: next,
           stackedOnPoints: stackedOnNext
@@ -45164,16 +45233,9 @@ var elementCreator = {
     return rect;
   },
   polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
-    // Keep the same logic with bar in catesion: use end value to control
-    // direction. Notice that if clockwise is true (by default), the sector
-    // will always draw clockwisely, no matter whether endAngle is greater
-    // or less than startAngle.
-    var clockwise = layout.startAngle < layout.endAngle;
     var ShapeClass = !isRadial && roundCap ? SausagePath : Sector;
     var sector = new ShapeClass({
-      shape: defaults({
-        clockwise: clockwise
-      }, layout),
+      shape: layout,
       z2: 1
     });
     sector.name = 'item';
@@ -45304,7 +45366,8 @@ var getLayout = {
       r0: layout.r0,
       r: layout.r,
       startAngle: layout.startAngle,
-      endAngle: layout.endAngle
+      endAngle: layout.endAngle,
+      clockwise: layout.clockwise
     };
   }
 };
@@ -48630,7 +48693,21 @@ var builders = {
     var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
     var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
     fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
-    buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection);
+    buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart.
+    // See https://github.com/apache/echarts/issues/14266 for more.
+
+    if (axisModel.get(['axisLabel', 'hideOverlap'])) {
+      var labelList = prepareLayoutList(map(labelEls, function (label) {
+        return {
+          label: label,
+          priority: label.z2,
+          defaultAttr: {
+            ignore: label.ignore
+          }
+        };
+      }));
+      hideOverlap(labelList);
+    }
   },
   axisName: function (opt, axisModel, group, transformGroup) {
     var name = retrieve(opt.axisName, axisModel.get('name'));
@@ -48953,7 +49030,7 @@ function buildAxisLabel(group, transformGroup, axisModel, opt) {
       y: opt.labelOffset + opt.labelDirection * labelMargin,
       rotation: labelLayout.rotation,
       silent: silent,
-      z2: 10,
+      z2: 10 + (labelItem.level || 0),
       style: createTextStyle(itemLabelModel, {
         text: formattedLabel,
         align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
@@ -70320,7 +70397,7 @@ function (_super) {
       children: option.data
     };
     completeTreeValue$1(root);
-    var levelModels = map(option.levels || [], function (levelDefine) {
+    var levelModels = this._levelModels = map(option.levels || [], function (levelDefine) {
       return new Model(levelDefine, this, ecModel);
     }, this); // Make sure always a new tree is created when setOption,
     // in TreemapView, we check whether oldTree === newTree
@@ -70356,6 +70433,10 @@ function (_super) {
     return params;
   };
 
+  SunburstSeriesModel.prototype.getLevelModel = function (node) {
+    return this._levelModels && this._levelModels[node.depth];
+  };
+
   SunburstSeriesModel.prototype.getViewRoot = function () {
     return this._viewRoot;
   };
@@ -70551,17 +70632,20 @@ function sunburstLayout(seriesType, ecModel, api) {
         var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1);
         var rStart = r0 + rPerLevel * depth;
         var rEnd = r0 + rPerLevel * (depth + 1);
-        var itemModel = node.getModel(); // @ts-ignore. TODO this is not provided to developer yet. Rename it.
+        var levelModel = seriesModel.getLevelModel(node);
 
-        if (itemModel.get('r0') != null) {
-          // @ts-ignore
-          rStart = parsePercent$1(itemModel.get('r0'), size / 2);
-        } // @ts-ignore
+        if (levelModel) {
+          var r0_1 = levelModel.get('r0', true);
+          var r_1 = levelModel.get('r', true);
+          var radius_1 = levelModel.get('radius', true);
 
+          if (radius_1 != null) {
+            r0_1 = radius_1[0];
+            r_1 = radius_1[1];
+          }
 
-        if (itemModel.get('r') != null) {
-          // @ts-ignore
-          rEnd = parsePercent$1(itemModel.get('r'), size / 2);
+          r0_1 != null && (rStart = parsePercent$1(r0_1, size / 2));
+          r_1 != null && (rEnd = parsePercent$1(r_1, size / 2));
         }
 
         node.setLayout({
@@ -75247,7 +75331,15 @@ function barLayoutPolar(seriesType, ecModel, api) {
         // Consider that positive angle is anti-clockwise,
         // while positive radian of sector is clockwise
         startAngle: -startAngle * Math.PI / 180,
-        endAngle: -endAngle * Math.PI / 180
+        endAngle: -endAngle * Math.PI / 180,
+
+        /**
+         * Keep the same logic with bar in catesion: use end value to
+         * control direction. Notice that if clockwise is true (by
+         * default), the sector will always draw clockwisely, no matter
+         * whether endAngle is greater or less than startAngle.
+         */
+        clockwise: startAngle >= endAngle
       });
     }
   });
@@ -81183,7 +81275,15 @@ function (_super) {
 
     this._initGlobalListener();
 
-    this._keepShow();
+    this._keepShow(); // PENDING
+    // `mousemove` event will be triggered very frequently when the mouse moves fast,
+    // which causes that the updatePosition was also called very frequently.
+    // In Chrome with devtools open and Firefox, tooltip looks lagged and shaked around. See #14695.
+    // To avoid the frequent triggering,
+    // consider throttling it in 50ms. (the tested result may need to validate)
+
+
+    this._updatePosition = this._renderMode === 'html' ? throttle(bind$2(this._doUpdatePosition, this), 50) : this._doUpdatePosition;
   };
 
   TooltipView.prototype._initGlobalListener = function () {
@@ -81691,7 +81791,7 @@ function (_super) {
     }
   };
 
-  TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x
+  TooltipView.prototype._doUpdatePosition = function (tooltipModel, positionExpr, x, // Mouse x
   y, // Mouse y
   content, params, el) {
     var viewWidth = this._api.getWidth();
@@ -84570,13 +84670,14 @@ coordSys, item) {
   // Alwalys return true if there is no coordSys
   return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
 }
-function dimValueGetter(item, dimName, dataIndex, dimIndex) {
-  // x, y, radius, angle
-  if (dimIndex < 2) {
-    return item.coord && item.coord[dimIndex];
-  }
-
-  return item.value;
+function createMarkerDimValueGetter(inCoordSys, dims) {
+  return inCoordSys ? function (item, dimName, dataIndex, dimIndex) {
+    var rawVal = dimIndex < 2 // x, y, radius, angle
+    ? item.coord && item.coord[dimIndex] : item.value;
+    return parseDataValue(rawVal, dims[dimIndex]);
+  } : function (item, dimName, dataIndex, dimIndex) {
+    return parseDataValue(item.value, dims[dimIndex]);
+  };
 }
 function numCalculate(data, valueDataDim, type) {
   if (type === 'average') {
@@ -84813,9 +84914,8 @@ function createData(coordSys, seriesModel, mpModel) {
     dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys));
   }
 
-  mpData.initData(dataOpt, null, coordSys ? dimValueGetter : function (item) {
-    return item.value;
-  });
+  var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
+  mpData.initData(dataOpt, null, dimValueGetter);
   return mpData;
 }
 
@@ -85210,15 +85310,13 @@ function createList$1(coordSys, seriesModel, mlModel) {
     optData = filter(optData, curry(markLineFilter, coordSys));
   }
 
-  var dimValueGetter$1 = coordSys ? dimValueGetter : function (item) {
-    return item.value;
-  };
+  var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
   fromData.initData(map(optData, function (item) {
     return item[0];
-  }), null, dimValueGetter$1);
+  }), null, dimValueGetter);
   toData.initData(map(optData, function (item) {
     return item[1];
-  }), null, dimValueGetter$1);
+  }), null, dimValueGetter);
   lineData.initData(map(optData, function (item) {
     return item[2];
   }));
@@ -85545,12 +85643,12 @@ function (_super) {
 }(MarkerView);
 
 function createList$2(coordSys, seriesModel, maModel) {
-  var coordDimsInfos;
   var areaData;
+  var dataDims;
   var dims = ['x0', 'y0', 'x1', 'y1'];
 
   if (coordSys) {
-    coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
+    var coordDimsInfos_1 = map(coordSys && coordSys.dimensions, function (coordDim) {
       var data = seriesModel.getData();
       var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
 
@@ -85560,18 +85658,19 @@ function createList$2(coordSys, seriesModel, maModel) {
         ordinalMeta: null
       });
     });
-    areaData = new SeriesData(map(dims, function (dim, idx) {
+    dataDims = map(dims, function (dim, idx) {
       return {
         name: dim,
-        type: coordDimsInfos[idx % 2].type
+        type: coordDimsInfos_1[idx % 2].type
       };
-    }), maModel);
+    });
+    areaData = new SeriesData(dataDims, maModel);
   } else {
-    coordDimsInfos = [{
+    dataDims = [{
       name: 'value',
       type: 'float'
     }];
-    areaData = new SeriesData(coordDimsInfos, maModel);
+    areaData = new SeriesData(dataDims, maModel);
   }
 
   var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel));
@@ -85582,9 +85681,10 @@ function createList$2(coordSys, seriesModel, maModel) {
 
   var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
     // TODO should convert to ParsedValue?
-    return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
-  } : function (item) {
-    return item.value;
+    var rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
+    return parseDataValue(rawVal, dataDims[dimIndex]);
+  } : function (item, dimName, dataIndex, dimIndex) {
+    return parseDataValue(item.value, dataDims[dimIndex]);
   };
   areaData.initData(optData, null, dimValueGetter);
   areaData.hasItemOption = true;
@@ -85842,17 +85942,13 @@ function (_super) {
     itemWidth: 25,
     itemHeight: 14,
     symbolRotate: 'inherit',
+    symbolKeepAspect: true,
     inactiveColor: '#ccc',
     inactiveBorderColor: '#ccc',
     inactiveBorderWidth: 'auto',
     itemStyle: {
       color: 'inherit',
       opacity: 'inherit',
-      decal: 'inherit',
-      shadowBlur: 0,
-      shadowColor: null,
-      shadowOffsetX: 0,
-      shadowOffsetY: 0,
       borderColor: 'inherit',
       borderWidth: 'auto',
       borderCap: 'inherit',
@@ -85870,11 +85966,7 @@ function (_super) {
       cap: 'inherit',
       join: 'inherit',
       dashOffset: 'inherit',
-      miterLimit: 'inherit',
-      shadowBlur: 0,
-      shadowColor: null,
-      shadowOffsetX: 0,
-      shadowOffsetY: 0
+      miterLimit: 'inherit'
     },
     textStyle: {
       color: '#333'
@@ -85886,7 +85978,7 @@ function (_super) {
       borderRadius: 10,
       padding: [3, 5, 3, 5],
       fontSize: 12,
-      fontFamily: ' sans-serif',
+      fontFamily: 'sans-serif',
       color: '#666',
       borderWidth: 1,
       borderColor: '#666'
@@ -86132,10 +86224,10 @@ function (_super) {
     var itemHeight = legendModel.get('itemHeight');
     var isSelected = legendModel.isSelected(name);
     var iconRotate = legendItemModel.get('symbolRotate');
+    var symbolKeepAspect = legendItemModel.get('symbolKeepAspect');
     var legendIconType = legendItemModel.get('icon');
     legendIcon = legendIconType || legendIcon || 'roundRect';
-    var legendLineStyle = legendModel.getModel('lineStyle');
-    var style = getLegendStyle(legendIcon, legendItemModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected);
+    var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected);
     var itemGroup = new Group$2();
     var textStyleModel = legendItemModel.getModel('textStyle');
 
@@ -86147,7 +86239,8 @@ function (_super) {
         icon: legendIcon,
         iconRotate: iconRotate,
         itemStyle: style.itemStyle,
-        lineStyle: style.lineStyle
+        lineStyle: style.lineStyle,
+        symbolKeepAspect: symbolKeepAspect
       }));
     } else {
       // Use default legend icon policy for most series
@@ -86159,7 +86252,8 @@ function (_super) {
         icon: legendIcon,
         iconRotate: rotate,
         itemStyle: style.itemStyle,
-        lineStyle: style.lineStyle
+        lineStyle: style.lineStyle,
+        symbolKeepAspect: symbolKeepAspect
       }));
     }
 
@@ -86275,77 +86369,56 @@ function (_super) {
   return LegendView;
 }(ComponentView);
 
-function getLegendStyle(iconType, legendModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
+function getLegendStyle(iconType, legendModel, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
   /**
    * Use series style if is inherit;
    * elsewise, use legend style
    */
-  // itemStyle
+  function handleCommonProps(style, visualStyle) {
+    // If lineStyle.width is 'auto', it is set to be 2 if series has border
+    if (style.lineWidth === 'auto') {
+      style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0;
+    }
+
+    each$d(style, function (propVal, propName) {
+      style[propName] === 'inherit' && (style[propName] = visualStyle[propName]);
+    });
+  } // itemStyle
+
+
   var legendItemModel = legendModel.getModel('itemStyle');
-  var itemProperties = ITEM_STYLE_KEY_MAP.concat([['decal']]);
-  var itemStyle = {};
-
-  for (var i = 0; i < itemProperties.length; ++i) {
-    var propName = itemProperties[i][itemProperties[i].length - 1];
-    var visualName = itemProperties[i][0];
-    var value = legendItemModel.getShallow(propName);
-
-    if (value === 'inherit') {
-      switch (visualName) {
-        case 'fill':
-          /**
-           * Series with visualDrawType as 'stroke' should have
-           * series stroke as legend fill
-           */
-          itemStyle.fill = itemVisualStyle[drawType];
-          break;
+  var itemStyle = legendItemModel.getItemStyle();
+  var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke';
+  itemStyle.decal = itemVisualStyle.decal;
 
-        case 'stroke':
-          /**
-           * icon type with "emptyXXX" should use fill color
-           * in visual style
-           */
-          itemStyle.stroke = itemVisualStyle[iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'];
-          break;
+  if (itemStyle.fill === 'inherit') {
+    /**
+     * Series with visualDrawType as 'stroke' should have
+     * series stroke as legend fill
+     */
+    itemStyle.fill = itemVisualStyle[drawType];
+  }
 
-        case 'opacity':
-          /**
-           * Use lineStyle.opacity if drawType is stroke
-           */
-          itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
-          break;
+  if (itemStyle.stroke === 'inherit') {
+    /**
+     * icon type with "emptyXXX" should use fill color
+     * in visual style
+     */
+    itemStyle.stroke = itemVisualStyle[iconBrushType];
+  }
 
-        default:
-          itemStyle[visualName] = itemVisualStyle[visualName];
-      }
-    } else if (value === 'auto' && visualName === 'lineWidth') {
-      // If lineStyle.width is 'auto', it is set to be 2 if series has border
-      itemStyle.lineWidth = itemVisualStyle.lineWidth > 0 ? 2 : 0;
-    } else {
-      itemStyle[visualName] = value;
-    }
-  } // lineStyle
+  if (itemStyle.opacity === 'inherit') {
+    /**
+     * Use lineStyle.opacity if drawType is stroke
+     */
+    itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
+  }
 
+  handleCommonProps(itemStyle, itemVisualStyle); // lineStyle
 
   var legendLineModel = legendModel.getModel('lineStyle');
-  var lineProperties = LINE_STYLE_KEY_MAP.concat([['inactiveColor'], ['inactiveWidth']]);
-  var lineStyle = {};
-
-  for (var i = 0; i < lineProperties.length; ++i) {
-    var propName = lineProperties[i][1];
-    var visualName = lineProperties[i][0];
-    var value = legendLineModel.getShallow(propName);
-
-    if (value === 'inherit') {
-      lineStyle[visualName] = lineVisualStyle[visualName];
-    } else if (value === 'auto' && visualName === 'lineWidth') {
-      // If lineStyle.width is 'auto', it is set to be 2 if series has border
-      lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0;
-    } else {
-      lineStyle[visualName] = value;
-    }
-  } // Fix auto color to real color
-
+  var lineStyle = legendLineModel.getLineStyle();
+  handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color
 
   itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
   itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
@@ -86359,12 +86432,12 @@ function getLegendStyle(iconType, legendModel, legendLineStyle, lineVisualStyle,
      * use border only when series has border if is set to be auto
      */
 
-    var visualHasBorder = itemStyle[iconType.indexOf('empty') > -1 ? 'fill' : 'stroke'];
+    var visualHasBorder = itemStyle[iconBrushType];
     itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
     itemStyle.fill = legendModel.get('inactiveColor');
     itemStyle.stroke = legendModel.get('inactiveBorderColor');
-    lineStyle.stroke = legendLineStyle.get('inactiveColor');
-    lineStyle.lineWidth = legendLineStyle.get('inactiveWidth');
+    lineStyle.stroke = legendLineModel.get('inactiveColor');
+    lineStyle.lineWidth = legendLineModel.get('inactiveWidth');
   }
 
   return {
@@ -86375,7 +86448,7 @@ function getLegendStyle(iconType, legendModel, legendLineStyle, lineVisualStyle,
 
 function getDefaultLegendIcon(opt) {
   var symboType = opt.icon || 'roundRect';
-  var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill);
+  var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
   icon.setStyle(opt.itemStyle);
   icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
   icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
diff --git a/dist/echarts.esm.js.map b/dist/echarts.esm.js.map
index f997b06..c828ae2 100644
--- a/dist/echarts.esm.js.map
+++ b/dist/echarts.esm.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.esm.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/Ges [...]
\ No newline at end of file
+{"version":3,"file":"echarts.esm.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/Ges [...]
\ No newline at end of file
diff --git a/dist/echarts.esm.min.js b/dist/echarts.esm.min.js
index 6c35c2c..24b029d 100644
--- a/dist/echarts.esm.min.js
+++ b/dist/echarts.esm.min.js
@@ -32,7 +32,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 PERFORMANCE OF THIS SOFTWARE.
 ***************************************************************************** */
-var t=function(e,n){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return(n=Object.assign|| [...]
+var t=function(e,n){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return(n=Object.assign|| [...]
 /*!
 * ZRender, a high performance 2d drawing library.
 *
@@ -42,4 +42,4 @@ var t=function(e,n){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Arr
 * LICENSE
 * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
 */
-var Pi=!o.canvasSupported,Oi={},Ri={};var Ni=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new xe,a=n.renderer||"canvas";if(Pi)throw new Error("IE8 support has been dropped since 5.0");if(Oi[a]||(a=E(Oi)[0]),!Oi[a])throw new Error("Renderer '"+a+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
+var Pi=!o.canvasSupported,Oi={},Ri={};var Ni=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new xe,a=n.renderer||"canvas";if(Pi)throw new Error("IE8 support has been dropped since 5.0");if(Oi[a]||(a=E(Oi)[0]),!Oi[a])throw new Error("Renderer '"+a+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
diff --git a/dist/echarts.js b/dist/echarts.js
index e9c7174..2cfd82d 100644
--- a/dist/echarts.js
+++ b/dist/echarts.js
@@ -188,6 +188,7 @@
     var nativeMap = arrayProto.map;
     var ctorFunction = function () { }.constructor;
     var protoFunction = ctorFunction ? ctorFunction.prototype : null;
+    var protoKey = '__proto__';
     var methods = {};
     function $override(name, fn) {
         methods[name] = fn;
@@ -236,7 +237,7 @@
         else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
             result = {};
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     result[key] = clone(source[key]);
                 }
             }
@@ -248,7 +249,7 @@
             return overwrite ? clone(source) : target;
         }
         for (var key in source) {
-            if (source.hasOwnProperty(key)) {
+            if (source.hasOwnProperty(key) && key !== protoKey) {
                 var targetProp = target[key];
                 var sourceProp = source[key];
                 if (isObject(sourceProp)
@@ -283,7 +284,7 @@
         }
         else {
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     target[key] = source[key];
                 }
             }
@@ -1221,6 +1222,7 @@
             calculateZrXY(el, e, out);
         }
         else if (env.browser.firefox
+            && env.browser.version < '39'
             && e.layerX != null
             && e.layerX !== e.offsetX) {
             out.zrX = e.layerX;
@@ -2181,7 +2183,7 @@
         ts.forceMergeRuns();
     }
 
-    var REDARAW_BIT = 1;
+    var REDRAW_BIT = 1;
     var STYLE_CHANGED_BIT = 2;
     var SHAPE_CHANGED_BIT = 4;
 
@@ -2265,7 +2267,7 @@
                 for (var i = 0; i < children.length; i++) {
                     var child = children[i];
                     if (el.__dirty) {
-                        child.__dirty |= REDARAW_BIT;
+                        child.__dirty |= REDRAW_BIT;
                     }
                     this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
                 }
@@ -5326,7 +5328,7 @@
                     innerTextDefaultStyle.verticalAlign = textVerticalAlign;
                     textEl.setDefaultTextStyle(innerTextDefaultStyle);
                 }
-                textEl.__dirty |= REDARAW_BIT;
+                textEl.__dirty |= REDRAW_BIT;
                 if (textStyleChanged) {
                     textEl.dirtyStyle(true);
                 }
@@ -5503,7 +5505,7 @@
             this.markRedraw();
             if (!useHoverLayer && this.__inHover) {
                 this._toggleHoverLayerFlag(false);
-                this.__dirty &= ~REDARAW_BIT;
+                this.__dirty &= ~REDRAW_BIT;
             }
             return state;
         };
@@ -5562,7 +5564,7 @@
                 this.markRedraw();
                 if (!useHoverLayer && this.__inHover) {
                     this._toggleHoverLayerFlag(false);
-                    this.__dirty &= ~REDARAW_BIT;
+                    this.__dirty &= ~REDRAW_BIT;
                 }
             }
         };
@@ -5773,7 +5775,7 @@
             }
         };
         Element.prototype.markRedraw = function () {
-            this.__dirty |= REDARAW_BIT;
+            this.__dirty |= REDRAW_BIT;
             var zr = this.__zr;
             if (zr) {
                 if (this.__inHover) {
@@ -5922,7 +5924,7 @@
             elProto.dragging = false;
             elProto.ignoreClip = false;
             elProto.__inHover = false;
-            elProto.__dirty = REDARAW_BIT;
+            elProto.__dirty = REDRAW_BIT;
             var logs = {};
             function logDeprecatedError(key, xKey, yKey) {
                 if (!logs[key + xKey + yKey]) {
@@ -6593,7 +6595,7 @@
     function registerPainter(name, Ctor) {
         painterCtors[name] = Ctor;
     }
-    var version = '5.2.0';
+    var version = '5.2.1';
 
     var zrender = /*#__PURE__*/Object.freeze({
         __proto__: null,
@@ -9163,7 +9165,7 @@
             dispProto.incremental = false;
             dispProto._rect = null;
             dispProto.dirtyRectTolerance = 0;
-            dispProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT;
+            dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
         })();
         return Displayable;
     }(Element));
@@ -10944,7 +10946,7 @@
                 for (var i = 0; i < pathCopyParams.length; ++i) {
                     decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
                 }
-                decalEl.__dirty |= REDARAW_BIT;
+                decalEl.__dirty |= REDRAW_BIT;
             }
             else if (this._decalEl) {
                 this._decalEl = null;
@@ -11270,7 +11272,7 @@
             pathProto.segmentIgnoreThreshold = 0;
             pathProto.subPixelOptimize = false;
             pathProto.autoBatch = false;
-            pathProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
+            pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
         })();
         return Path;
     }(Displayable));
@@ -27159,7 +27161,7 @@
     function brush(ctx, el, scope, isLast) {
         var m = el.transform;
         if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
-            el.__dirty &= ~REDARAW_BIT;
+            el.__dirty &= ~REDRAW_BIT;
             el.__isRendered = false;
             return;
         }
@@ -28031,7 +28033,7 @@
                     inheritStyle(parentGroup, img);
                     parseAttributes(xmlNode, img, this._defsUsePending, false, false);
                     img.setStyle({
-                        image: xmlNode.getAttribute('xlink:href'),
+                        image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'),
                         x: +xmlNode.getAttribute('x'),
                         y: +xmlNode.getAttribute('y'),
                         width: +xmlNode.getAttribute('width'),
@@ -29431,9 +29433,9 @@
     var lifecycle = new Eventful();
 
     var hasWindow = typeof window !== 'undefined';
-    var version$1 = '5.2.0';
+    var version$1 = '5.2.1';
     var dependencies = {
-      zrender: '5.2.0'
+      zrender: '5.2.1'
     };
     var TEST_FRAME_REMAIN_TIME = 1;
     var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
@@ -36680,7 +36682,8 @@
     // `scale.setExtent` or `scale.unionExtentFromData`;
 
 
-    function niceScaleExtent(scale, model) {
+    function niceScaleExtent(scale, inModel) {
+      var model = inModel;
       var extentInfo = getScaleExtent(scale, model);
       var extent = extentInfo.extent;
       var splitNumber = model.get('splitNumber');
@@ -37245,6 +37248,7 @@
       return {
         labels: map(ticks, function (tick, idx) {
           return {
+            level: tick.level,
             formattedLabel: labelFormatter(tick, idx),
             rawLabel: axis.scale.getLabel(tick),
             tickValue: tick.value
@@ -39305,7 +39309,7 @@
     function bindStyle(svgEl, style, el) {
         var opacity = style.opacity == null ? 1 : style.opacity;
         if (el instanceof ZRImage) {
-            svgEl.style.opacity = opacity + '';
+            attr(svgEl, 'opacity', opacity + '');
             return;
         }
         if (pathHasFill(style)) {
@@ -39346,7 +39350,7 @@
                 attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + '');
             }
             else {
-                attr(svgEl, 'stroke-dasharray', '');
+                attr(svgEl, 'stroke-dasharray', NONE);
             }
             style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap);
             style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin);
@@ -40136,7 +40140,7 @@
         ShadowManager.prototype.remove = function (svgElement, displayable) {
             if (displayable._shadowDom != null) {
                 displayable._shadowDom = null;
-                svgElement.style.filter = '';
+                svgElement.removeAttribute('filter');
             }
         };
         ShadowManager.prototype.updateDom = function (svgElement, displayable, shadowDom) {
@@ -40166,7 +40170,7 @@
             shadowDom.setAttribute('height', '300%');
             displayable._shadowDom = shadowDom;
             var id = shadowDom.getAttribute('id');
-            svgElement.style.filter = 'url(#' + id + ')';
+            svgElement.setAttribute('filter', 'url(#' + id + ')');
         };
         ShadowManager.prototype.removeUnused = function () {
             var defs = this.getDefs(false);
@@ -40655,13 +40659,13 @@
                 var el = displayList[i];
                 if (el) {
                     var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
-                    var prevRect = el.__isRendered && ((el.__dirty & REDARAW_BIT) || !shouldPaint)
+                    var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint)
                         ? el.getPrevPaintRect()
                         : null;
                     if (prevRect) {
                         addRectToMergePool(prevRect);
                     }
-                    var curRect = shouldPaint && ((el.__dirty & REDARAW_BIT) || !el.__isRendered)
+                    var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered)
                         ? el.getPaintRect()
                         : null;
                     if (curRect) {
@@ -41269,7 +41273,7 @@
                     updatePrevLayer(i);
                     prevLayer = layer;
                 }
-                if ((el.__dirty & REDARAW_BIT) && !el.__inHover) {
+                if ((el.__dirty & REDRAW_BIT) && !el.__inHover) {
                     layer.__dirty = true;
                     if (layer.incremental && layer.__drawIndex < 0) {
                         layer.__drawIndex = i;
@@ -43006,8 +43010,60 @@
       stepPoints.push(points[i++], points[i++]);
       return stepPoints;
     }
+    /**
+     * Clip color stops to edge. Avoid creating too large gradients.
+     * Which may lead to blurry when GPU acceleration is enabled. See #15680
+     *
+     * The stops has been sorted from small to large.
+     */
+
+
+    function clipColorStops(colorStops, maxSize) {
+      var newColorStops = [];
+      var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop.
+
+      var prevOutOfRangeColorStop;
+      var prevInRangeColorStop;
+
+      function lerpStop(stop0, stop1, clippedCoord) {
+        var coord0 = stop0.coord;
+        var p = (clippedCoord - coord0) / (stop1.coord - coord0);
+        var color = lerp$1(p, [stop0.color, stop1.color]);
+        return {
+          coord: clippedCoord,
+          color: color
+        };
+      }
+
+      for (var i = 0; i < len; i++) {
+        var stop_1 = colorStops[i];
+        var coord = stop_1.coord;
 
-    function getVisualGradient(data, coordSys) {
+        if (coord < 0) {
+          prevOutOfRangeColorStop = stop_1;
+        } else if (coord > maxSize) {
+          if (prevInRangeColorStop) {
+            newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize));
+          } // All following stop will be out of range. So just ignore them.
+
+
+          break;
+        } else {
+          if (prevOutOfRangeColorStop) {
+            newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset
+
+            prevOutOfRangeColorStop = null;
+          }
+
+          newColorStops.push(stop_1);
+          prevInRangeColorStop = stop_1;
+        }
+      }
+
+      return newColorStops;
+    }
+
+    function getVisualGradient(data, coordSys, api) {
       var visualMetaList = data.getVisual('visualMeta');
 
       if (!visualMetaList || !visualMetaList.length || !data.count()) {
@@ -43050,16 +43106,12 @@
       // LinearGradient to render `outerColors`.
 
 
-      var axis = coordSys.getAxis(coordDim);
-      var axisScaleExtent = axis.scale.getExtent(); // dataToCoord mapping may not be linear, but must be monotonic.
+      var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic.
 
       var colorStops = map(visualMeta.stops, function (stop) {
-        var coord = axis.toGlobalCoord(axis.dataToCoord(stop.value)); // normalize the infinite value
-
-        isNaN(coord) || isFinite(coord) || (coord = axis.toGlobalCoord(axis.dataToCoord(axisScaleExtent[+(coord < 0)])));
+        // offset will be calculated later.
         return {
-          offset: 0,
-          coord: coord,
+          coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
           color: stop.color
         };
       });
@@ -43071,32 +43123,37 @@
         outerColors.reverse();
       }
 
-      var tinyExtent = 10; // Arbitrary value: 10px
+      var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight());
+      var inRangeStopLen = colorStopsInRange.length;
+
+      if (!inRangeStopLen && stopLen) {
+        // All stops are out of range. All will be the same color.
+        return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color;
+      }
+
+      var tinyExtent = 0; // Arbitrary value: 10px
 
-      var minCoord = colorStops[0].coord - tinyExtent;
-      var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
+      var minCoord = colorStopsInRange[0].coord - tinyExtent;
+      var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent;
       var coordSpan = maxCoord - minCoord;
 
       if (coordSpan < 1e-3) {
         return 'transparent';
       }
 
-      each(colorStops, function (stop) {
+      each(colorStopsInRange, function (stop) {
         stop.offset = (stop.coord - minCoord) / coordSpan;
       });
-      colorStops.push({
-        offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
+      colorStopsInRange.push({
+        // NOTE: inRangeStopLen may still be 0 if stoplen is zero.
+        offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5,
         color: outerColors[1] || 'transparent'
       });
-      colorStops.unshift({
-        offset: stopLen ? colorStops[0].offset : 0.5,
+      colorStopsInRange.unshift({
+        offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5,
         color: outerColors[0] || 'transparent'
-      }); // zrUtil.each(colorStops, function (colorStop) {
-      //     // Make sure each offset has rounded px to avoid not sharp edge
-      //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
-      // });
-
-      var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
+      });
+      var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true);
       gradient[coordDim] = minCoord;
       gradient[coordDim + '2'] = maxCoord;
       return gradient;
@@ -43371,7 +43428,7 @@
         }
 
         this._clipShapeForSymbol = clipShapeForSymbol;
-        var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
+        var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
 
         if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
           showSymbol && symbolDraw.updateData(data, {
@@ -43421,9 +43478,19 @@
           } // Update clipPath
 
 
-          lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
+          var oldClipPath = lineGroup.getClipPath();
+
+          if (oldClipPath) {
+            var newClipPath = createLineClipPath(this, coordSys, false, seriesModel);
+            initProps(oldClipPath, {
+              shape: newClipPath.shape
+            }, seriesModel);
+          } else {
+            lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
+          } // Always update, or it is wrong in the case turning on legend
           // because points are not changed
 
+
           showSymbol && symbolDraw.updateData(data, {
             isIgnore: isIgnoreFunc,
             clipShape: clipShapeForSymbol,
@@ -43894,11 +43961,13 @@
 
 
         if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
+          polyline.stopAnimation();
           polyline.setShape({
             points: next
           });
 
           if (polygon) {
+            polygon.stopAnimation();
             polygon.setShape({
               points: next,
               stackedOnPoints: stackedOnNext
@@ -45170,16 +45239,9 @@
         return rect;
       },
       polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
-        // Keep the same logic with bar in catesion: use end value to control
-        // direction. Notice that if clockwise is true (by default), the sector
-        // will always draw clockwisely, no matter whether endAngle is greater
-        // or less than startAngle.
-        var clockwise = layout.startAngle < layout.endAngle;
         var ShapeClass = !isRadial && roundCap ? SausagePath : Sector;
         var sector = new ShapeClass({
-          shape: defaults({
-            clockwise: clockwise
-          }, layout),
+          shape: layout,
           z2: 1
         });
         sector.name = 'item';
@@ -45310,7 +45372,8 @@
           r0: layout.r0,
           r: layout.r,
           startAngle: layout.startAngle,
-          endAngle: layout.endAngle
+          endAngle: layout.endAngle,
+          clockwise: layout.clockwise
         };
       }
     };
@@ -48636,7 +48699,21 @@
         var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
         var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
         fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
-        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection);
+        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart.
+        // See https://github.com/apache/echarts/issues/14266 for more.
+
+        if (axisModel.get(['axisLabel', 'hideOverlap'])) {
+          var labelList = prepareLayoutList(map(labelEls, function (label) {
+            return {
+              label: label,
+              priority: label.z2,
+              defaultAttr: {
+                ignore: label.ignore
+              }
+            };
+          }));
+          hideOverlap(labelList);
+        }
       },
       axisName: function (opt, axisModel, group, transformGroup) {
         var name = retrieve(opt.axisName, axisModel.get('name'));
@@ -48959,7 +49036,7 @@
           y: opt.labelOffset + opt.labelDirection * labelMargin,
           rotation: labelLayout.rotation,
           silent: silent,
-          z2: 10,
+          z2: 10 + (labelItem.level || 0),
           style: createTextStyle(itemLabelModel, {
             text: formattedLabel,
             align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
@@ -70326,7 +70403,7 @@
           children: option.data
         };
         completeTreeValue$1(root);
-        var levelModels = map(option.levels || [], function (levelDefine) {
+        var levelModels = this._levelModels = map(option.levels || [], function (levelDefine) {
           return new Model(levelDefine, this, ecModel);
         }, this); // Make sure always a new tree is created when setOption,
         // in TreemapView, we check whether oldTree === newTree
@@ -70362,6 +70439,10 @@
         return params;
       };
 
+      SunburstSeriesModel.prototype.getLevelModel = function (node) {
+        return this._levelModels && this._levelModels[node.depth];
+      };
+
       SunburstSeriesModel.prototype.getViewRoot = function () {
         return this._viewRoot;
       };
@@ -70557,17 +70638,20 @@
             var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1);
             var rStart = r0 + rPerLevel * depth;
             var rEnd = r0 + rPerLevel * (depth + 1);
-            var itemModel = node.getModel(); // @ts-ignore. TODO this is not provided to developer yet. Rename it.
+            var levelModel = seriesModel.getLevelModel(node);
 
-            if (itemModel.get('r0') != null) {
-              // @ts-ignore
-              rStart = parsePercent$1(itemModel.get('r0'), size / 2);
-            } // @ts-ignore
+            if (levelModel) {
+              var r0_1 = levelModel.get('r0', true);
+              var r_1 = levelModel.get('r', true);
+              var radius_1 = levelModel.get('radius', true);
 
+              if (radius_1 != null) {
+                r0_1 = radius_1[0];
+                r_1 = radius_1[1];
+              }
 
-            if (itemModel.get('r') != null) {
-              // @ts-ignore
-              rEnd = parsePercent$1(itemModel.get('r'), size / 2);
+              r0_1 != null && (rStart = parsePercent$1(r0_1, size / 2));
+              r_1 != null && (rEnd = parsePercent$1(r_1, size / 2));
             }
 
             node.setLayout({
@@ -75253,7 +75337,15 @@
             // Consider that positive angle is anti-clockwise,
             // while positive radian of sector is clockwise
             startAngle: -startAngle * Math.PI / 180,
-            endAngle: -endAngle * Math.PI / 180
+            endAngle: -endAngle * Math.PI / 180,
+
+            /**
+             * Keep the same logic with bar in catesion: use end value to
+             * control direction. Notice that if clockwise is true (by
+             * default), the sector will always draw clockwisely, no matter
+             * whether endAngle is greater or less than startAngle.
+             */
+            clockwise: startAngle >= endAngle
           });
         }
       });
@@ -81189,7 +81281,15 @@
 
         this._initGlobalListener();
 
-        this._keepShow();
+        this._keepShow(); // PENDING
+        // `mousemove` event will be triggered very frequently when the mouse moves fast,
+        // which causes that the updatePosition was also called very frequently.
+        // In Chrome with devtools open and Firefox, tooltip looks lagged and shaked around. See #14695.
+        // To avoid the frequent triggering,
+        // consider throttling it in 50ms. (the tested result may need to validate)
+
+
+        this._updatePosition = this._renderMode === 'html' ? throttle(bind$2(this._doUpdatePosition, this), 50) : this._doUpdatePosition;
       };
 
       TooltipView.prototype._initGlobalListener = function () {
@@ -81697,7 +81797,7 @@
         }
       };
 
-      TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x
+      TooltipView.prototype._doUpdatePosition = function (tooltipModel, positionExpr, x, // Mouse x
       y, // Mouse y
       content, params, el) {
         var viewWidth = this._api.getWidth();
@@ -84576,13 +84676,14 @@
       // Alwalys return true if there is no coordSys
       return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
     }
-    function dimValueGetter(item, dimName, dataIndex, dimIndex) {
-      // x, y, radius, angle
-      if (dimIndex < 2) {
-        return item.coord && item.coord[dimIndex];
-      }
-
-      return item.value;
+    function createMarkerDimValueGetter(inCoordSys, dims) {
+      return inCoordSys ? function (item, dimName, dataIndex, dimIndex) {
+        var rawVal = dimIndex < 2 // x, y, radius, angle
+        ? item.coord && item.coord[dimIndex] : item.value;
+        return parseDataValue(rawVal, dims[dimIndex]);
+      } : function (item, dimName, dataIndex, dimIndex) {
+        return parseDataValue(item.value, dims[dimIndex]);
+      };
     }
     function numCalculate(data, valueDataDim, type) {
       if (type === 'average') {
@@ -84819,9 +84920,8 @@
         dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys));
       }
 
-      mpData.initData(dataOpt, null, coordSys ? dimValueGetter : function (item) {
-        return item.value;
-      });
+      var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
+      mpData.initData(dataOpt, null, dimValueGetter);
       return mpData;
     }
 
@@ -85216,15 +85316,13 @@
         optData = filter(optData, curry(markLineFilter, coordSys));
       }
 
-      var dimValueGetter$1 = coordSys ? dimValueGetter : function (item) {
-        return item.value;
-      };
+      var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
       fromData.initData(map(optData, function (item) {
         return item[0];
-      }), null, dimValueGetter$1);
+      }), null, dimValueGetter);
       toData.initData(map(optData, function (item) {
         return item[1];
-      }), null, dimValueGetter$1);
+      }), null, dimValueGetter);
       lineData.initData(map(optData, function (item) {
         return item[2];
       }));
@@ -85551,12 +85649,12 @@
     }(MarkerView);
 
     function createList$2(coordSys, seriesModel, maModel) {
-      var coordDimsInfos;
       var areaData;
+      var dataDims;
       var dims = ['x0', 'y0', 'x1', 'y1'];
 
       if (coordSys) {
-        coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
+        var coordDimsInfos_1 = map(coordSys && coordSys.dimensions, function (coordDim) {
           var data = seriesModel.getData();
           var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
 
@@ -85566,18 +85664,19 @@
             ordinalMeta: null
           });
         });
-        areaData = new SeriesData(map(dims, function (dim, idx) {
+        dataDims = map(dims, function (dim, idx) {
           return {
             name: dim,
-            type: coordDimsInfos[idx % 2].type
+            type: coordDimsInfos_1[idx % 2].type
           };
-        }), maModel);
+        });
+        areaData = new SeriesData(dataDims, maModel);
       } else {
-        coordDimsInfos = [{
+        dataDims = [{
           name: 'value',
           type: 'float'
         }];
-        areaData = new SeriesData(coordDimsInfos, maModel);
+        areaData = new SeriesData(dataDims, maModel);
       }
 
       var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel));
@@ -85588,9 +85687,10 @@
 
       var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
         // TODO should convert to ParsedValue?
-        return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
-      } : function (item) {
-        return item.value;
+        var rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
+        return parseDataValue(rawVal, dataDims[dimIndex]);
+      } : function (item, dimName, dataIndex, dimIndex) {
+        return parseDataValue(item.value, dataDims[dimIndex]);
       };
       areaData.initData(optData, null, dimValueGetter);
       areaData.hasItemOption = true;
@@ -85848,17 +85948,13 @@
         itemWidth: 25,
         itemHeight: 14,
         symbolRotate: 'inherit',
+        symbolKeepAspect: true,
         inactiveColor: '#ccc',
         inactiveBorderColor: '#ccc',
         inactiveBorderWidth: 'auto',
         itemStyle: {
           color: 'inherit',
           opacity: 'inherit',
-          decal: 'inherit',
-          shadowBlur: 0,
-          shadowColor: null,
-          shadowOffsetX: 0,
-          shadowOffsetY: 0,
           borderColor: 'inherit',
           borderWidth: 'auto',
           borderCap: 'inherit',
@@ -85876,11 +85972,7 @@
           cap: 'inherit',
           join: 'inherit',
           dashOffset: 'inherit',
-          miterLimit: 'inherit',
-          shadowBlur: 0,
-          shadowColor: null,
-          shadowOffsetX: 0,
-          shadowOffsetY: 0
+          miterLimit: 'inherit'
         },
         textStyle: {
           color: '#333'
@@ -85892,7 +85984,7 @@
           borderRadius: 10,
           padding: [3, 5, 3, 5],
           fontSize: 12,
-          fontFamily: ' sans-serif',
+          fontFamily: 'sans-serif',
           color: '#666',
           borderWidth: 1,
           borderColor: '#666'
@@ -86138,10 +86230,10 @@
         var itemHeight = legendModel.get('itemHeight');
         var isSelected = legendModel.isSelected(name);
         var iconRotate = legendItemModel.get('symbolRotate');
+        var symbolKeepAspect = legendItemModel.get('symbolKeepAspect');
         var legendIconType = legendItemModel.get('icon');
         legendIcon = legendIconType || legendIcon || 'roundRect';
-        var legendLineStyle = legendModel.getModel('lineStyle');
-        var style = getLegendStyle(legendIcon, legendItemModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected);
+        var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected);
         var itemGroup = new Group$2();
         var textStyleModel = legendItemModel.getModel('textStyle');
 
@@ -86153,7 +86245,8 @@
             icon: legendIcon,
             iconRotate: iconRotate,
             itemStyle: style.itemStyle,
-            lineStyle: style.lineStyle
+            lineStyle: style.lineStyle,
+            symbolKeepAspect: symbolKeepAspect
           }));
         } else {
           // Use default legend icon policy for most series
@@ -86165,7 +86258,8 @@
             icon: legendIcon,
             iconRotate: rotate,
             itemStyle: style.itemStyle,
-            lineStyle: style.lineStyle
+            lineStyle: style.lineStyle,
+            symbolKeepAspect: symbolKeepAspect
           }));
         }
 
@@ -86281,77 +86375,56 @@
       return LegendView;
     }(ComponentView);
 
-    function getLegendStyle(iconType, legendModel, legendLineStyle, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
+    function getLegendStyle(iconType, legendModel, lineVisualStyle, itemVisualStyle, drawType, isSelected) {
       /**
        * Use series style if is inherit;
        * elsewise, use legend style
        */
-      // itemStyle
+      function handleCommonProps(style, visualStyle) {
+        // If lineStyle.width is 'auto', it is set to be 2 if series has border
+        if (style.lineWidth === 'auto') {
+          style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0;
+        }
+
+        each$d(style, function (propVal, propName) {
+          style[propName] === 'inherit' && (style[propName] = visualStyle[propName]);
+        });
+      } // itemStyle
+
+
       var legendItemModel = legendModel.getModel('itemStyle');
-      var itemProperties = ITEM_STYLE_KEY_MAP.concat([['decal']]);
-      var itemStyle = {};
-
-      for (var i = 0; i < itemProperties.length; ++i) {
-        var propName = itemProperties[i][itemProperties[i].length - 1];
-        var visualName = itemProperties[i][0];
-        var value = legendItemModel.getShallow(propName);
-
-        if (value === 'inherit') {
-          switch (visualName) {
-            case 'fill':
-              /**
-               * Series with visualDrawType as 'stroke' should have
-               * series stroke as legend fill
-               */
-              itemStyle.fill = itemVisualStyle[drawType];
-              break;
+      var itemStyle = legendItemModel.getItemStyle();
+      var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke';
+      itemStyle.decal = itemVisualStyle.decal;
 
-            case 'stroke':
-              /**
-               * icon type with "emptyXXX" should use fill color
-               * in visual style
-               */
-              itemStyle.stroke = itemVisualStyle[iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'];
-              break;
+      if (itemStyle.fill === 'inherit') {
+        /**
+         * Series with visualDrawType as 'stroke' should have
+         * series stroke as legend fill
+         */
+        itemStyle.fill = itemVisualStyle[drawType];
+      }
 
-            case 'opacity':
-              /**
-               * Use lineStyle.opacity if drawType is stroke
-               */
-              itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
-              break;
+      if (itemStyle.stroke === 'inherit') {
+        /**
+         * icon type with "emptyXXX" should use fill color
+         * in visual style
+         */
+        itemStyle.stroke = itemVisualStyle[iconBrushType];
+      }
 
-            default:
-              itemStyle[visualName] = itemVisualStyle[visualName];
-          }
-        } else if (value === 'auto' && visualName === 'lineWidth') {
-          // If lineStyle.width is 'auto', it is set to be 2 if series has border
-          itemStyle.lineWidth = itemVisualStyle.lineWidth > 0 ? 2 : 0;
-        } else {
-          itemStyle[visualName] = value;
-        }
-      } // lineStyle
+      if (itemStyle.opacity === 'inherit') {
+        /**
+         * Use lineStyle.opacity if drawType is stroke
+         */
+        itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
+      }
 
+      handleCommonProps(itemStyle, itemVisualStyle); // lineStyle
 
       var legendLineModel = legendModel.getModel('lineStyle');
-      var lineProperties = LINE_STYLE_KEY_MAP.concat([['inactiveColor'], ['inactiveWidth']]);
-      var lineStyle = {};
-
-      for (var i = 0; i < lineProperties.length; ++i) {
-        var propName = lineProperties[i][1];
-        var visualName = lineProperties[i][0];
-        var value = legendLineModel.getShallow(propName);
-
-        if (value === 'inherit') {
-          lineStyle[visualName] = lineVisualStyle[visualName];
-        } else if (value === 'auto' && visualName === 'lineWidth') {
-          // If lineStyle.width is 'auto', it is set to be 2 if series has border
-          lineStyle.lineWidth = lineVisualStyle.lineWidth > 0 ? 2 : 0;
-        } else {
-          lineStyle[visualName] = value;
-        }
-      } // Fix auto color to real color
-
+      var lineStyle = legendLineModel.getLineStyle();
+      handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color
 
       itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
       itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
@@ -86365,12 +86438,12 @@
          * use border only when series has border if is set to be auto
          */
 
-        var visualHasBorder = itemStyle[iconType.indexOf('empty') > -1 ? 'fill' : 'stroke'];
+        var visualHasBorder = itemStyle[iconBrushType];
         itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
         itemStyle.fill = legendModel.get('inactiveColor');
         itemStyle.stroke = legendModel.get('inactiveBorderColor');
-        lineStyle.stroke = legendLineStyle.get('inactiveColor');
-        lineStyle.lineWidth = legendLineStyle.get('inactiveWidth');
+        lineStyle.stroke = legendLineModel.get('inactiveColor');
+        lineStyle.lineWidth = legendLineModel.get('inactiveWidth');
       }
 
       return {
@@ -86381,7 +86454,7 @@
 
     function getDefaultLegendIcon(opt) {
       var symboType = opt.icon || 'roundRect';
-      var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill);
+      var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
       icon.setStyle(opt.itemStyle);
       icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
       icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
diff --git a/dist/echarts.js.map b/dist/echarts.js.map
index 505e04a..9632e0a 100644
--- a/dist/echarts.js.map
+++ b/dist/echarts.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/Gesture [...]
\ No newline at end of file
+{"version":3,"file":"echarts.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/Gesture [...]
\ No newline at end of file
diff --git a/dist/echarts.min.js b/dist/echarts.min.js
index b886fde..26a073f 100644
--- a/dist/echarts.min.js
+++ b/dist/echarts.min.js
@@ -32,7 +32,7 @@
     LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     PERFORMANCE OF THIS SOFTWARE.
-    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
+    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
 /*!
     * ZRender, a high performance 2d drawing library.
     *
@@ -42,4 +42,4 @@
     * LICENSE
     * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
     */
-var Vi=!a.canvasSupported,Gi={},Fi={};var Hi=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new Se,o=n.renderer||"canvas";if(Vi)throw new Error("IE8 support has been dropped since 5.0");if(Gi[o]||(o=E(Gi)[0]),!Gi[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
+var Gi=!a.canvasSupported,Fi={},Hi={};var Wi=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new Me,o=n.renderer||"canvas";if(Gi)throw new Error("IE8 support has been dropped since 5.0");if(Fi[o]||(o=V(Fi)[0]),!Fi[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
diff --git a/dist/echarts.simple.js b/dist/echarts.simple.js
index aee5cd3..fa3b124 100644
--- a/dist/echarts.simple.js
+++ b/dist/echarts.simple.js
@@ -188,6 +188,7 @@
     var nativeMap = arrayProto.map;
     var ctorFunction = function () { }.constructor;
     var protoFunction = ctorFunction ? ctorFunction.prototype : null;
+    var protoKey = '__proto__';
     var methods = {};
     function $override(name, fn) {
         methods[name] = fn;
@@ -236,7 +237,7 @@
         else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
             result = {};
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     result[key] = clone(source[key]);
                 }
             }
@@ -248,7 +249,7 @@
             return overwrite ? clone(source) : target;
         }
         for (var key in source) {
-            if (source.hasOwnProperty(key)) {
+            if (source.hasOwnProperty(key) && key !== protoKey) {
                 var targetProp = target[key];
                 var sourceProp = source[key];
                 if (isObject(sourceProp)
@@ -283,7 +284,7 @@
         }
         else {
             for (var key in source) {
-                if (source.hasOwnProperty(key)) {
+                if (source.hasOwnProperty(key) && key !== protoKey) {
                     target[key] = source[key];
                 }
             }
@@ -1216,6 +1217,7 @@
             calculateZrXY(el, e, out);
         }
         else if (env.browser.firefox
+            && env.browser.version < '39'
             && e.layerX != null
             && e.layerX !== e.offsetX) {
             out.zrX = e.layerX;
@@ -2173,7 +2175,7 @@
         ts.forceMergeRuns();
     }
 
-    var REDARAW_BIT = 1;
+    var REDRAW_BIT = 1;
     var STYLE_CHANGED_BIT = 2;
     var SHAPE_CHANGED_BIT = 4;
 
@@ -2257,7 +2259,7 @@
                 for (var i = 0; i < children.length; i++) {
                     var child = children[i];
                     if (el.__dirty) {
-                        child.__dirty |= REDARAW_BIT;
+                        child.__dirty |= REDRAW_BIT;
                     }
                     this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
                 }
@@ -5318,7 +5320,7 @@
                     innerTextDefaultStyle.verticalAlign = textVerticalAlign;
                     textEl.setDefaultTextStyle(innerTextDefaultStyle);
                 }
-                textEl.__dirty |= REDARAW_BIT;
+                textEl.__dirty |= REDRAW_BIT;
                 if (textStyleChanged) {
                     textEl.dirtyStyle(true);
                 }
@@ -5495,7 +5497,7 @@
             this.markRedraw();
             if (!useHoverLayer && this.__inHover) {
                 this._toggleHoverLayerFlag(false);
-                this.__dirty &= ~REDARAW_BIT;
+                this.__dirty &= ~REDRAW_BIT;
             }
             return state;
         };
@@ -5554,7 +5556,7 @@
                 this.markRedraw();
                 if (!useHoverLayer && this.__inHover) {
                     this._toggleHoverLayerFlag(false);
-                    this.__dirty &= ~REDARAW_BIT;
+                    this.__dirty &= ~REDRAW_BIT;
                 }
             }
         };
@@ -5765,7 +5767,7 @@
             }
         };
         Element.prototype.markRedraw = function () {
-            this.__dirty |= REDARAW_BIT;
+            this.__dirty |= REDRAW_BIT;
             var zr = this.__zr;
             if (zr) {
                 if (this.__inHover) {
@@ -5914,7 +5916,7 @@
             elProto.dragging = false;
             elProto.ignoreClip = false;
             elProto.__inHover = false;
-            elProto.__dirty = REDARAW_BIT;
+            elProto.__dirty = REDRAW_BIT;
             var logs = {};
             function logDeprecatedError(key, xKey, yKey) {
                 if (!logs[key + xKey + yKey]) {
@@ -6585,7 +6587,7 @@
     function registerPainter(name, Ctor) {
         painterCtors[name] = Ctor;
     }
-    var version = '5.2.0';
+    var version = '5.2.1';
 
     var zrender = /*#__PURE__*/Object.freeze({
         __proto__: null,
@@ -9062,7 +9064,7 @@
             dispProto.incremental = false;
             dispProto._rect = null;
             dispProto.dirtyRectTolerance = 0;
-            dispProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT;
+            dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
         })();
         return Displayable;
     }(Element));
@@ -10843,7 +10845,7 @@
                 for (var i = 0; i < pathCopyParams.length; ++i) {
                     decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
                 }
-                decalEl.__dirty |= REDARAW_BIT;
+                decalEl.__dirty |= REDRAW_BIT;
             }
             else if (this._decalEl) {
                 this._decalEl = null;
@@ -11169,7 +11171,7 @@
             pathProto.segmentIgnoreThreshold = 0;
             pathProto.subPixelOptimize = false;
             pathProto.autoBatch = false;
-            pathProto.__dirty = REDARAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
+            pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
         })();
         return Path;
     }(Displayable));
@@ -13925,6 +13927,125 @@
         return RadialGradient;
     }(Gradient));
 
+    var extent = [0, 0];
+    var extent2 = [0, 0];
+    var minTv$1 = new Point();
+    var maxTv$1 = new Point();
+    var OrientedBoundingRect = (function () {
+        function OrientedBoundingRect(rect, transform) {
+            this._corners = [];
+            this._axes = [];
+            this._origin = [0, 0];
+            for (var i = 0; i < 4; i++) {
+                this._corners[i] = new Point();
+            }
+            for (var i = 0; i < 2; i++) {
+                this._axes[i] = new Point();
+            }
+            if (rect) {
+                this.fromBoundingRect(rect, transform);
+            }
+        }
+        OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) {
+            var corners = this._corners;
+            var axes = this._axes;
+            var x = rect.x;
+            var y = rect.y;
+            var x2 = x + rect.width;
+            var y2 = y + rect.height;
+            corners[0].set(x, y);
+            corners[1].set(x2, y);
+            corners[2].set(x2, y2);
+            corners[3].set(x, y2);
+            if (transform) {
+                for (var i = 0; i < 4; i++) {
+                    corners[i].transform(transform);
+                }
+            }
+            Point.sub(axes[0], corners[1], corners[0]);
+            Point.sub(axes[1], corners[3], corners[0]);
+            axes[0].normalize();
+            axes[1].normalize();
+            for (var i = 0; i < 2; i++) {
+                this._origin[i] = axes[i].dot(corners[0]);
+            }
+        };
+        OrientedBoundingRect.prototype.intersect = function (other, mtv) {
+            var overlapped = true;
+            var noMtv = !mtv;
+            minTv$1.set(Infinity, Infinity);
+            maxTv$1.set(0, 0);
+            if (!this._intersectCheckOneSide(this, other, minTv$1, maxTv$1, noMtv, 1)) {
+                overlapped = false;
+                if (noMtv) {
+                    return overlapped;
+                }
+            }
+            if (!this._intersectCheckOneSide(other, this, minTv$1, maxTv$1, noMtv, -1)) {
+                overlapped = false;
+                if (noMtv) {
+                    return overlapped;
+                }
+            }
+            if (!noMtv) {
+                Point.copy(mtv, overlapped ? minTv$1 : maxTv$1);
+            }
+            return overlapped;
+        };
+        OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) {
+            var overlapped = true;
+            for (var i = 0; i < 2; i++) {
+                var axis = this._axes[i];
+                this._getProjMinMaxOnAxis(i, self._corners, extent);
+                this._getProjMinMaxOnAxis(i, other._corners, extent2);
+                if (extent[1] < extent2[0] || extent[0] > extent2[1]) {
+                    overlapped = false;
+                    if (noMtv) {
+                        return overlapped;
+                    }
+                    var dist0 = Math.abs(extent2[0] - extent[1]);
+                    var dist1 = Math.abs(extent[0] - extent2[1]);
+                    if (Math.min(dist0, dist1) > maxTv.len()) {
+                        if (dist0 < dist1) {
+                            Point.scale(maxTv, axis, -dist0 * inverse);
+                        }
+                        else {
+                            Point.scale(maxTv, axis, dist1 * inverse);
+                        }
+                    }
+                }
+                else if (minTv) {
+                    var dist0 = Math.abs(extent2[0] - extent[1]);
+                    var dist1 = Math.abs(extent[0] - extent2[1]);
+                    if (Math.min(dist0, dist1) < minTv.len()) {
+                        if (dist0 < dist1) {
+                            Point.scale(minTv, axis, dist0 * inverse);
+                        }
+                        else {
+                            Point.scale(minTv, axis, -dist1 * inverse);
+                        }
+                    }
+                }
+            }
+            return overlapped;
+        };
+        OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) {
+            var axis = this._axes[dim];
+            var origin = this._origin;
+            var proj = corners[0].dot(axis) + origin[dim];
+            var min = proj;
+            var max = proj;
+            for (var i = 1; i < corners.length; i++) {
+                var proj_1 = corners[i].dot(axis) + origin[dim];
+                min = Math.min(proj_1, min);
+                max = Math.max(proj_1, max);
+            }
+            out[0] = min;
+            out[1] = max;
+        };
+        return OrientedBoundingRect;
+    }());
+
     var m = [];
     var IncrementalDisplayable = (function (_super) {
         __extends(IncrementalDisplayable, _super);
@@ -25822,7 +25943,7 @@
     function brush(ctx, el, scope, isLast) {
         var m = el.transform;
         if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
-            el.__dirty &= ~REDARAW_BIT;
+            el.__dirty &= ~REDRAW_BIT;
             el.__isRendered = false;
             return;
         }
@@ -26694,7 +26815,7 @@
                     inheritStyle(parentGroup, img);
                     parseAttributes(xmlNode, img, this._defsUsePending, false, false);
                     img.setStyle({
-                        image: xmlNode.getAttribute('xlink:href'),
+                        image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'),
                         x: +xmlNode.getAttribute('x'),
                         y: +xmlNode.getAttribute('y'),
                         width: +xmlNode.getAttribute('width'),
@@ -28094,9 +28215,9 @@
     var lifecycle = new Eventful();
 
     var hasWindow = typeof window !== 'undefined';
-    var version$1 = '5.2.0';
+    var version$1 = '5.2.1';
     var dependencies = {
-      zrender: '5.2.0'
+      zrender: '5.2.1'
     };
     var TEST_FRAME_REMAIN_TIME = 1;
     var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
@@ -35308,7 +35429,8 @@
     // `scale.setExtent` or `scale.unionExtentFromData`;
 
 
-    function niceScaleExtent(scale, model) {
+    function niceScaleExtent(scale, inModel) {
+      var model = inModel;
       var extentInfo = getScaleExtent(scale, model);
       var extent = extentInfo.extent;
       var splitNumber = model.get('splitNumber');
@@ -35864,6 +35986,7 @@
       return {
         labels: map(ticks, function (tick, idx) {
           return {
+            level: tick.level,
             formattedLabel: labelFormatter(tick, idx),
             rawLabel: axis.scale.getLabel(tick),
             tickValue: tick.value
@@ -36663,6 +36786,46 @@
       return statesModels;
     }
 
+    function prepareLayoutList(input) {
+      var list = [];
+
+      for (var i = 0; i < input.length; i++) {
+        var rawItem = input[i];
+
+        if (rawItem.defaultAttr.ignore) {
+          continue;
+        }
+
+        var label = rawItem.label;
+        var transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el.
+
+        var localRect = label.getBoundingRect();
+        var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5;
+        var minMargin = label.style.margin || 0;
+        var globalRect = localRect.clone();
+        globalRect.applyTransform(transform);
+        globalRect.x -= minMargin / 2;
+        globalRect.y -= minMargin / 2;
+        globalRect.width += minMargin;
+        globalRect.height += minMargin;
+        var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
+        list.push({
+          label: label,
+          labelLine: rawItem.labelLine,
+          rect: globalRect,
+          localRect: localRect,
+          obb: obb,
+          priority: rawItem.priority,
+          defaultAttr: rawItem.defaultAttr,
+          layoutOption: rawItem.computedLayoutOption,
+          axisAligned: isAxisAligned,
+          transform: transform
+        });
+      }
+
+      return list;
+    }
+
     function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) {
       var len = list.length;
 
@@ -36831,6 +36994,83 @@
     balanceShift) {
       return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift);
     }
+    function hideOverlap(labelList) {
+      var displayedLabels = []; // TODO, render overflow visible first, put in the displayedLabels.
+
+      labelList.sort(function (a, b) {
+        return b.priority - a.priority;
+      });
+      var globalRect = new BoundingRect(0, 0, 0, 0);
+
+      function hideEl(el) {
+        if (!el.ignore) {
+          // Show on emphasis.
+          var emphasisState = el.ensureState('emphasis');
+
+          if (emphasisState.ignore == null) {
+            emphasisState.ignore = false;
+          }
+        }
+
+        el.ignore = true;
+      }
+
+      for (var i = 0; i < labelList.length; i++) {
+        var labelItem = labelList[i];
+        var isAxisAligned = labelItem.axisAligned;
+        var localRect = labelItem.localRect;
+        var transform = labelItem.transform;
+        var label = labelItem.label;
+        var labelLine = labelItem.labelLine;
+        globalRect.copy(labelItem.rect); // Add a threshold because layout may be aligned precisely.
+
+        globalRect.width -= 0.1;
+        globalRect.height -= 0.1;
+        globalRect.x += 0.05;
+        globalRect.y += 0.05;
+        var obb = labelItem.obb;
+        var overlapped = false;
+
+        for (var j = 0; j < displayedLabels.length; j++) {
+          var existsTextCfg = displayedLabels[j]; // Fast rejection.
+
+          if (!globalRect.intersect(existsTextCfg.rect)) {
+            continue;
+          }
+
+          if (isAxisAligned && existsTextCfg.axisAligned) {
+            // Is overlapped
+            overlapped = true;
+            break;
+          }
+
+          if (!existsTextCfg.obb) {
+            // If self is not axis aligned. But other is.
+            existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform);
+          }
+
+          if (!obb) {
+            // If self is axis aligned. But other is not.
+            obb = new OrientedBoundingRect(localRect, transform);
+          }
+
+          if (obb.intersect(existsTextCfg.obb)) {
+            overlapped = true;
+            break;
+          }
+        } // TODO Callback to determine if this overlap should be handled?
+
+
+        if (overlapped) {
+          hideEl(label);
+          labelLine && hideEl(labelLine);
+        } else {
+          label.attr('ignore', labelItem.defaultAttr.ignore);
+          labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
+          displayedLabels.push(labelItem);
+        }
+      }
+    }
 
     function returnFalse() {
         return false;
@@ -36986,13 +37226,13 @@
                 var el = displayList[i];
                 if (el) {
                     var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
-                    var prevRect = el.__isRendered && ((el.__dirty & REDARAW_BIT) || !shouldPaint)
+                    var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint)
                         ? el.getPrevPaintRect()
                         : null;
                     if (prevRect) {
                         addRectToMergePool(prevRect);
                     }
-                    var curRect = shouldPaint && ((el.__dirty & REDARAW_BIT) || !el.__isRendered)
+                    var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered)
                         ? el.getPaintRect()
                         : null;
                     if (curRect) {
@@ -37600,7 +37840,7 @@
                     updatePrevLayer(i);
                     prevLayer = layer;
                 }
-                if ((el.__dirty & REDARAW_BIT) && !el.__inHover) {
+                if ((el.__dirty & REDRAW_BIT) && !el.__inHover) {
                     layer.__dirty = true;
                     if (layer.incremental && layer.__drawIndex < 0) {
                         layer.__drawIndex = i;
@@ -39337,8 +39577,60 @@
       stepPoints.push(points[i++], points[i++]);
       return stepPoints;
     }
+    /**
+     * Clip color stops to edge. Avoid creating too large gradients.
+     * Which may lead to blurry when GPU acceleration is enabled. See #15680
+     *
+     * The stops has been sorted from small to large.
+     */
 
-    function getVisualGradient(data, coordSys) {
+
+    function clipColorStops(colorStops, maxSize) {
+      var newColorStops = [];
+      var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop.
+
+      var prevOutOfRangeColorStop;
+      var prevInRangeColorStop;
+
+      function lerpStop(stop0, stop1, clippedCoord) {
+        var coord0 = stop0.coord;
+        var p = (clippedCoord - coord0) / (stop1.coord - coord0);
+        var color = lerp$1(p, [stop0.color, stop1.color]);
+        return {
+          coord: clippedCoord,
+          color: color
+        };
+      }
+
+      for (var i = 0; i < len; i++) {
+        var stop_1 = colorStops[i];
+        var coord = stop_1.coord;
+
+        if (coord < 0) {
+          prevOutOfRangeColorStop = stop_1;
+        } else if (coord > maxSize) {
+          if (prevInRangeColorStop) {
+            newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize));
+          } // All following stop will be out of range. So just ignore them.
+
+
+          break;
+        } else {
+          if (prevOutOfRangeColorStop) {
+            newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset
+
+            prevOutOfRangeColorStop = null;
+          }
+
+          newColorStops.push(stop_1);
+          prevInRangeColorStop = stop_1;
+        }
+      }
+
+      return newColorStops;
+    }
+
+    function getVisualGradient(data, coordSys, api) {
       var visualMetaList = data.getVisual('visualMeta');
 
       if (!visualMetaList || !visualMetaList.length || !data.count()) {
@@ -39381,16 +39673,12 @@
       // LinearGradient to render `outerColors`.
 
 
-      var axis = coordSys.getAxis(coordDim);
-      var axisScaleExtent = axis.scale.getExtent(); // dataToCoord mapping may not be linear, but must be monotonic.
+      var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic.
 
       var colorStops = map(visualMeta.stops, function (stop) {
-        var coord = axis.toGlobalCoord(axis.dataToCoord(stop.value)); // normalize the infinite value
-
-        isNaN(coord) || isFinite(coord) || (coord = axis.toGlobalCoord(axis.dataToCoord(axisScaleExtent[+(coord < 0)])));
+        // offset will be calculated later.
         return {
-          offset: 0,
-          coord: coord,
+          coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
           color: stop.color
         };
       });
@@ -39402,32 +39690,37 @@
         outerColors.reverse();
       }
 
-      var tinyExtent = 10; // Arbitrary value: 10px
+      var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight());
+      var inRangeStopLen = colorStopsInRange.length;
+
+      if (!inRangeStopLen && stopLen) {
+        // All stops are out of range. All will be the same color.
+        return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color;
+      }
+
+      var tinyExtent = 0; // Arbitrary value: 10px
 
-      var minCoord = colorStops[0].coord - tinyExtent;
-      var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
+      var minCoord = colorStopsInRange[0].coord - tinyExtent;
+      var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent;
       var coordSpan = maxCoord - minCoord;
 
       if (coordSpan < 1e-3) {
         return 'transparent';
       }
 
-      each(colorStops, function (stop) {
+      each(colorStopsInRange, function (stop) {
         stop.offset = (stop.coord - minCoord) / coordSpan;
       });
-      colorStops.push({
-        offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
+      colorStopsInRange.push({
+        // NOTE: inRangeStopLen may still be 0 if stoplen is zero.
+        offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5,
         color: outerColors[1] || 'transparent'
       });
-      colorStops.unshift({
-        offset: stopLen ? colorStops[0].offset : 0.5,
+      colorStopsInRange.unshift({
+        offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5,
         color: outerColors[0] || 'transparent'
-      }); // zrUtil.each(colorStops, function (colorStop) {
-      //     // Make sure each offset has rounded px to avoid not sharp edge
-      //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
-      // });
-
-      var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
+      });
+      var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true);
       gradient[coordDim] = minCoord;
       gradient[coordDim + '2'] = maxCoord;
       return gradient;
@@ -39702,7 +39995,7 @@
         }
 
         this._clipShapeForSymbol = clipShapeForSymbol;
-        var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
+        var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed
 
         if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
           showSymbol && symbolDraw.updateData(data, {
@@ -39752,9 +40045,19 @@
           } // Update clipPath
 
 
-          lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend
+          var oldClipPath = lineGroup.getClipPath();
+
+          if (oldClipPath) {
+            var newClipPath = createLineClipPath(this, coordSys, false, seriesModel);
+            initProps(oldClipPath, {
+              shape: newClipPath.shape
+            }, seriesModel);
+          } else {
+            lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
+          } // Always update, or it is wrong in the case turning on legend
           // because points are not changed
 
+
           showSymbol && symbolDraw.updateData(data, {
             isIgnore: isIgnoreFunc,
             clipShape: clipShapeForSymbol,
@@ -40225,11 +40528,13 @@
 
 
         if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
+          polyline.stopAnimation();
           polyline.setShape({
             points: next
           });
 
           if (polygon) {
+            polygon.stopAnimation();
             polygon.setShape({
               points: next,
               stackedOnPoints: stackedOnNext
@@ -41501,16 +41806,9 @@
         return rect;
       },
       polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
-        // Keep the same logic with bar in catesion: use end value to control
-        // direction. Notice that if clockwise is true (by default), the sector
-        // will always draw clockwisely, no matter whether endAngle is greater
-        // or less than startAngle.
-        var clockwise = layout.startAngle < layout.endAngle;
         var ShapeClass = !isRadial && roundCap ? SausagePath : Sector;
         var sector = new ShapeClass({
-          shape: defaults({
-            clockwise: clockwise
-          }, layout),
+          shape: layout,
           z2: 1
         });
         sector.name = 'item';
@@ -41641,7 +41939,8 @@
           r0: layout.r0,
           r: layout.r,
           startAngle: layout.startAngle,
-          endAngle: layout.endAngle
+          endAngle: layout.endAngle,
+          clockwise: layout.clockwise
         };
       }
     };
@@ -44523,7 +44822,21 @@
         var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
         var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
         fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
-        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection);
+        buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart.
+        // See https://github.com/apache/echarts/issues/14266 for more.
+
+        if (axisModel.get(['axisLabel', 'hideOverlap'])) {
+          var labelList = prepareLayoutList(map(labelEls, function (label) {
+            return {
+              label: label,
+              priority: label.z2,
+              defaultAttr: {
+                ignore: label.ignore
+              }
+            };
+          }));
+          hideOverlap(labelList);
+        }
       },
       axisName: function (opt, axisModel, group, transformGroup) {
         var name = retrieve(opt.axisName, axisModel.get('name'));
@@ -44846,7 +45159,7 @@
           y: opt.labelOffset + opt.labelDirection * labelMargin,
           rotation: labelLayout.rotation,
           silent: silent,
-          z2: 10,
+          z2: 10 + (labelItem.level || 0),
           style: createTextStyle(itemLabelModel, {
             text: formattedLabel,
             align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
diff --git a/dist/echarts.simple.js.map b/dist/echarts.simple.js.map
index 6d7c71e..9a65098 100644
--- a/dist/echarts.simple.js.map
+++ b/dist/echarts.simple.js.map
@@ -1 +1 @@
-{"version":3,"file":"echarts.simple.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
+{"version":3,"file":"echarts.simple.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/zrender/lib/core/env.js","../node_modules/zrender/lib/core/util.js","../node_modules/zrender/lib/core/vector.js","../node_modules/zrender/lib/mixin/Draggable.js","../node_modules/zrender/lib/core/Eventful.js","../node_modules/zrender/lib/core/fourPointsTransform.js","../node_modules/zrender/lib/core/dom.js","../node_modules/zrender/lib/core/event.js","../node_modules/zrender/lib/core/ [...]
\ No newline at end of file
diff --git a/dist/echarts.simple.min.js b/dist/echarts.simple.min.js
index a7b42d6..208c139 100644
--- a/dist/echarts.simple.min.js
+++ b/dist/echarts.simple.min.js
@@ -32,7 +32,7 @@
     LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     PERFORMANCE OF THIS SOFTWARE.
-    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
+    ***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])})(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object [...]
 /*!
     * ZRender, a high performance 2d drawing library.
     *
@@ -42,4 +42,4 @@
     * LICENSE
     * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
     */
-var Di=!a.canvasSupported,Ii={},ki={};var Ai=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new ge,o=n.renderer||"canvas";if(Di)throw new Error("IE8 support has been dropped since 5.0");if(Ii[o]||(o=N(Ii)[0]),!Ii[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
+var Ii=!a.canvasSupported,ki={},Ai={};var Pi=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var r=new ye,o=n.renderer||"canvas";if(Ii)throw new Error("IE8 support has been dropped since 5.0");if(ki[o]||(o=E(ki)[0]),!ki[o])throw new Error("Renderer '"+o+"' is not imported. Please import it first.");n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var [...]
diff --git a/dist/extension/dataTool.js.map b/dist/extension/dataTool.js.map
index 699dd28..783b1b8 100644
--- a/dist/extension/dataTool.js.map
+++ b/dist/extension/dataTool.js.map
@@ -1 +1 @@
-{"version":3,"file":"dataTool.js","sources":["../../node_modules/zrender/lib/core/util.js","../../extension/dataTool/gexf.js","../../extension/dataTool/prepareBoxplotData.js","../../extension/dataTool/index.js"],"sourcesContent":["var BUILTIN_OBJECT = {\n    '[object Function]': true,\n    '[object RegExp]': true,\n    '[object Date]': true,\n    '[object Error]': true,\n    '[object CanvasGradient]': true,\n    '[object CanvasPattern]': true,\n    '[object Image]': true,\n    '[object C [...]
\ No newline at end of file
+{"version":3,"file":"dataTool.js","sources":["../../node_modules/zrender/lib/core/util.js","../../extension/dataTool/gexf.js","../../extension/dataTool/prepareBoxplotData.js","../../extension/dataTool/index.js"],"sourcesContent":["var BUILTIN_OBJECT = {\n    '[object Function]': true,\n    '[object RegExp]': true,\n    '[object Date]': true,\n    '[object Error]': true,\n    '[object CanvasGradient]': true,\n    '[object CanvasPattern]': true,\n    '[object Image]': true,\n    '[object C [...]
\ No newline at end of file
diff --git a/i18n/langPT-br-obj.js b/i18n/langPT-br-obj.js
new file mode 100644
index 0000000..62a69b8
--- /dev/null
+++ b/i18n/langPT-br-obj.js
@@ -0,0 +1,174 @@
+
+
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+/**
+ * AUTO-GENERATED FILE. DO NOT MODIFY.
+ */
+(function(root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['exports'], factory);
+    } else if (
+        typeof exports === 'object' &&
+        typeof exports.nodeName !== 'string'
+    ) {
+        // CommonJS
+        factory(exports);
+    } else {
+        // Browser globals
+        factory({});
+    }
+})(this, function(exports) {
+
+
+/**
+ * Language: Portuguese (Brazil).
+ */
+
+var localeObj = {
+    time: {
+        month: [
+            'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
+            'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
+        ],
+        monthAbbr: [
+            'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',
+            'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'
+        ],
+        dayOfWeek: [
+            'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira',
+'Quinta-feira', 'Sexta-feira', 'Sábado'
+        ],
+        dayOfWeekAbbr: [
+            'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'
+        ]
+    },
+    legend: {
+        selector: {
+            all: 'Todas',
+            inverse: 'Inv'
+        }
+    },
+    toolbox: {
+        brush: {
+            title: {
+                rect: 'Seleção retangular',
+                polygon: 'Seleção em laço',
+                lineX: 'Selecionar horizontalmente',
+                lineY: 'Selecionar verticalmente',
+                keep: 'Manter seleções',
+                clear: 'Limpar seleções'
+            }
+        },
+        dataView: {
+            title: 'Exibição de dados',
+            lang: ['Exibição de dados', 'Fechar', 'Atualizar']
+        },
+        dataZoom: {
+            title: {
+                zoom: 'Zoom',
+                back: 'Restaurar Zoom'
+            }
+        },
+        magicType: {
+            title: {
+                line: 'Trocar para gráfico de linhas',
+                bar: 'Trocar para gráfico de barras',
+                stack: 'Empilhar',
+                tiled: 'Tile'
+            }
+        },
+        restore: {
+            title: 'Restore'
+        },
+        saveAsImage: {
+            title: 'Salvar como imagem',
+            lang: ['Clique com o botão direito para salvar imagem']
+        }
+    },
+    series: {
+        typeNames: {
+            pie: 'Gráfico de pizza',
+            bar: 'Gráfico de barras',
+            line: 'Gráfico de linhas',
+            scatter: 'Gráfico de dispersão',
+            effectScatter: 'Gráfico de dispersão ondulado',
+            radar: 'Gráfico radar',
+            tree: 'Árvore',
+            treemap: 'Treemap',
+            boxplot: 'Boxplot',
+            candlestick: 'Candlestick',
+            k: 'Gráfico K line',
+            heatmap: 'Mapa de calor',
+            map: 'Mapa',
+            parallel: 'Coordenadas paralelas',
+            lines: 'Gráfico de linhas',
+            graph: 'Relationship graph',
+            sankey: 'Gráfico Sankey',
+            funnel: 'Gráfico de funil',
+            gauge: 'Gauge',
+            pictorialBar: 'Pictorial bar',
+            themeRiver: 'Theme River Map',
+            sunburst: 'Sunburst'
+        }
+    },
+    aria: {
+        general: {
+            withTitle: 'Este é um gráfico entitulado "{title}"',
+            withoutTitle: 'Este é um gráfico'
+        },
+        series: {
+            single: {
+                prefix: '',
+                withName: ' do tipo {seriesType} nomeada/nomeado como {seriesName}.',
+                withoutName: ' do tipo {seriesType}.'
+            },
+            multiple: {
+                prefix: '. Consiste de {seriesCount} séries.',
+                withName: ' A {seriesId} série é um/uma {seriesType} representando {seriesName}.',
+                withoutName: ' A {seriesId} series é um/uma {seriesType}.',
+                separator: {
+                    middle: '',
+                    end: ''
+                }
+            }
+        },
+        data: {
+            allData: 'Os dados são: ',
+            partialData: 'As primeiros {displayCnt} itens são: ',
+            withName: 'os dados para {name} são {value}',
+            withoutName: '{value}',
+            separator: {
+                middle: ', ',
+                end: '. '
+            }
+        }
+    }
+};
+
+    for (var key in localeObj) {
+        if (localeObj.hasOwnProperty(key)) {
+            exports[key] = localeObj[key];
+        }
+    }
+        
+});
\ No newline at end of file
diff --git a/i18n/langPT-br.js b/i18n/langPT-br.js
new file mode 100644
index 0000000..5711e7e
--- /dev/null
+++ b/i18n/langPT-br.js
@@ -0,0 +1,170 @@
+
+
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+/**
+ * AUTO-GENERATED FILE. DO NOT MODIFY.
+ */
+(function(root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['exports', 'echarts'], factory);
+    } else if (
+        typeof exports === 'object' &&
+        typeof exports.nodeName !== 'string'
+    ) {
+        // CommonJS
+        factory(exports, require('echarts/lib/echarts'));
+    } else {
+        // Browser globals
+        factory({}, root.echarts);
+    }
+})(this, function(exports, echarts) {
+
+
+/**
+ * Language: Portuguese (Brazil).
+ */
+
+var localeObj = {
+    time: {
+        month: [
+            'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
+            'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
+        ],
+        monthAbbr: [
+            'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',
+            'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'
+        ],
+        dayOfWeek: [
+            'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira',
+'Quinta-feira', 'Sexta-feira', 'Sábado'
+        ],
+        dayOfWeekAbbr: [
+            'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'
+        ]
+    },
+    legend: {
+        selector: {
+            all: 'Todas',
+            inverse: 'Inv'
+        }
+    },
+    toolbox: {
+        brush: {
+            title: {
+                rect: 'Seleção retangular',
+                polygon: 'Seleção em laço',
+                lineX: 'Selecionar horizontalmente',
+                lineY: 'Selecionar verticalmente',
+                keep: 'Manter seleções',
+                clear: 'Limpar seleções'
+            }
+        },
+        dataView: {
+            title: 'Exibição de dados',
+            lang: ['Exibição de dados', 'Fechar', 'Atualizar']
+        },
+        dataZoom: {
+            title: {
+                zoom: 'Zoom',
+                back: 'Restaurar Zoom'
+            }
+        },
+        magicType: {
+            title: {
+                line: 'Trocar para gráfico de linhas',
+                bar: 'Trocar para gráfico de barras',
+                stack: 'Empilhar',
+                tiled: 'Tile'
+            }
+        },
+        restore: {
+            title: 'Restore'
+        },
+        saveAsImage: {
+            title: 'Salvar como imagem',
+            lang: ['Clique com o botão direito para salvar imagem']
+        }
+    },
+    series: {
+        typeNames: {
+            pie: 'Gráfico de pizza',
+            bar: 'Gráfico de barras',
+            line: 'Gráfico de linhas',
+            scatter: 'Gráfico de dispersão',
+            effectScatter: 'Gráfico de dispersão ondulado',
+            radar: 'Gráfico radar',
+            tree: 'Árvore',
+            treemap: 'Treemap',
+            boxplot: 'Boxplot',
+            candlestick: 'Candlestick',
+            k: 'Gráfico K line',
+            heatmap: 'Mapa de calor',
+            map: 'Mapa',
+            parallel: 'Coordenadas paralelas',
+            lines: 'Gráfico de linhas',
+            graph: 'Relationship graph',
+            sankey: 'Gráfico Sankey',
+            funnel: 'Gráfico de funil',
+            gauge: 'Gauge',
+            pictorialBar: 'Pictorial bar',
+            themeRiver: 'Theme River Map',
+            sunburst: 'Sunburst'
+        }
+    },
+    aria: {
+        general: {
+            withTitle: 'Este é um gráfico entitulado "{title}"',
+            withoutTitle: 'Este é um gráfico'
+        },
+        series: {
+            single: {
+                prefix: '',
+                withName: ' do tipo {seriesType} nomeada/nomeado como {seriesName}.',
+                withoutName: ' do tipo {seriesType}.'
+            },
+            multiple: {
+                prefix: '. Consiste de {seriesCount} séries.',
+                withName: ' A {seriesId} série é um/uma {seriesType} representando {seriesName}.',
+                withoutName: ' A {seriesId} series é um/uma {seriesType}.',
+                separator: {
+                    middle: '',
+                    end: ''
+                }
+            }
+        },
+        data: {
+            allData: 'Os dados são: ',
+            partialData: 'As primeiros {displayCnt} itens são: ',
+            withName: 'os dados para {name} são {value}',
+            withoutName: '{value}',
+            separator: {
+                middle: ', ',
+                end: '. '
+            }
+        }
+    }
+};
+
+    echarts.registerLocale('PT-br', localeObj);
+        
+});
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 7c07116..c319fcf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "echarts",
-  "version": "5.2.0",
+  "version": "5.2.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -11122,9 +11122,9 @@
       }
     },
     "zrender": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.2.0.tgz",
-      "integrity": "sha512-87v3gvB0lcWy48ObA/DwrhQ95ADMMRhECVrXmHDFCBNvbxHFfEDZtrZh4VmVjLAeFAjimY4PyZ65rbLCivdszA==",
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.2.1.tgz",
+      "integrity": "sha512-M3bPGZuyLTNBC6LiNKXJwSCtglMp8XUEqEBG+2MdICDI3d1s500Y4P0CzldQGsqpRVB7fkvf3BKQQRxsEaTlsw==",
       "requires": {
         "tslib": "2.3.0"
       }
diff --git a/package.json b/package.json
index 1830cb9..319d57e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "echarts",
-  "version": "5.2.0",
+  "version": "5.2.1",
   "description": "Apache ECharts is a powerful, interactive charting and data visualization library for browser",
   "license": "Apache-2.0",
   "keywords": [
@@ -64,7 +64,7 @@
   },
   "dependencies": {
     "tslib": "2.3.0",
-    "zrender": "5.2.0"
+    "zrender": "5.2.1"
   },
   "devDependencies": {
     "@babel/code-frame": "7.10.4",
diff --git a/src/core/echarts.ts b/src/core/echarts.ts
index 9d13ebc..8a61c98 100644
--- a/src/core/echarts.ts
+++ b/src/core/echarts.ts
@@ -139,10 +139,10 @@ type ModelFinder = modelUtil.ModelFinder;
 
 const hasWindow = typeof window !== 'undefined';
 
-export const version = '5.2.0';
+export const version = '5.2.1';
 
 export const dependencies = {
-    zrender: '5.2.0'
+    zrender: '5.2.1'
 };
 
 const TEST_FRAME_REMAIN_TIME = 1;

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