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/12/10 13:44:15 UTC
[incubator-echarts] 05/05: fix: when label animation is not
finished, start a new label animation,
the label should not jump the the last final value.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch fix/label-valueAnimation
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit ab9aa43e7b0f782c9c6febc12c9c7ecc11847d11
Author: 100pah <su...@gmail.com>
AuthorDate: Thu Dec 10 21:43:08 2020 +0800
fix: when label animation is not finished, start a new label animation, the label should not jump the the last final value.
---
src/label/labelStyle.ts | 17 +-
test/label-animation.html | 329 ++++++++++++++++++++----------
test/lib/testHelper.js | 25 ++-
test/line-endLabel.html | 87 +++++++-
test/runTest/actions/__meta__.json | 2 +
test/runTest/actions/label-animation.json | 1 +
test/runTest/actions/line-endLabel.json | 1 +
7 files changed, 344 insertions(+), 118 deletions(-)
diff --git a/src/label/labelStyle.ts b/src/label/labelStyle.ts
index 7934fe5..2a8caed 100644
--- a/src/label/labelStyle.ts
+++ b/src/label/labelStyle.ts
@@ -620,10 +620,14 @@ export const labelInner = makeInner<{
*/
prevValue?: ParsedValue | ParsedValue[]
/**
- * Current value stored used for label.
+ * Target value stored used for label.
*/
value?: ParsedValue | ParsedValue[]
/**
+ * Current value in text animation.
+ */
+ interpolatedValue?: ParsedValue | ParsedValue[]
+ /**
* If enable value animation
*/
valueAnimation?: boolean
@@ -657,7 +661,9 @@ export function setLabelValueAnimation(
}
const obj = labelInner(label);
- obj.prevValue = obj.value;
+ // Consider the case that being animating, do not use the `obj.value`,
+ // Otherwise it will jump to the `obj.value` when this new animation started.
+ obj.prevValue = retrieve2(obj.interpolatedValue, obj.value);
obj.value = value;
const normalLabelModel = labelStatesModels.normal;
@@ -693,6 +699,7 @@ export function animateLabelValue(
currentValue,
percent
);
+ labelInnerStore.interpolatedValue = percent === 1 ? null : interpolated;
const labelText = getLabelText({
labelDataIndex: dataIndex,
@@ -705,6 +712,8 @@ export function animateLabelValue(
setLabelText(textEl, labelText);
}
- (prevValue == null ? initProps
- : updateProps)(textEl, {}, seriesModel, dataIndex, null, during);
+ (prevValue == null
+ ? initProps
+ : updateProps
+ )(textEl, {}, seriesModel, dataIndex, null, during);
}
\ No newline at end of file
diff --git a/test/label-animation.html b/test/label-animation.html
index e9940e9..5a534d8 100644
--- a/test/label-animation.html
+++ b/test/label-animation.html
@@ -39,11 +39,13 @@ under the License.
<div id="main0"></div>
<div id="main1"></div>
+ <div id="main2"></div>
+
<script>
- function makeSource1() {
+ function makeSource0() {
return [
[ 'Int','Country', 'Float', 'Num'],
[900, 'Germany', 90.55, 0],
@@ -56,6 +58,17 @@ under the License.
[1200, 'France', 120.55, 3],
];
}
+ function makeSource1() {
+ return {
+ category: ['Germany', 'France'],
+ dataList: [
+ [900, 1900],
+ [300, 1300],
+ [800, 1800],
+ [200, 1200]
+ ]
+ };
+ }
</script>
@@ -67,6 +80,42 @@ under the License.
var option;
var currNum = 0;
+ var formatterConfigs = [
+ {
+ text: 'formatter: {c} 元',
+ formatter: '{c} 元'
+ },
+ {
+ text: 'formatter: {@[1]} {@[0]} 元',
+ formatter: '{@[1]} {@[0]} 元'
+ },
+ {
+ text: 'formatter: {@Country} {@Int} 元',
+ formatter: '{@Country} {@Int} 元'
+ },
+ {
+ text: 'formatter: callback',
+ formatter: function (params) {
+ return params.value.join(',') + ' 元';
+ }
+ }
+ ];
+ var formatterSwitchButtons = [];
+ for (var i = 0; i < formatterConfigs.length; i++) {
+ var config = formatterConfigs[i];
+ formatterSwitchButtons.push({
+ text: config.text,
+ onclick: (function (cfg) {
+ return function () {
+ currNum = 0;
+ var option = makeOption(cfg.formatter);
+ chart.__testHelper.updateInfo(cfg.formatter.toString(), 'formatter');
+ chart.setOption(option, { notMerge: true } );
+ };
+ })(config)
+ });
+ }
+
function makeTransformDataset() {
return {
id: 'singleA',
@@ -88,68 +137,57 @@ under the License.
};
}
- option = {
- animationDuration: 5000,
- animationDurationUpdate: 5000,
- dataset: [{
- source: makeSource1(),
- },
- makeTransformDataset()
- ],
- xAxis: {},
- yAxis: { type: 'category' },
- grid: {
- right: 160
- },
- series: [{
- type: 'bar',
- datasetId: 'singleA',
- encode: {
- x: 'Int',
- y: 'Country'
+ function makeOption(labelFormatter) {
+ return {
+ animationDuration: 3000,
+ animationDurationUpdate: 3000,
+ dataset: [{
+ source: makeSource0(),
},
- label: {
- show: true,
- position: 'right',
- fontSize: 16,
- formatter: '(StrFmt) {c} 元',
- valueAnimation: true
- }
- }, {
- type: 'bar',
- datasetId: 'singleA',
- encode: {
- x: 'Int',
- y: 'Country'
+ makeTransformDataset()
+ ],
+ xAxis: {},
+ yAxis: { type: 'category' },
+ grid: {
+ right: 160
},
- label: {
- show: true,
- position: 'right',
- fontSize: 16,
- formatter: function (params) {
- console.log(params);
- return '(CbFmt) ' + params.value.join(',') + ' 元';
+ series: [{
+ id: Math.random(),
+ type: 'bar',
+ datasetId: 'singleA',
+ encode: {
+ x: 'Int',
+ y: 'Country'
},
- valueAnimation: true
- }
- }]
- };
+ label: {
+ show: true,
+ position: 'right',
+ fontSize: 16,
+ formatter: labelFormatter,
+ valueAnimation: true
+ }
+ }]
+ };
+ }
var chart = testHelper.create(echarts, 'main0', {
title: [
- 'Check init and **click next once**',
- 'label text anmiation should OK. **except Country**',
- 'label should display like : "910,France,617.52,0 元"',
+ 'Check **init** valueAnimation should be OK',
+ 'Swithch formatter, for each formatter **click next once**',
+ 'label text anmiation should OK. **except Country**'
],
- option: option,
+ option: makeOption(formatterConfigs[0].formatter),
+ info: formatterConfigs[0].formatter.toString(),
+ infoKey: 'formatter',
buttons: [{
- text: 'next', onclick: function () {
+ text: 'next',
+ onclick: function () {
currNum++;
chart.setOption({
dataset: makeTransformDataset()
});
}
- }],
+ }].concat(formatterSwitchButtons)
});
});
</script>
@@ -162,92 +200,171 @@ under the License.
+
+
+
+
+
+
<script>
require(['echarts'/*, 'map/js/china' */], function (echarts) {
var option;
var currNum = 0;
- function makeTransformDataset() {
+ var formatterConfigs = [
+ {
+ text: 'formatter: {c} 元',
+ formatter: '{c} 元'
+ },
+ // { // not supportted in this case
+ // text: 'formatter: {@[1]} {@[0]} 元',
+ // formatter: '{@[1]} {@[0]} 元'
+ // },
+ {
+ text: 'formatter: callback',
+ formatter: function (params) {
+ return params.value + ' 元';
+ }
+ }
+ ];
+ var formatterSwitchButtons = [];
+ for (var i = 0; i < formatterConfigs.length; i++) {
+ var config = formatterConfigs[i];
+ formatterSwitchButtons.push({
+ text: config.text,
+ onclick: (function (cfg) {
+ return function () {
+ currNum = 0;
+ var option = makeOption(cfg.formatter);
+ chart.__testHelper.updateInfo(cfg.formatter.toString(), 'formatter');
+ chart.setOption(option, { notMerge: true } );
+ };
+ })(config)
+ });
+ }
+
+ var source1 = makeSource1();
+
+ function makeOption(labelFormatter) {
return {
- id: 'singleA',
- transform: {
- type: 'filter',
- print: true,
- config: {
- and: [{
- or: [{
- dimension: 'Country', eq: 'Germany'
- }, {
- dimension: 'Country', eq: 'France'
- }]
- }, {
- dimension: 'Num', eq: currNum
- }]
+ animationDuration: 3000,
+ animationDurationUpdate: 3000,
+ xAxis: {},
+ yAxis: {
+ type: 'category',
+ data: source1.category
+ },
+ grid: {
+ right: 160
+ },
+ series: [{
+ id: Math.random(),
+ type: 'bar',
+ data: source1.dataList[currNum],
+ label: {
+ show: true,
+ position: 'right',
+ fontSize: 16,
+ formatter: labelFormatter,
+ valueAnimation: true
}
- }
+ }]
};
}
- option = {
+ var chart = testHelper.create(echarts, 'main1', {
+ title: [
+ 'Check **init** valueAnimation should be OK',
+ 'Swithch formatter, for each formatter **click next once**',
+ 'label text anmiation should OK. **except Country**'
+ ],
+ option: makeOption(formatterConfigs[0].formatter),
+ info: formatterConfigs[0].formatter.toString(),
+ infoKey: 'formatter',
+ buttons: [{
+ text: 'next',
+ onclick: function () {
+ currNum++;
+ chart.setOption({
+ series: {
+ data: source1.dataList[currNum]
+ }
+ });
+ }
+ }].concat(formatterSwitchButtons)
+ });
+ });
+ </script>
+
+
+
+
+
+
+
+
+
+ <script>
+ require(['echarts'/*, 'map/js/china' */], function (echarts) {
+ var valueA = 100;
+ var valueB = 200;
+
+ var option = {
animationDuration: 5000,
animationDurationUpdate: 5000,
- dataset: [{
- source: makeSource1(),
- },
- makeTransformDataset()
- ],
+ animationEasing: 'linear',
+ animationEasingUpdate: 'linear',
xAxis: {},
- yAxis: { type: 'category' },
+ yAxis: {
+ type: 'category',
+ data: ['A', 'B']
+ },
grid: {
right: 160
},
series: [{
type: 'bar',
- datasetId: 'singleA',
- encode: {
- x: 'Int',
- y: 'Country'
- },
- label: {
- show: true,
- position: 'right',
- fontSize: 16,
- formatter: '(StrFmt1) {@Country} {@Int} 元',
- valueAnimation: true
- }
- }, {
- type: 'bar',
- datasetId: 'singleA',
- encode: {
- x: 'Int',
- y: 'Country'
- },
+ data: [valueA, valueB],
label: {
show: true,
position: 'right',
fontSize: 16,
- formatter: '(StrFmt2) {@[1]} {@[0]} 元',
+ formatter: '{c} ton',
valueAnimation: true
}
}]
};
- var chart = testHelper.create(echarts, 'main1', {
+ function updateChart() {
+ chart.setOption({
+ series: [{
+ data: [valueA, valueB]
+ }]
+ });
+ }
+
+ var chart = testHelper.create(echarts, 'main2', {
title: [
- 'Check init and **click next once**',
- 'label text anmiation should OK. **except Country**',
- 'label should display like : "France 910 元"',
+ 'Check A++ **before value animation finished**.',
+ 'B should keep on label animation, rather than jump to the final label.',
+ 'B should finally reach at 200. A should finally reach at 600'
],
option: option,
buttons: [{
- text: 'next', onclick: function () {
- currNum++;
- chart.setOption({
- dataset: makeTransformDataset()
- });
+ text: 'A++',
+ onclick: function () {
+ valueA += 500;
+ updateChart();
+ }
+ }, {
+ text: 'B++',
+ onclick: function () {
+ valueB += 500;
+ updateChart();
}
- }],
+ }]
});
+
});
</script>
@@ -256,12 +373,6 @@ under the License.
-
-
-
-
-
-
</body>
</html>
diff --git a/test/lib/testHelper.js b/test/lib/testHelper.js
index 88dc879..be1d491 100644
--- a/test/lib/testHelper.js
+++ b/test/lib/testHelper.js
@@ -144,11 +144,19 @@
}
if (opt.info) {
- infoContainer.innerHTML = createObjectHTML(opt.info, opt.infoKey || 'option');
+ updateInfo(opt.info, opt.infoKey);
+ }
+
+ function updateInfo(info, infoKey) {
+ infoContainer.innerHTML = createObjectHTML(info, infoKey || 'option');
}
initRecordCanvas(opt, chart, recordCanvasContainer);
+ chart.__testHelper = {
+ updateInfo: updateInfo
+ };
+
return chart;
};
@@ -932,9 +940,15 @@
}
function createObjectHTML(obj, key) {
+ var html = isObject(obj)
+ ? testHelper.encodeHTML(printObject(obj, key))
+ : obj
+ ? obj.toString()
+ : '';
+
return [
'<pre class="test-print-object">',
- testHelper.encodeHTML(printObject(obj, key)),
+ html,
'</pre>'
].join('');
}
@@ -977,6 +991,13 @@
return params ? params.split('&') : [];
}
+ function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ const type = typeof value;
+ return type === 'function' || (!!value && type === 'object');
+ }
+
context.testHelper = testHelper;
})(window);
\ No newline at end of file
diff --git a/test/line-endLabel.html b/test/line-endLabel.html
index b5826cb..3fcbd04 100644
--- a/test/line-endLabel.html
+++ b/test/line-endLabel.html
@@ -36,7 +36,90 @@ under the License.
height: 1000px;
margin-bottom: 30px;
}
+ #formatterSwitchButtons {
+ margin: 10px;
+ padding: 10px;
+ }
+ #currentFormatter {
+ margin: 10px;
+ padding: 10px;
+ border: 1px solid #aaa;
+ }
</style>
+
+ <div id="formatterSwitchButtons">
+ </div>
+ <div>
+ Current formatter:
+ <pre id="currentFormatter"></pre>
+ </div>
+
+ <script>
+ var _endLabelFormatter;
+
+ // Init formatter switch buttons.
+ (function () {
+
+ var formatterConfigs = [
+ {
+ text: 'formatter string {c}',
+ formatter: '$ {c}'
+ },
+ {
+ text: 'formatter string {@[dimIndex]}',
+ formatter: '$ {@[1]}'
+ },
+ {
+ text: 'formatter callback',
+ formatter: function (param) {
+ return '$ ' + param.value;
+ }
+ }
+ ];
+ var END_LABEL_FORMATTER = '__EC_TEST_line-endLabel.html_FOMRATTER___';
+
+ function setLocalStorage(formatterKey) {
+ window.localStorage.setItem(END_LABEL_FORMATTER, formatterKey);
+ }
+ function getLocalStorage() {
+ return window.localStorage.getItem(END_LABEL_FORMATTER);
+ }
+
+ var currFormatterKey = getLocalStorage();
+ var fmtBtnBox = document.getElementById('formatterSwitchButtons');
+ for (var i = 0; i < formatterConfigs.length; i++) {
+ var config = formatterConfigs[i];
+
+ if (_endLabelFormatter == null
+ && (
+ currFormatterKey == null
+ || currFormatterKey === config.text
+ )
+ ) {
+ _endLabelFormatter = config.formatter;
+ }
+
+ var btn = document.createElement('button');
+ btn.innerHTML = config.text;
+ btn.onclick = (function (cfg) {
+ return function () {
+ setLocalStorage(cfg.text);
+ location.reload();
+ };
+ })(config);
+ fmtBtnBox.appendChild(btn);
+ }
+
+ if (!_endLabelFormatter) {
+ throw new Error();
+ }
+ var formatterDisplayBox = document.getElementById('currentFormatter');
+ formatterDisplayBox.innerHTML = _endLabelFormatter.toString();
+ })();
+
+ </script>
+
+
<div id="main0"></div>
<div id="main1"></div>
<script>
@@ -200,9 +283,7 @@ under the License.
},
endLabel: {
show: true,
- formatter: function (param) {
- return '$' + param.value;
- },
+ formatter: _endLabelFormatter,
fontSize: 14
},
emphasis: {
diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json
index 663ac84..f6eb460 100644
--- a/test/runTest/actions/__meta__.json
+++ b/test/runTest/actions/__meta__.json
@@ -91,6 +91,7 @@
"hoverFocus2": 2,
"hoverStyle": 14,
"hoverStyle2": 1,
+ "label-animation": 3,
"label-layout": 1,
"label-position": 1,
"largeLine-tooltip": 1,
@@ -100,6 +101,7 @@
"line-animation": 1,
"line-boldWhenHover": 1,
"line-crash": 1,
+ "line-endLabel": 1,
"map": 3,
"map-contour": 2,
"map-default": 1,
diff --git a/test/runTest/actions/label-animation.json b/test/runTest/actions/label-animation.json
new file mode 100644
index 0000000..045bf8a
--- /dev/null
+++ b/test/runTest/actions/label-animation.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":476,"x":107,"y":131},{"type":"mousemove","time":676,"x":107,"y":118},{"type":"mousedown","time":820,"x":108,"y":115},{"type":"mousemove","time":885,"x":108,"y":115},{"type":"mouseup","time":952,"x":108,"y":115},{"time":953,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":3025,"x":105,"y":115},{"type":"mousemove","time":3225,"x":31,"y":128},{"type":"mousemove","time":3425,"x":20,"y":126},{"type":"mousemove","time":3633, [...]
\ No newline at end of file
diff --git a/test/runTest/actions/line-endLabel.json b/test/runTest/actions/line-endLabel.json
new file mode 100644
index 0000000..712dc3e
--- /dev/null
+++ b/test/runTest/actions/line-endLabel.json
@@ -0,0 +1 @@
+[{"name":"Action 1","ops":[{"type":"mousemove","time":732,"x":86,"y":167},{"type":"mousemove","time":932,"x":85,"y":126},{"type":"mousemove","time":1132,"x":85,"y":63},{"type":"mousemove","time":1339,"x":94,"y":30},{"type":"mousemove","time":1556,"x":95,"y":28},{"type":"mousedown","time":1764,"x":95,"y":28},{"type":"mouseup","time":1928,"x":95,"y":28},{"time":1929,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":4451,"x":96,"y":28},{"type":"mousemove","time":4667,"x":135, [...]
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org