Skip to content

Commit 55de79f

Browse files
committed
feat: support expansion animation for data update; fix apache#11029
1 parent 129c334 commit 55de79f

File tree

3 files changed

+227
-25
lines changed

3 files changed

+227
-25
lines changed

src/chart/pie/PieSeries.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,12 @@ var PieSeries = echarts.extendSeriesModel({
170170
borderWidth: 1
171171
},
172172

173-
// Animation type canbe expansion, scale
173+
// Animation type. Valid values: expansion, scale
174174
animationType: 'expansion',
175175

176+
// Animation type when update. Valid values: transition, expansion
177+
animationTypeUpdate: 'transition',
178+
176179
animationEasing: 'cubicOut'
177180
}
178181
});

src/chart/pie/PieView.js

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
112112
var sectorShape = zrUtil.extend({}, layout);
113113
sectorShape.label = null;
114114

115+
var animationTypeUpdate = seriesModel.getShallow('animationTypeUpdate');
116+
115117
if (firstCreate) {
116118
sector.setShape(sectorShape);
117119

@@ -136,9 +138,15 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
136138

137139
}
138140
else {
139-
graphic.updateProps(sector, {
140-
shape: sectorShape
141-
}, seriesModel, idx);
141+
if (animationTypeUpdate === 'expansion') {
142+
// Sectors are set to be target shape and an overlaying clipPath is used for animation
143+
sector.setShape(sectorShape);
144+
} else {
145+
// Transition animation from the old shape
146+
graphic.updateProps(sector, {
147+
shape: sectorShape
148+
}, seriesModel, idx);
149+
}
142150
}
143151

144152
// Update common style
@@ -167,7 +175,9 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
167175
seriesModel.get('animation')
168176
);
169177

170-
this._updateLabel(data, idx);
178+
// Label and text animation should be applied only for transition type animation when update
179+
var withAnimation = !firstCreate && animationTypeUpdate === 'transition';
180+
this._updateLabel(data, idx, withAnimation);
171181

