提交 c56e2dcd 编写于 作者: 1 100pah

feature: add duration animation for custom series.

上级 88c51a08
......@@ -84,6 +84,8 @@ const inner = makeInner<{
customImagePath: CustomImageOption['style']['image'];
customText: string;
txConZ2Set: number;
orginalDuring: Element['updateDuringAnimation'];
customDuring: CustomZRPathOption['during'];
}, Element>();
type CustomExtraElementInfo = Dictionary<unknown>;
......@@ -103,6 +105,8 @@ interface CustomBaseElementOption extends Partial<Pick<
info?: CustomExtraElementInfo;
// `false` means remove the textContent.
textContent?: CustomTextOption | false;
// updateDuringAnimation
during?(elProps: CustomDuringElProps): void;
};
interface CustomDisplayableOption extends CustomBaseElementOption, Partial<Pick<
Displayable, 'zlevel' | 'z' | 'z2' | 'invisible'
......@@ -128,6 +132,9 @@ interface CustomGroupOption extends CustomBaseElementOption {
}
interface CustomZRPathOption extends CustomDisplayableOption, Pick<PathProps, 'shape'> {
}
interface CustomDuringElProps extends Partial<Pick<Element, TransformProps>> {
shape?: PathProps['shape'];
}
interface CustomSVGPathOption extends CustomDisplayableOption {
type: 'path';
shape?: {
......@@ -277,7 +284,7 @@ const Z2_SPECIFIED_BIT = {
emphasis: 1
} as const;
const tmpDuringElProps = {} as CustomDuringElProps;
export type PrepareCustomInfo = (coordSys: CoordinateSystem) => {
......@@ -640,6 +647,19 @@ function updateElNormal(
zrUtil.hasOwn(elOption, 'silent') && (el.silent = elOption.silent);
zrUtil.hasOwn(elOption, 'ignore') && (el.ignore = elOption.ignore);
const customDuringMounted = el.updateDuringAnimation === elUpdateDuringAnimation;
if (elOption.during) {
const innerEl = inner(el);
if (!customDuringMounted) {
innerEl.orginalDuring = el.updateDuringAnimation;
el.updateDuringAnimation = elUpdateDuringAnimation;
}
innerEl.customDuring = elOption.during;
}
else if (customDuringMounted) {
el.updateDuringAnimation = inner(el).orginalDuring;
}
if (!isTextContent) {
// `elOption.info` enables user to mount some info on
// elements and use them in event handlers.
......@@ -650,6 +670,38 @@ function updateElNormal(
el.markRedraw();
}
function elUpdateDuringAnimation(this: graphicUtil.Path, key: string): void {
const innerEl = inner(this);
// FIXME `this.markRedraw();` directly ?
innerEl.orginalDuring.call(this, key);
const customDuring = innerEl.customDuring;
// Only provide these props. Usually other props do not need to be
// changed in animation during.
// Do not give `this` to user util really needed in future.
// Props in `shape` can be modified directly in the during callback.
tmpDuringElProps.shape = this.shape;
tmpDuringElProps.x = this.x;
tmpDuringElProps.y = this.y;
tmpDuringElProps.scaleX = this.scaleX;
tmpDuringElProps.scaleX = this.scaleY;
tmpDuringElProps.originX = this.originX;
tmpDuringElProps.originY = this.originY;
tmpDuringElProps.rotation = this.rotation;
customDuring(tmpDuringElProps);
tmpDuringElProps.shape !== this.shape && (this.shape = tmpDuringElProps.shape);
// Consider prop on prototype.
tmpDuringElProps.x !== this.x && (this.x = tmpDuringElProps.x);
tmpDuringElProps.y !== this.y && (this.y = tmpDuringElProps.y);
tmpDuringElProps.scaleX !== this.scaleX && (this.scaleX = tmpDuringElProps.scaleX);
tmpDuringElProps.scaleY !== this.scaleY && (this.scaleY = tmpDuringElProps.scaleY);
tmpDuringElProps.originX !== this.originX && (this.originX = tmpDuringElProps.originX);
tmpDuringElProps.originY !== this.originY && (this.originY = tmpDuringElProps.originY);
tmpDuringElProps.rotation !== this.rotation && (this.rotation = tmpDuringElProps.rotation);
}
function updateElOnState(
state: DisplayStateNonNormal,
el: Element,
......
......@@ -38,7 +38,10 @@ under the License.
<div id="main0"></div>
<div id="main2"></div>
<div id="main3"></div>
<!-- <div id="main1"></div> -->
<div id="init-animation-additive"></div>
<!-- <div id="spiral"></div> -->
<div id="spiral2"></div>
<div id="texture-bar"></div>
<script>
......@@ -365,6 +368,443 @@ under the License.
<script>
require(['echarts'], function (echarts) {
var animationDuration = 5000;
var animationDurationUpdate = 4000;
var option = {
xAxis: {},
yAxis: {},
dataZoom: [
{ type: 'slider' },
{ type: 'inside' }
],
animationDuration: animationDuration,
animationDurationUpdate: animationDurationUpdate,
series: [{
type: 'custom',
renderItem: function (params, api) {
return {
type: 'group',
position: api.coord([api.value(0), api.value(1)]),
children: [{
type: 'rect',
shape: {
x: -50,
y: 50,
width: 100,
height: 150,
r: 10
},
style: {
fill: 'rgba(102,241,98,0.9)'
}
}, {
type: 'circle',
shape: {
cx: -50,
cy: 50,
r: 30
},
style: {
fill: 'blue'
},
textContent: {
text: 'data',
style: {
fill: '#fff'
}
}
}]
};
},
data: [[121, 333], [29, 312]]
}]
};
var chart = testHelper.create(echarts, 'init-animation-additive', {
title: [
'Style merge:',
'(1) dataZoom hide a data item, and then show it, ensure the fade in animation normal.',
'(2) click button to setOption merge.'
],
option: option,
info: {
animationDuration: animationDuration,
animationDurationUpdate: animationDurationUpdate
},
buttons: [{
text: 'merge style: border become blue, but background not changed',
onclick: function () {
chart.setOption({
type: 'custom',
renderItem: function (params, api) {
return {
type: 'group',
children: [{
type: 'rect',
style: {
stroke: 'red',
lineWidth: 5
}
}]
};
}
});
}
}]
});
});
</script>
<!--
<script>
require([
'echarts'/*, 'map/js/china' */
], function (echarts) {
var animationDuration = 5000;
var animationDurationUpdate = 4000;
var angleLabel = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces'];
var angleRoundValue = angleLabel.length;
var radiusOffset = 10;
var angleStep = angleRoundValue / 90;
var barWidthValue = 0.4;
var radiusStep = 4;
var colors = {
'A': { stroke: 'green', fill: 'rgba(0,152,0,0.6)' },
'B': { stroke: 'red', fill: 'rgba(152,0,0,0.6)' },
'C': { stroke: 'blue', fill: 'rgba(0,0, 152,0.6)' },
};
var allData = [[
[[1, 3, 'A']],
[[2, 6, 'B']],
[[3, 9, 'C']],
], [
[[1, 12, 'A']],
[[2, 16, 'B']],
[[3, 14, 'C']],
], [
[[1, 17, 'A']],
[[2, 22, 'B']],
[[3, 19, 'C']],
]];
var currentDataIndex = 0;
function getMaxRadius() {
var radius = 0;
for (var j = 0; j < allData.length; j++) {
var data = allData[j];
for (var i = 0; i < data.length; i++) {
radius = Math.max(radius, getSpiralValueRadius(data[i][0][0], data[i][0][1]));
}
}
return Math.ceil(radius * 1.2);
}
function getSpiralValueRadius(valRadius, valAngle) {
return valRadius + radiusStep * (valAngle / angleRoundValue);
}
function renderItem(params, api) {
var valueRadius = api.value(0);
var valueAngle = api.value(1);
var points = [];
for (var iAngleVal = 0, end = valueAngle + angleStep; iAngleVal < end; iAngleVal += angleStep) {
iAngleVal > valueAngle && (iAngleVal = valueAngle);
var iRadiusVal = getSpiralValueRadius(valueRadius - barWidthValue, iAngleVal);
var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2);
points.push(point);
}
for (var iAngleVal = valueAngle; iAngleVal > -angleStep; iAngleVal -= angleStep) {
iAngleVal < 0 && (iAngleVal = 0);
var iRadiusVal = getSpiralValueRadius(valueRadius + barWidthValue, iAngleVal);
var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2);
points.push(point);
}
var name = api.value(2);
return {
type: 'polygon',
shape: { points: points },
style: {
lineWidth: 1,
fill: colors[name].fill,
stroke: colors[name].stroke
}
};
}
var option = {
animationDuration: animationDuration,
animationDurationUpdate: animationDurationUpdate,
angleAxis: {
type: 'value',
// splitLine: { show: false },
splitArea: {show: true},
axisLabel: {
formatter: function(val) {
return angleLabel[val];
},
color: 'rgba(0,0,0,0.2)'
},
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: angleRoundValue
},
radiusAxis: {
type: 'value',
splitLine: { show: false },
axisLabel: { color: 'rgba(0,0,0,0.2)' },
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: getMaxRadius()
},
polar: {
},
tooltip: {},
series: [{
type: 'custom',
name: 'A',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][0]
}, {
type: 'custom',
name: 'B',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][1]
}, {
type: 'custom',
name: 'C',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][2]
}]
};
var chart = testHelper.create(echarts, 'spiral', {
title: [
'animation: ',
],
option: option,
buttons: [{
text: 'next',
onclick: function () {
currentDataIndex++;
currentDataIndex >= allData.length && (currentDataIndex = 0);
chart.setOption({
series: [{
data: allData[currentDataIndex][0]
}, {
data: allData[currentDataIndex][1]
}, {
data: allData[currentDataIndex][2]
}]
})
}
}, {
text: 'enable animation',
onclick: function () {
chart.setOption({ animation: true });
}
}, {
text: 'disable animation',
onclick: function () {
chart.setOption({ animation: false });
}
}]
});
});
</script>
-->
<script>
require([
'echarts'/*, 'map/js/china' */
], function (echarts) {
var animationDuration = 5000;
var animationDurationUpdate = 4000;
var animationEasingUpdate = 'elasticOut';
var angleLabel = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces'];
var angleRoundValue = angleLabel.length;
var radiusOffset = 10;
var angleStep = angleRoundValue / 90;
var barWidthValue = 0.4;
var radiusStep = 4;
var colors = {
'A': { stroke: 'green', fill: 'rgba(0,152,0,0.6)' },
'B': { stroke: 'red', fill: 'rgba(152,0,0,0.6)' },
'C': { stroke: 'blue', fill: 'rgba(0,0, 152,0.6)' },
};
var allData = [[
[[1, 3, 'A']],
[[2, 6, 'B']],
[[3, 9, 'C']],
], [
[[1, 12, 'A']],
[[2, 16, 'B']],
[[3, 14, 'C']],
], [
[[1, 17, 'A']],
[[2, 22, 'B']],
[[3, 19, 'C']],
]];
var currentDataIndex = 0;
function getMaxRadius() {
var radius = 0;
for (var j = 0; j < allData.length; j++) {
var data = allData[j];
for (var i = 0; i < data.length; i++) {
radius = Math.max(radius, getSpiralValueRadius(data[i][0][0], data[i][0][1]));
}
}
return Math.ceil(radius * 1.2);
}
function getSpiralValueRadius(valRadius, valAngle) {
return valRadius + radiusStep * (valAngle / angleRoundValue);
}
function makeShapePoints(api, valueRadius, valueAngle) {
var points = [];
for (var iAngleVal = 0, end = valueAngle + angleStep; iAngleVal < end; iAngleVal += angleStep) {
iAngleVal > valueAngle && (iAngleVal = valueAngle);
var iRadiusVal = getSpiralValueRadius(valueRadius - barWidthValue, iAngleVal);
var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2);
points.push(point);
}
for (var iAngleVal = valueAngle; iAngleVal > -angleStep; iAngleVal -= angleStep) {
iAngleVal < 0 && (iAngleVal = 0);
var iRadiusVal = getSpiralValueRadius(valueRadius + barWidthValue, iAngleVal);
var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2);
points.push(point);
}
return points;
}
function renderItem(params, api) {
var valueRadius = api.value(0);
var valueAngle = api.value(1);
var name = api.value(2);
return {
type: 'polygon',
shape: {
points: makeShapePoints(api, valueRadius, valueAngle),
valueAngle: valueAngle
},
style: {
lineWidth: 1,
fill: colors[name].fill,
stroke: colors[name].stroke
},
during: function (elProps) {
elProps.shape.points = makeShapePoints(
api, valueRadius, elProps.shape.valueAngle
);
}
};
}
var option = {
animationDuration: animationDuration,
animationDurationUpdate: animationDurationUpdate,
animationEasingUpdate: animationEasingUpdate,
angleAxis: {
type: 'value',
// splitLine: { show: false },
splitArea: {show: true},
axisLabel: {
formatter: function(val) {
return angleLabel[val];
},
color: 'rgba(0,0,0,0.2)'
},
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: angleRoundValue
},
radiusAxis: {
type: 'value',
splitLine: { show: false },
axisLabel: { color: 'rgba(0,0,0,0.2)' },
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: getMaxRadius()
},
polar: {
},
tooltip: {},
series: [{
type: 'custom',
name: 'A',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][0]
}, {
type: 'custom',
name: 'B',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][1]
}, {
type: 'custom',
name: 'C',
coordinateSystem: 'polar',
renderItem: renderItem,
data: allData[currentDataIndex][2]
}]
};
var chart = testHelper.create(echarts, 'spiral2', {
title: [
'animation: ',
],
option: option,
buttons: [{
text: 'next',
onclick: function () {
currentDataIndex++;
currentDataIndex >= allData.length && (currentDataIndex = 0);
chart.setOption({
series: [{
data: allData[currentDataIndex][0]
}, {
data: allData[currentDataIndex][1]
}, {
data: allData[currentDataIndex][2]
}]
})
}
}, {
text: 'enable animation',
onclick: function () {
chart.setOption({ animation: true });
}
}, {
text: 'disable animation',
onclick: function () {
chart.setOption({ animation: false });
}
}]
});
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册