You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2020/04/29 19:54:01 UTC
[incubator-echarts] 01/02: fix: (1) revert increamental render
broken brought by a96d97191b28500d2a3dc4f44e53221d54fbe218 (2) add stream
test tools.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch next
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit 0802ef0a8ba2f7944fc1f1eca843bad3ecf328ca
Author: 100pah <su...@gmail.com>
AuthorDate: Wed Apr 29 23:26:04 2020 +0800
fix:
(1) revert increamental render broken brought by a96d97191b28500d2a3dc4f44e53221d54fbe218
(2) add stream test tools.
---
src/echarts.ts | 4 +-
test/-cases.js | 1 +
test/lib/reset.css | 14 ++++
test/lib/testHelper.js | 219 +++++++++++++++++++++++++++++++++++++++---------
test/stream-basic1.html | 163 +++++++++++++++++++++++++++++++++++
5 files changed, 360 insertions(+), 41 deletions(-)
diff --git a/src/echarts.ts b/src/echarts.ts
index d60e366..bb85b18 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -1654,7 +1654,9 @@ class ECharts extends Eventful {
unfinished |= +renderTask.perform(scheduler.getPerformArgs(renderTask));
chartView.group.silent = !!seriesModel.get('silent');
- chartView.group.markRedraw();
+ // Should not call markRedraw on group, because it will disable zrender
+ // increamental render (alway render from the __startIndex each frame)
+ // chartView.group.markRedraw();
updateZ(seriesModel, chartView);
diff --git a/test/-cases.js b/test/-cases.js
index 676b67f..9f5434f 100644
--- a/test/-cases.js
+++ b/test/-cases.js
@@ -53,6 +53,7 @@
}, {
name: 'stream-cases',
whiteList: [
+ 'stream-basic1.html',
'lines-ny-appendData.html',
'scatter-stream-large.html',
'scatter-stream-not-large.html',
diff --git a/test/lib/reset.css b/test/lib/reset.css
index 67e7b0d..fd34ca6 100644
--- a/test/lib/reset.css
+++ b/test/lib/reset.css
@@ -122,3 +122,17 @@ td.test-data-table-key {
width: 300px;
height: 500px;
}
+
+.control-frame-btn-panel {
+ position: fixed;
+ top: 10px;
+ left: 10px;
+ box-shadow: 0 0 3px #000;
+ background: green;
+ padding: 5px;
+}
+.control-frame-btn-panel .control-frame-info {
+ display: block;
+ color: #fff;
+ font-size: 10px;
+}
diff --git a/test/lib/testHelper.js b/test/lib/testHelper.js
index d6685d4..efbe103 100644
--- a/test/lib/testHelper.js
+++ b/test/lib/testHelper.js
@@ -147,44 +147,51 @@
infoContainer.innerHTML = createObjectHTML(opt.info, opt.infoKey || 'option');
}
- if (opt.recordCanvas) {
- recordCanvasContainer.innerHTML = ''
- + '<button>Show Canvas Record</button>'
- + '<button>Clear Canvas Record</button>'
- + '<div class="content-area"><textarea></textarea><br><button>Close</button></div>';
- var buttons = recordCanvasContainer.getElementsByTagName('button');
- var canvasRecordButton = buttons[0];
- var clearButton = buttons[1];
- var closeButton = buttons[2];
- var recordArea = recordCanvasContainer.getElementsByTagName('textarea')[0];
- var contentAraa = recordArea.parentNode;
- canvasRecordButton.addEventListener('click', function () {
- var content = [];
- eachCtx(function (zlevel, ctx) {
- content.push('Layer zlevel: ' + zlevel, '\n\n');
- if (typeof ctx.stack !== 'function') {
- alert('Missing: <script src="test/lib/canteen.js"></script>');
- return;
- }
- var stack = ctx.stack();
- for (var i = 0; i < stack.length; i++) {
- var line = stack[i];
- content.push(JSON.stringify(line), ',\n');
- }
- });
- contentAraa.style.display = 'block';
- recordArea.value = content.join('');
- });
- clearButton.addEventListener('click', function () {
- eachCtx(function (zlevel, ctx) {
- ctx.clear();
- });
- recordArea.value = 'Cleared.';
+ initRecordCanvas(opt, chart, recordCanvasContainer);
+
+ return chart;
+ };
+
+ function initRecordCanvas(opt, chart, recordCanvasContainer) {
+ if (!opt.recordCanvas) {
+ return;
+ }
+ recordCanvasContainer.innerHTML = ''
+ + '<button>Show Canvas Record</button>'
+ + '<button>Clear Canvas Record</button>'
+ + '<div class="content-area"><textarea></textarea><br><button>Close</button></div>';
+ var buttons = recordCanvasContainer.getElementsByTagName('button');
+ var canvasRecordButton = buttons[0];
+ var clearButton = buttons[1];
+ var closeButton = buttons[2];
+ var recordArea = recordCanvasContainer.getElementsByTagName('textarea')[0];
+ var contentAraa = recordArea.parentNode;
+ canvasRecordButton.addEventListener('click', function () {
+ var content = [];
+ eachCtx(function (zlevel, ctx) {
+ content.push('\nLayer zlevel: ' + zlevel, '\n\n');
+ if (typeof ctx.stack !== 'function') {
+ alert('Missing: <script src="test/lib/canteen.js"></script>');
+ return;
+ }
+ var stack = ctx.stack();
+ for (var i = 0; i < stack.length; i++) {
+ var line = stack[i];
+ content.push(JSON.stringify(line), ',\n');
+ }
});
- closeButton.addEventListener('click', function () {
- contentAraa.style.display = 'none';
+ contentAraa.style.display = 'block';
+ recordArea.value = content.join('');
+ });
+ clearButton.addEventListener('click', function () {
+ eachCtx(function (zlevel, ctx) {
+ ctx.clear();
});
- }
+ recordArea.value = 'Cleared.';
+ });
+ closeButton.addEventListener('click', function () {
+ contentAraa.style.display = 'none';
+ });
function eachCtx(cb) {
var layers = chart.getZr().painter.getLayers();
@@ -197,9 +204,7 @@
}
}
}
-
- return chart;
- };
+ }
/**
* @param {ECharts} echarts
@@ -257,6 +262,95 @@
};
+ var _dummyRequestAnimationFrameMounted = false;
+
+ /**
+ * Usage:
+ * ```js
+ * testHelper.controlFrame({pauseAt: 60});
+ * // Then load echarts.js (must after controlFrame called)
+ * ```
+ *
+ * @param {Object} [opt]
+ * @param {number} [opt.puaseAt] If specified `pauseAt`, auto pause at the frame.
+ * @param {Function} [opt.onFrame]
+ */
+ testHelper.controlFrame = function (opt) {
+ opt = opt || {};
+ var pauseAt = opt.pauseAt;
+ pauseAt == null && (pauseAt = 0);
+
+ var _running = true;
+ var _pendingCbList = [];
+ var _frameNumber = 0;
+ var _mounted = false;
+
+ var buttons = [{
+ text: 'run',
+ onclick: run
+ }, {
+ text: 'pause',
+ onclick: pause
+ }, {
+ text: 'next frame',
+ onclick: nextFrame
+ }];
+
+ var btnPanel = document.createElement('div');
+ btnPanel.className = 'control-frame-btn-panel'
+ var infoEl = document.createElement('div');
+ infoEl.className = 'control-frame-info';
+ btnPanel.appendChild(infoEl);
+ document.body.appendChild(btnPanel);
+ for (var i = 0; i < buttons.length; i++) {
+ var button = buttons[i];
+ var btnEl = document.createElement('button');
+ btnEl.innerHTML = button.text;
+ btnEl.addEventListener('click', button.onclick);
+ btnPanel.appendChild(btnEl);
+ }
+
+ if (_dummyRequestAnimationFrameMounted) {
+ throw new Error('Do not support `controlFrame` twice');
+ }
+ _dummyRequestAnimationFrameMounted = true;
+ var raf = window.requestAnimationFrame;
+ window.requestAnimationFrame = function (cb) {
+ _pendingCbList.push(cb);
+ if (_running && !_mounted) {
+ _mounted = true;
+ raf(nextFrame);
+ }
+ };
+
+ function run() {
+ _running = true;
+ nextFrame();
+ }
+
+ function pause() {
+ _running = false;
+ }
+
+ function nextFrame() {
+ opt.onFrame && opt.onFrame(_frameNumber);
+
+ infoEl.innerHTML = 'current frame: ' + _frameNumber;
+ if (pauseAt != null && _frameNumber === pauseAt) {
+ _running = false;
+ pauseAt = null;
+ }
+
+ _mounted = false;
+ var pending = _pendingCbList;
+ _pendingCbList = [];
+ for (var i = 0; i < pending.length; i++) {
+ pending[i]();
+ }
+ _frameNumber++;
+ }
+ }
+
testHelper.resizable = function (chart) {
var dom = chart.getDom();
var width = dom.clientWidth;
@@ -505,7 +599,6 @@
* For example: 'z2' or ['z2', 'style.fill', 'style.stroke']
* @param {function} [opt.filter] print a subtree only if any satisfied node exists.
* param: el, return: boolean
- * @param {boolean} [opt.preventPrint]
*/
testHelper.stringifyElements = function (chart, opt) {
if (!chart) {
@@ -602,6 +695,52 @@
console.log(elsStr);
};
+ /**
+ * Usage:
+ * ```js
+ * // Print all elements that has `style.text`:
+ * testHelper.retrieveElements(chart, {
+ * filter: el => el.style && el.style.text
+ * });
+ * ```
+ *
+ * @param {EChart} chart
+ * @param {Object} [opt]
+ * @param {function} [opt.filter] print a subtree only if any satisfied node exists.
+ * param: el, return: boolean
+ * @return {Array.<Element>}
+ */
+ testHelper.retrieveElements = function (chart, opt) {
+ if (!chart) {
+ return;
+ }
+ opt = opt || {};
+ var attrNameList = opt.attr;
+ if (getType(attrNameList) !== 'array') {
+ attrNameList = attrNameList ? [attrNameList] : [];
+ }
+
+ var zr = chart.getZr();
+ var roots = zr.storage.getRoots();
+ var result = [];
+
+ retrieve(roots);
+
+ function retrieve(elList) {
+ for (var i = 0; i < elList.length; i++) {
+ var el = elList[i];
+ if (!opt.filter || opt.filter(el)) {
+ result.push(el);
+ }
+ if (el.isGroup) {
+ retrieve(el.childrenRef());
+ }
+ }
+ }
+
+ return result;
+ };
+
// opt: {record: JSON, width: number, height: number}
testHelper.reproduceCanteen = function (opt) {
var canvas = document.createElement('canvas');
diff --git a/test/stream-basic1.html b/test/stream-basic1.html
new file mode 100644
index 0000000..bb74ee9
--- /dev/null
+++ b/test/stream-basic1.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+
+
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <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/canteen.js"></script>
+ <link rel="stylesheet" href="lib/reset.css" />
+ </head>
+ <body>
+ <style>
+ .record-title {
+ margin: 10px;
+ font-size: 18px;
+ font-weight: 700;
+ }
+ .record {
+ margin: 5px 20px;
+ }
+ .record-unit {
+ margin: 10px 10px;
+ font-size: 10px;
+ }
+ .record-unit .cmd-count {
+ color: red;
+ font-size: 12px;
+ }
+ .record-title .cmd-count {
+ color: red;
+ }
+ </style>
+
+
+
+ <div id="main0"></div>
+ <div class="record-title">
+ In incremental layer, each frame, <br>
+ new canvas command count (<span class="cmd-count">red number</span>) should be the same:</div>
+ <div id="record"></div>
+
+
+ <script>
+
+ window.Canteen.globals.STACK_SIZE = 100000000;
+
+ var recordContainer = document.getElementById('record');
+ var chart;
+ var layersInfoMap = {};
+
+ testHelper.controlFrame({
+ pauseAt: 120,
+ onFrame: function (frameNumber) {
+ if (chart) {
+ var layers = chart.getZr().painter.getLayers();
+ for (var zlevel in layers) {
+ if (layers.hasOwnProperty(zlevel)) {
+ printNewCmds(zlevel, layers[zlevel], frameNumber)
+ }
+ }
+ }
+ }
+ });
+
+ function printNewCmds(zlevel, layer, frameNumber) {
+ var layerInfo = layersInfoMap[zlevel];
+ if (!layerInfo) {
+ layerInfo = layersInfoMap[zlevel] = {
+ lastStackLength: 0,
+ recordDom: document.createElement('div')
+ };
+ layerInfo.recordDom.className = 'record-unit';
+ layerInfo.recordDom.innerHTML = 'layer ' + zlevel + ': <br>';
+ recordContainer.appendChild(layerInfo.recordDom);
+ }
+
+ var canvas = layer.dom;
+ var ctx = canvas.getContext('2d');
+ var stackLength = ctx.stack().length;
+ var span = document.createElement('span');
+ span.innerHTML = frameNumber + ':<span class="cmd-count">' + (stackLength - layerInfo.lastStackLength) + '</span> ';
+ layerInfo.recordDom.appendChild(span);
+ layerInfo.lastStackLength = stackLength;
+ }
+
+
+ require(['echarts'], function (echarts) {
+ var option;
+
+ var count = 5000;
+ var lineCount = 100;
+ var progressive = 50;
+ var data = [];
+ var yCurr = 5;
+ for (var i = 0; i < count; i++) {
+ var mod = i % lineCount;
+ if (mod === 0) {
+ yCurr += 5;
+ }
+ data.push([mod, yCurr]);
+ }
+
+ option = {
+ color: ['red'],
+ grid: {top: 20, bottom: 30},
+ xAxis: {
+ type: 'category',
+ axisLabel: {fontSize: 9, interval: 0, rotate: 90, margin: 20},
+ boundaryGap: false
+ },
+ yAxis: {
+ type: 'category',
+ axisLabel: {fontSize: 9, interval: 0},
+ boundaryGap: false
+ },
+ progressive: progressive,
+ progressiveThreshold: 1,
+ largeThreshold: 1,
+ series: {
+ type: 'scatter',
+ symbolSize: 2,
+ data: data
+ }
+ };
+
+ chart = testHelper.create(echarts, 'main0', {
+ title: [
+ 'Click **run** and check the printed records:',
+ ],
+ option: option,
+ height: 450,
+ recordCanvas: true
+ });
+ });
+ </script>
+
+
+ </body>
+</html>
+
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org