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/11/16 04:51:49 UTC

[echarts] 01/01: fix(dataZoom): optimize dataZoom shadow render performance

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

shenyi pushed a commit to branch optimize-dataZoom-shadow-performance
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit 15375ca696f11447af76ac57c0f0309399ea71ae
Author: pissang <bm...@gmail.com>
AuthorDate: Tue Nov 16 12:44:02 2021 +0800

    fix(dataZoom): optimize dataZoom shadow render performance
---
 src/component/dataZoom/SliderZoomView.ts | 111 ++++++++++++++++++-------------
 1 file changed, 64 insertions(+), 47 deletions(-)

diff --git a/src/component/dataZoom/SliderZoomView.ts b/src/component/dataZoom/SliderZoomView.ts
index b677224..ff43663 100644
--- a/src/component/dataZoom/SliderZoomView.ts
+++ b/src/component/dataZoom/SliderZoomView.ts
@@ -42,6 +42,7 @@ import { deprecateLog } from '../../util/log';
 import { PointLike } from 'zrender/src/core/Point';
 import Displayable from 'zrender/src/graphic/Displayable';
 import {createTextStyle} from '../../label/labelStyle';
+import SeriesData from '../../data/SeriesData';
 
 const Rect = graphic.Rect;
 
@@ -124,6 +125,12 @@ class SliderZoomView extends DataZoomView {
         otherAxisInverse: boolean
     };
 
+    // Cached raw data. Avoid rendering data shadow multiple times.
+    private _shadowData: SeriesData;
+    private _shadowDim: string;
+    private _shadowPolygonPts: number[][];
+    private _shadowPolylinePts: number[][];
+
     init(ecModel: GlobalModel, api: ExtensionAPI) {
         this.api = api;
 
@@ -350,7 +357,6 @@ class SliderZoomView extends DataZoomView {
         const size = this._size;
         const seriesModel = info.series;
         const data = seriesModel.getRawData();
-
         const otherDim: string = seriesModel.getShadowDim
             ? seriesModel.getShadowDim() // @see candlestick
             : info.otherDim;
@@ -359,57 +365,68 @@ class SliderZoomView extends DataZoomView {
             return;
         }
 
-        let otherDataExtent = data.getDataExtent(otherDim);
-        // Nice extent.
-        const otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
-        otherDataExtent = [
-            otherDataExtent[0] - otherOffset,
-            otherDataExtent[1] + otherOffset
-        ];
-        const otherShadowExtent = [0, size[1]];
-
-        const thisShadowExtent = [0, size[0]];
+        let polygonPts = this._shadowPolygonPts;
+        let polylinePts = this._shadowPolylinePts;
+        // Not re-render if data doesn't change.
+        if (data !== this._shadowData || otherDim !== this._shadowDim) {
+            let otherDataExtent = data.getDataExtent(otherDim);
+            // Nice extent.
+            const otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
+            otherDataExtent = [
+                otherDataExtent[0] - otherOffset,
+                otherDataExtent[1] + otherOffset
+            ];
+            const otherShadowExtent = [0, size[1]];
+
+            const thisShadowExtent = [0, size[0]];
+
+            const areaPoints = [[size[0], 0], [0, 0]];
+            const linePoints: number[][] = [];
+            const step = thisShadowExtent[1] / (data.count() - 1);
+            let thisCoord = 0;
+
+            // Optimize for large data shadow
+            const stride = Math.round(data.count() / size[0]);
+            let lastIsEmpty: boolean;
+            data.each([otherDim], function (value: ParsedValue, index) {
+                if (stride > 0 && (index % stride)) {
+                    thisCoord += step;
+                    return;
+                }
 
-        const areaPoints = [[size[0], 0], [0, 0]];
-        const linePoints: number[][] = [];
-        const step = thisShadowExtent[1] / (data.count() - 1);
-        let thisCoord = 0;
+                // FIXME
+                // Should consider axis.min/axis.max when drawing dataShadow.
 
-        // Optimize for large data shadow
-        const stride = Math.round(data.count() / size[0]);
-        let lastIsEmpty: boolean;
-        data.each([otherDim], function (value: ParsedValue, index) {
-            if (stride > 0 && (index % stride)) {
-                thisCoord += step;
-                return;
-            }
+                // FIXME
+                // 应该使用统一的空判断?还是在list里进行空判断?
+                const isEmpty = value == null || isNaN(value as number) || value === '';
+                // See #4235.
+                const otherCoord = isEmpty
+                    ? 0 : linearMap(value as number, otherDataExtent, otherShadowExtent, true);
 
-            // FIXME
-            // Should consider axis.min/axis.max when drawing dataShadow.
+                // Attempt to draw data shadow precisely when there are empty value.
+                if (isEmpty && !lastIsEmpty && index) {
+                    areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
+                    linePoints.push([linePoints[linePoints.length - 1][0], 0]);
+                }
+                else if (!isEmpty && lastIsEmpty) {
+                    areaPoints.push([thisCoord, 0]);
+                    linePoints.push([thisCoord, 0]);
+                }
 
-            // FIXME
-            // 应该使用统一的空判断?还是在list里进行空判断?
-            const isEmpty = value == null || isNaN(value as number) || value === '';
-            // See #4235.
-            const otherCoord = isEmpty
-                ? 0 : linearMap(value as number, otherDataExtent, otherShadowExtent, true);
+                areaPoints.push([thisCoord, otherCoord]);
+                linePoints.push([thisCoord, otherCoord]);
 
-            // Attempt to draw data shadow precisely when there are empty value.
-            if (isEmpty && !lastIsEmpty && index) {
-                areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
-                linePoints.push([linePoints[linePoints.length - 1][0], 0]);
-            }
-            else if (!isEmpty && lastIsEmpty) {
-                areaPoints.push([thisCoord, 0]);
-                linePoints.push([thisCoord, 0]);
-            }
+                thisCoord += step;
+                lastIsEmpty = isEmpty;
+            });
 
-            areaPoints.push([thisCoord, otherCoord]);
-            linePoints.push([thisCoord, otherCoord]);
+            polygonPts = this._shadowPolygonPts = areaPoints;
+            polylinePts = this._shadowPolylinePts = linePoints;
 
-            thisCoord += step;
-            lastIsEmpty = isEmpty;
-        });
+        }
+        this._shadowData = data;
+        this._shadowDim = otherDim;
 
         const dataZoomModel = this.dataZoomModel;
 
@@ -417,14 +434,14 @@ class SliderZoomView extends DataZoomView {
             const model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground');
             const group = new graphic.Group();
             const polygon = new graphic.Polygon({
-                shape: {points: areaPoints},
+                shape: {points: polygonPts},
                 segmentIgnoreThreshold: 1,
                 style: model.getModel('areaStyle').getAreaStyle(),
                 silent: true,
                 z2: -20
             });
             const polyline = new graphic.Polyline({
-                shape: {points: linePoints},
+                shape: {points: polylinePts},
                 segmentIgnoreThreshold: 1,
                 style: model.getModel('lineStyle').getLineStyle(),
                 silent: true,

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