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

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

commit ddab25f623950f31de61d12186939cb7d77e2f2a
Author: sushuang <sushuang0...@gmail.com>
AuthorDate: Mon Apr 16 23:43:05 2018 +0800

    support auto sampling in progressive, which makes the incremental graphic 
elements uniformly distributed.
---
 src/chart/candlestick/CandlestickSeries.js |  1 +
 src/chart/candlestick/CandlestickView.js   |  4 +-
 src/chart/candlestick/candlestickLayout.js | 20 +++----
 src/chart/candlestick/candlestickVisual.js |  3 +-
 src/stream/Scheduler.js                    | 13 ++++-
 src/stream/task.js                         | 71 +++++++++++++++++++++++--
 test/candlestick-large2.html               | 50 +++++++-----------
 test/candlestick-large3.html               | 84 ++++++++++++++++++++++--------
 8 files changed, 175 insertions(+), 71 deletions(-)

diff --git a/src/chart/candlestick/CandlestickSeries.js 
b/src/chart/candlestick/CandlestickSeries.js
index 682cb7e..0d2d352 100644
--- a/src/chart/candlestick/CandlestickSeries.js
+++ b/src/chart/candlestick/CandlestickSeries.js
@@ -60,6 +60,7 @@ var CandlestickSeries = SeriesModel.extend({
 
         progressive: 5e3,
         progressiveThreshold: 1e4,
+        progressiveChunkMode: 'mod',
 
         animationUpdate: false,
         animationEasing: 'linear',
diff --git a/src/chart/candlestick/CandlestickView.js 
b/src/chart/candlestick/CandlestickView.js
index 527f62a..4200c1c 100644
--- a/src/chart/candlestick/CandlestickView.js
+++ b/src/chart/candlestick/CandlestickView.js
@@ -45,7 +45,6 @@ var CandlestickView = ChartView.extend({
     },
 
     _renderNormal: function (seriesModel) {
-        // var largePoints = data.getLayout('largePoints');
         var data = seriesModel.getData();
         var oldData = this._data;
         var group = this.group;
@@ -115,7 +114,8 @@ var CandlestickView = ChartView.extend({
         var data = seriesModel.getData();
         var isSimpleBox = data.getLayout('isSimpleBox');
 
-        for (var dataIndex = params.start; dataIndex < params.end; 
dataIndex++) {
+        var dataIndex;
+        while ((dataIndex = params.next()) != null) {
             var el;
 
             var itemLayout = data.getItemLayout(dataIndex);
diff --git a/src/chart/candlestick/candlestickLayout.js 
b/src/chart/candlestick/candlestickLayout.js
index 3aa8d5c..40f6712 100644
--- a/src/chart/candlestick/candlestickLayout.js
+++ b/src/chart/candlestick/candlestickLayout.js
@@ -42,8 +42,8 @@ export default {
         };
 
         function normalProgress(params, data) {
-
-            for (var dataIndex = params.start; dataIndex < params.end; 
dataIndex++) {
+            var dataIndex;
+            while ((dataIndex = params.next()) != null) {
 
                 var axisDimVal = data.get(cDim, dataIndex);
                 var openVal = data.get(openDim, dataIndex);
@@ -126,15 +126,15 @@ export default {
         }
 
         function largeProgress(params, data) {
-            var segCount = params.end - params.start;
             // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...]
-            var points = new LargeArr(segCount * 5);
-
-            for (
-                var dataIndex = params.start, offset = 0, point, tmpIn = [], 
tmpOut = [];
-                dataIndex < params.end;
-                dataIndex++
-            ) {
+            var points = new LargeArr(params.count * 5);
+            var offset = 0;
+            var point;
+            var tmpIn = [];
+            var tmpOut = [];
+            var dataIndex;
+
+            while ((dataIndex = params.next()) != null) {
                 var axisDimVal = data.get(cDim, dataIndex);
                 var openVal = data.get(openDim, dataIndex);
                 var closeVal = data.get(closeDim, dataIndex);
diff --git a/src/chart/candlestick/candlestickVisual.js 
b/src/chart/candlestick/candlestickVisual.js
index 9273480..abca11e 100644
--- a/src/chart/candlestick/candlestickVisual.js
+++ b/src/chart/candlestick/candlestickVisual.js
@@ -36,7 +36,8 @@ export default {
 
 
         function progress(params, data) {
-            for (var dataIndex = params.start; dataIndex < params.end; 
dataIndex++) {
+            var dataIndex;
+            while ((dataIndex = params.next()) != null) {
                 var itemModel = data.getItemModel(dataIndex);
                 var sign = data.getItemLayout(dataIndex).sign;
 
diff --git a/src/stream/Scheduler.js b/src/stream/Scheduler.js
index 4dfcf80..beb5d88 100644
--- a/src/stream/Scheduler.js
+++ b/src/stream/Scheduler.js
@@ -93,7 +93,11 @@ proto.getPerformArgs = function (task, isBlock) {
         && (!pCtx || pCtx.progressiveRender)
         && task.__idxInPipeline > pipeline.bockIndex;
 
-    return {step: incremental ? pipeline.step : null};
+    var step = incremental ? pipeline.step : null;
+    var modDataCount = pCtx && pCtx.modDataCount;
+    var modBy = modDataCount != null ? Math.ceil(modDataCount / step): null;
+
+    return {step: step, modBy: modBy, modDataCount: modDataCount};
 };
 
 proto.getPipeline = function (pipelineId) {
@@ -123,8 +127,13 @@ proto.updateStreamModes = function (seriesModel, view) {
 
     var large = seriesModel.get('large') && dataLen >= 
seriesModel.get('largeThreshold');
 
+    // TODO: modDataCount should not updated if `appendData`, otherwise cause 
whole repaint.
+    // see `test/candlestick-large3.html`
+    var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? 
dataLen : null;
+
     seriesModel.pipelineContext = pipeline.context = {
         progressiveRender: progressiveRender,
+        modDataCount: modDataCount,
         large: large
     };
 };
@@ -145,7 +154,7 @@ proto.restorePipelines = function (ecModel) {
             progressiveEnabled: progressive
                 && !(seriesModel.preventIncremental && 
seriesModel.preventIncremental()),
             bockIndex: -1,
-            step: progressive || 700, // ??? Temporarily number
+            step: Math.round(progressive || 700),
             count: 0
         });
 
diff --git a/src/stream/task.js b/src/stream/task.js
index e55b8dd..e1d19bc 100644
--- a/src/stream/task.js
+++ b/src/stream/task.js
@@ -38,6 +38,8 @@ var taskProto = Task.prototype;
  * @param {Object} performArgs
  * @param {number} [performArgs.step] Specified step.
  * @param {number} [performArgs.skip] Skip customer perform call.
+ * @param {number} [performArgs.modBy] Sampling window size.
+ * @param {number} [performArgs.modDataCount] Sampling count.
  */
 taskProto.perform = function (performArgs) {
     var upTask = this._upstream;
@@ -60,12 +62,30 @@ taskProto.perform = function (performArgs) {
         planResult = this._plan(this.context);
     }
 
+    // Support sharding by mod, which changes the render sequence and makes 
the rendered graphic
+    // elements uniformed distributed when progress, especially when moving or 
zooming.
+    var lastModBy = normalizeModBy(this._modBy);
+    var lastModDataCount = this._modDataCount || 0;
+    var modBy = normalizeModBy(performArgs && performArgs.modBy);
+    var modDataCount = performArgs && performArgs.modDataCount || 0;
+    if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
+        planResult = 'reset';
+    }
+
+    function normalizeModBy(val) {
+        !(val >= 1) && (val = 1); // jshint ignore:line
+        return val;
+    }
+
     var forceFirstProgress;
     if (this._dirty || planResult === 'reset') {
         this._dirty = false;
         forceFirstProgress = reset(this, skip);
     }
 
+    this._modBy = modBy;
+    this._modDataCount = modDataCount;
+
     var step = performArgs && performArgs.step;
 
     if (upTask) {
@@ -92,9 +112,12 @@ taskProto.perform = function (performArgs) {
             this._dueEnd
         );
 
-        !skip && (forceFirstProgress || start < end) && (
-            this._progress({start: start, end: end}, this.context)
-        );
+        if (!skip && (forceFirstProgress || start < end)) {
+            iterator.reset(start, end, modBy, modDataCount);
+            this._progress({
+                start: start, end: end, step: 1, count: end - start, next: 
iterator.next
+            }, this.context);
+        }
 
         this._dueIndex = end;
         // If no `outputDueEnd`, assume that output data and
@@ -120,6 +143,47 @@ taskProto.perform = function (performArgs) {
     return this.unfinished();
 };
 
+var iterator = (function () {
+
+    var end;
+    var current;
+    var modBy;
+    var modDataCount;
+    var winCount;
+
+    var it = {
+        reset: function (s, e, sStep, sCount) {
+            current = s;
+            end = e;
+
+            modBy = sStep;
+            modDataCount = sCount;
+            winCount = Math.ceil(modDataCount / modBy);
+
+            it.next = (modBy > 1 && modDataCount > 0) ? modNext : 
sequentialNext;
+        }
+    };
+
+    return it;
+
+    function sequentialNext() {
+        return current < end ? current++ : null;
+    }
+
+    function modNext() {
+        var dataIndex = (current % winCount) * modBy + Math.ceil(current / 
winCount);
+        var result = current >= end
+            ? null
+            : dataIndex < modDataCount
+            ? dataIndex
+            // If modDataCount is smaller than data.count() (consider 
`appendData` case),
+            // Use normal linear rendering mode.
+            : current;
+        current++;
+        return result;
+    }
+})();
+
 taskProto.dirty = function () {
     this._dirty = true;
     this._onDirty && this._onDirty(this.context);
@@ -144,6 +208,7 @@ function reset(taskIns, skip) {
     }
 
     taskIns._progress = progress;
+    taskIns._modBy = taskIns._modDataCount = null;
 
     var downstream = taskIns._downstream;
     downstream && downstream.dirty();
diff --git a/test/candlestick-large2.html b/test/candlestick-large2.html
index ec99971..9c4019b 100644
--- a/test/candlestick-large2.html
+++ b/test/candlestick-large2.html
@@ -3,11 +3,12 @@
     <head>
         <meta charset="utf-8">
         <meta name="viewport" content="width=device-width, initial-scale=1" />
-        <script src="../dist/echarts.js"></script>
+        <script src="lib/esl.js"></script>
         <script src="lib/config.js"></script>
         <script src="lib/jquery.min.js"></script>
         <script src="lib/facePrint.js"></script>
         <script src="lib/testHelper.js"></script>
+        <script src="lib/frameInsight.js"></script>
         <link rel="stylesheet" href="lib/reset.css" />
     </head>
     <body>
@@ -21,6 +22,7 @@
 
         <div id="main0"></div>
         <div id="panel0"></div>
+        <div id="duration"></div>
 
 
 
@@ -28,14 +30,15 @@
 
         <script>
 
+        require(['echarts'], function (echarts) {
+
             // The data count is from a real requirement.
             var rawDataCount = 2e5;
-            var progressive = 4e3;
 
             function run() {
                 var data = generateOHLC(rawDataCount);
-                var result = reorder(data);
-                init(result.data, result.categoryData);
+                // var result = reorder(data);
+                init(data);
             }
 
             function generateOHLC(count) {
@@ -76,27 +79,6 @@
                 return data;
             }
 
-            function reorder(data) {
-                var categoryData = new Array(data.length);
-                var categoryMap = {};
-                for (var i = 0; i < data.length; i++) {
-                    categoryData[i] = data[i][0];
-                    categoryMap[categoryData[i]] = i;
-                }
-
-                var newData = new Array(data.length);
-                var step = Math.round(data.length / progressive);
-                var newOffset = 0;
-                for (var offset = 0; offset < step; offset++) {
-                    for (var i = offset; i < data.length; i += step) {
-                        var item = data[i].slice();
-                        newData[newOffset++] = item;
-                        item[0] = categoryMap[item[0]];
-                    }
-                }
-                return {data: newData, categoryData: categoryData};
-            }
-
             function calculateMA(dayCount, data) {
                 var result = [];
                 for (var i = 0, len = data.length; i < len; i++) {
@@ -113,7 +95,9 @@
                 return result;
             }
 
-            function init(rawData, categoryData) {
+            function init(rawData) {
+
+                frameInsight.init(echarts, 'duration');
 
                 var option = {
                     dataset: {
@@ -165,12 +149,12 @@
                             type: 'category',
                             scale: true,
                             boundaryGap : false,
+                            // inverse: true,
                             axisLine: {onZero: false},
                             splitLine: {show: false},
                             splitNumber: 20,
                             min: 'dataMin',
-                            max: 'dataMax',
-                            data: categoryData
+                            max: 'dataMax'
                         },
                         // {
                         //     type: 'category',
@@ -222,14 +206,16 @@
                     ],
                     series: [
                         {
-                            name: 'Fake index',
+                            name: 'Data Amount: ' + 
echarts.format.addCommas(rawDataCount),
                             type: 'candlestick',
+                            // progressiveMode: 'linear',
                             // data: data,
                             encode: {
                                 x: 0,
                                 y: [1, 4, 3, 2]
                             },
-                            progressive: progressive
+                            // progressive: false
+                            // progressive: progressive
                             // tooltip: {
                             //     formatter: function (param) {
                             //         var param = param[0];
@@ -291,7 +277,7 @@
 
                 var panel = document.getElementById('panel0');
                 var chart = testHelper.create(echarts, 'main0', {
-                    title: 'Fake OHLC data',
+                    title: 'Progressive by mod',
                     option: option,
                     height: 550
                 });
@@ -337,6 +323,8 @@
 
             run();
 
+        });
+
         </script>
 
 
diff --git a/test/candlestick-large3.html b/test/candlestick-large3.html
index ca595ae..6361201 100644
--- a/test/candlestick-large3.html
+++ b/test/candlestick-large3.html
@@ -33,20 +33,54 @@
         require(['echarts'], function (echarts) {
 
             // The data count is from a real requirement.
-            var rawDataCount = 2e5;
+            var rawDataChunkSize = 1e4;
+            var chunkCount = 20;
+
+            var minute = 60 * 1000;
+            var xValue = +new Date(2011, 0, 1);
+            var baseValue = Math.random() * 12000;
+            var xValueMin = 0;
+            var xValueMax = rawDataChunkSize * chunkCount;
+            var yValueMin = Infinity;
+            var yValueMax = -Infinity;
+
+            var rawData = [];
+            for (var i = 0; i < chunkCount; i++) {
+                rawData.push(generateOHLC(rawDataChunkSize));
+            }
+            yValueMax = Math.ceil(yValueMax);
+            yValueMin = Math.floor(yValueMin);
 
             function run() {
-                var data = generateOHLC(rawDataCount);
-                // var result = reorder(data);
-                init(data);
+
+                frameInsight.init(echarts, 'duration');
+
+                // var data = generateOHLC(rawDataChunkSize);
+                var chart = window.chart = init();
+
+                var loadedChunkIndex = 0;
+
+                appendData();
+
+                function appendData() {
+                    if (loadedChunkIndex >= chunkCount) {
+                        return;
+                    }
+
+                    setTimeout(function () {
+
+                        chart.appendData({seriesIndex: 0, data: 
rawData[loadedChunkIndex]});
+
+                        loadedChunkIndex++;
+
+                        appendData();
+                    }, 300);
+                }
             }
 
             function generateOHLC(count) {
                 var data = [];
 
-                var xValue = +new Date(2011, 0, 1);
-                var minute = 60 * 1000;
-                var baseValue = Math.random() * 12000;
                 var tmpVals = new Array(4);
                 var dayRange = 12;
 
@@ -55,6 +89,12 @@
 
                     for (var j = 0; j < 4; j++) {
                         tmpVals[j] = (Math.random() - 0.5) * dayRange + 
baseValue;
+                        if (tmpVals[j] < yValueMin) {
+                            yValueMin = tmpVals[j];
+                        }
+                        if (tmpVals[j] > yValueMax) {
+                            yValueMax = tmpVals[j];
+                        }
                     }
                     tmpVals.sort();
 
@@ -95,14 +135,9 @@
                 return result;
             }
 
-            function init(rawData) {
-
-                frameInsight.init(echarts, 'duration');
+            function init() {
 
                 var option = {
-                    dataset: {
-                        source: rawData
-                    },
                     backgroundColor: '#eee',
                     // animation: false,
                     legend: {
@@ -153,8 +188,8 @@
                             axisLine: {onZero: false},
                             splitLine: {show: false},
                             splitNumber: 20,
-                            min: 'dataMin',
-                            max: 'dataMax'
+                            min: xValueMin,
+                            max: xValueMax
                         },
                         // {
                         //     type: 'category',
@@ -176,7 +211,9 @@
                             scale: true,
                             splitArea: {
                                 show: true
-                            }
+                            },
+                            min: yValueMin,
+                            max: yValueMax
                         },
                         // {
                         //     scale: true,
@@ -192,27 +229,28 @@
                         {
                             type: 'inside',
                             // xAxisIndex: [0, 1],
-                            start: 10,
-                            end: 100
+                            // start: 10,
+                            // end: 100
                         },
                         {
                             show: true,
                             // xAxisIndex: [0, 1],
                             type: 'slider',
                             bottom: 10,
-                            start: 10,
-                            end: 100
+                            // start: 10,
+                            // end: 100
                         }
                     ],
                     series: [
                         {
-                            name: 'Fake index',
                             type: 'candlestick',
+                            // progressiveMode: 'linear',
                             // data: data,
                             encode: {
                                 x: 0,
                                 y: [1, 4, 3, 2]
                             },
+                            // progressiveChunkMode: 'sequential'
                             // progressive: false
                             // progressive: progressive
                             // tooltip: {
@@ -276,11 +314,13 @@
 
                 var panel = document.getElementById('panel0');
                 var chart = testHelper.create(echarts, 'main0', {
-                    title: 'Fake OHLC data',
+                    title: 'Append data and progressive by mod',
                     option: option,
                     height: 550
                 });
 
+                return chart;
+
                 // chart && chart.on('brushSelected', renderBrushed);
 
                 // function renderBrushed(params) {

-- 
To stop receiving notification emails like this one, please contact
sushu...@apache.org.

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

Reply via email to