172182
this.highDownOnUpdate = (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled())
173183
? function (fromState, toState) {
@@ -201,7 +211,7 @@ piePieceProto.updateData = function (data, idx, firstCreate) {
201211
graphic.setHoverStyle(this);
202212
};
203213

204-
piePieceProto._updateLabel = function (data, idx) {
214+
piePieceProto._updateLabel = function (data, idx, withAnimation) {
205215

206216
var labelLine = this.childAt(1);
207217
var labelText = this.childAt(2);
@@ -218,20 +228,33 @@ piePieceProto._updateLabel = function (data, idx) {
218228
return;
219229
}
220230

221-
graphic.updateProps(labelLine, {
222-
shape: {
223-
points: labelLayout.linePoints || [
224-
[labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]
225-
]
226-
}
227-
}, seriesModel, idx);
231+
var targetLineShape = {
232+
points: labelLayout.linePoints || [
233+
[labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]
234+
]
235+
};
236+
var targetTextStyle = {
237+
x: labelLayout.x,
238+
y: labelLayout.y
239+
};
240+
if (withAnimation) {
241+
graphic.updateProps(labelLine, {
242+
shape: targetLineShape
243+
}, seriesModel, idx);
244+
245+
graphic.updateProps(labelText, {
246+
style: targetTextStyle
247+
}, seriesModel, idx);
248+
}
249+
else {
250+
labelLine.attr({
251+
shape: targetLineShape
252+
});
253+
labelText.attr({
254+
style: targetTextStyle
255+
});
256+
}
228257

229-
graphic.updateProps(labelText, {
230-
style: {
231-
x: labelLayout.x,
232-
y: labelLayout.y
233-
}
234-
}, seriesModel, idx);
235258
labelText.attr({
236259
rotation: labelLayout.rotation,
237260
origin: [labelLayout.x, labelLayout.y],
@@ -309,6 +332,7 @@ var PieView = ChartView.extend({
309332
var hasAnimation = ecModel.get('animation');
310333
var isFirstRender = !oldData;
311334
var animationType = seriesModel.get('animationType');
335+
var animationTypeUpdate = seriesModel.get('animationTypeUpdate');
312336

313337
var onSectorClick = zrUtil.curry(
314338
updateDataSelected, this.uid, seriesModel, hasAnimation, api
@@ -334,6 +358,12 @@ var PieView = ChartView.extend({
334358
.update(function (newIdx, oldIdx) {
335359
var piePiece = oldData.getItemGraphicEl(oldIdx);
336360

361+
if (!isFirstRender && animationTypeUpdate !== 'transition') {
362+
piePiece.eachChild(function (child) {
363+
child.stopAnimation(true);
364+
});
365+
}
366+
337367
piePiece.updateData(data, newIdx);
338368

339369
piePiece.off('click');
@@ -348,9 +378,8 @@ var PieView = ChartView.extend({
348378
.execute();
349379

350380
if (
351-
hasAnimation && isFirstRender && data.count() > 0
352-
// Default expansion animation
353-
&& animationType !== 'scale'
381+
hasAnimation && data.count() > 0
382+
&& (isFirstRender ? animationType !== 'scale' : animationTypeUpdate !== 'transition')
354383
) {
355384
var shape = data.getItemLayout(0);
356385
for (var s = 1; isNaN(shape.startAngle) && s < data.count(); ++s) {
@@ -361,7 +390,7 @@ var PieView = ChartView.extend({
361390

362391
var removeClipPath = zrUtil.bind(group.removeClipPath, group);
363392
group.setClipPath(this._createClipPath(
364-
shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel
393+
shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel, isFirstRender
365394
));
366395
}
367396
else {
@@ -375,7 +404,7 @@ var PieView = ChartView.extend({
375404
dispose: function () {},
376405

377406
_createClipPath: function (
378-
cx, cy, r, startAngle, clockwise, cb, seriesModel
407+
cx, cy, r, startAngle, clockwise, cb, seriesModel, isFirstRender
379408
) {
380409
var clipPath = new graphic.Sector({
381410
shape: {
@@ -389,7 +418,8 @@ var PieView = ChartView.extend({
389418
}
390419
});
391420

392-
graphic.initProps(clipPath, {
421+
var initOrUpdate = isFirstRender ? graphic.initProps : graphic.updateProps;
422+
initOrUpdate(clipPath, {
393423
shape: {
394424
endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
395425
}

test/pie-animation.html

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
<html>
21+
22+
<head>
23+
<meta charset="utf-8">
24+
<script src="lib/esl.js"></script>
25+
<script src="lib/config.js"></script>
26+
<meta name="viewport" content="width=device-width, initial-scale=1" />
27+
</head>
28+
29+
<body>
30+
<style>
31+
html,
32+
body,
33+
#main1,
34+
#main2 {
35+
width: 100%;
36+
height: 250px;
37+
margin: 0;
38+
}
39+
40+
.test-title {
41+
background: #146402;
42+
padding: 10px;
43+
color: #fff;
44+
}
45+
46+
button {
47+
padding: 10px 20px;
48+
margin: 10px;
49+
}
50+
</style>
51+
52+
<div class="test-title">Animation: Transition from previous state to new state, in 10 seconds after clicking Go</div>
53+
<button id="btn1">Go</button>
54+
<div id="main1"></div>
55+
56+
<div class="test-title">Animation: Transition all over again, in 10 seconds after clicking Go</div>
57+
<button id="btn2">Go</button>
58+
<div id="main2"></div>
59+
60+
<script>
61+
62+
require([
63+
'echarts'
64+
], function (echarts) {
65+
66+
67+
var chart = echarts.init(
68+
document.getElementById('main1'),
69+
null,
70+
{
71+
renderer: 'svg'
72+
}
73+
);
74+
var data = [
75+
{"name": "a1", "value": 92386},
76+
{"name": "b1", "value": 90611},
77+
{"name": "c1", "value": 12596},
78+
{"name": "d1", "value": 9438},
79+
{"name": "e1", "value": 10049}
80+
];
81+
var data2 = [
82+
{"name": "a1", "value": 120},
83+
{"name": "b1", "value": 200},
84+
{"name": "c1", "value": 300},
85+
{"name": "x1", "value": 20},
86+
{"name": "y1", "value": 30}
87+
];
88+
89+
var option = {
90+
series: [{
91+
type: 'pie',
92+
animationDuration: 1000,
93+
animationDurationUpdate: 10000,
94+
startAngle: 0,
95+
endAngle: 360,
96+
radius: ['50%', '80%'],
97+
center: ['40%', '50%'],
98+
data: data
99+
}]
100+
};
101+
chart.setOption(option);
102+
103+
document.getElementById('btn1').addEventListener('click', function () {
104+
option.series[0].data = data2;
105+
chart.setOption(option, true);
106+
});
107+
});
108+
109+
</script>
110+
111+
112+
113+
114+
115+
<script>
116+
117+
require([
118+
'echarts'
119+
], function (echarts) {
120+
121+
122+
var chart = echarts.init(
123+
document.getElementById('main2'),
124+
null,
125+
{
126+
renderer: 'svg'
127+
}
128+
);
129+
var data = [
130+
{"name": "a1", "value": 92386},
131+
{"name": "b1", "value": 90611},
132+
{"name": "c1", "value": 12596},
133+
{"name": "d1", "value": 9438},
134+
{"name": "e1", "value": 10049}
135+
];
136+
var data2 = [
137+
{"name": "a1", "value": 120},
138+
{"name": "b1", "value": 200},
139+
{"name": "c1", "value": 300},
140+
{"name": "x1", "value": 20},
141+
{"name": "y1", "value": 30}
142+
];
143+
144+
var option = {
145+
series: [{
146+
type: 'pie',
147+
animationType: 'expansion',
148+
animationDuration: 1000,
149+
animationDurationUpdate: 10000,
150+
animationTypeUpdate: 'expansion',
151+
startAngle: 0,
152+
endAngle: 360,
153+
radius: ['50%', '80%'],
154+
center: ['40%', '50%'],
155+
data: data
156+
}]
157+
};
158+
chart.setOption(option);
159+
160+
document.getElementById('btn2').addEventListener('click', function () {
161+
option.series[0].data = data2;
162+
chart.setOption(option, true);
163+
});
164+
});
165+
166+
</script>
167+
</body>
168+
169+
</html>

0 commit comments

Comments
 (0)