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/06/08 14:22:59 UTC
[incubator-echarts] 02/03: feature: custom series during callback
params re-design.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch custom-series-enhance
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit 6c227d3ab5bc01a21d40b0827fbd623e80b85fc4
Author: 100pah <su...@gmail.com>
AuthorDate: Mon Jun 8 12:28:59 2020 +0800
feature: custom series during callback params re-design.
---
src/chart/custom.ts | 110 ++++++++++++++++++++++++--------------------
test/custom-transition.html | 63 +++++++++++++++----------
2 files changed, 97 insertions(+), 76 deletions(-)
diff --git a/src/chart/custom.ts b/src/chart/custom.ts
index b35f55b..9125b97 100644
--- a/src/chart/custom.ts
+++ b/src/chart/custom.ts
@@ -103,6 +103,7 @@ const TRANSFORM_PROPS = {
rotation: 1
} as const;
type TransformProps = keyof typeof TRANSFORM_PROPS;
+const transformPropNamesStr = keys(TRANSFORM_PROPS).join(', ');
type TransitionAnyProps = string | string[];
type TransitionTransformProps = TransformProps | TransformProps[];
@@ -134,7 +135,7 @@ interface CustomBaseElementOption extends Partial<Pick<
// Shape can be set in any el option for custom prop for annimation duration.
shape?: TransitionAnyOption;
// updateDuringAnimation
- during?(elProps: CustomDuringElProps): void;
+ during?(params: typeof customDuringAPI): void;
};
interface CustomDisplayableOption extends CustomBaseElementOption, Partial<Pick<
Displayable, 'zlevel' | 'z' | 'z2' | 'invisible'
@@ -162,10 +163,6 @@ interface CustomGroupOption extends CustomBaseElementOption {
interface CustomZRPathOption extends CustomDisplayableOption {
shape?: PathProps['shape'] & TransitionAnyOption;
}
-interface CustomDuringElProps extends Partial<Pick<Element, TransformProps>> {
- shape?: PathProps['shape'];
- style?: { text: string };
-}
interface CustomSVGPathOption extends CustomDisplayableOption {
type: 'path';
shape?: {
@@ -319,9 +316,6 @@ const Z2_SPECIFIED_BIT = {
emphasis: 1
} as const;
-const tmpDuringStyle = {} as CustomDuringElProps['style'];
-const tmpDuringElProps = {} as CustomDuringElProps;
-
const LEGACY_TRANSFORM_PROPS = {
position: ['x', 'y'],
scale: ['scaleX', 'scaleY'],
@@ -931,54 +925,68 @@ function getOrCreateLeaveToPropsFromEl(el: Element): LooseElementProps {
return innerEl.leaveToProps || (innerEl.leaveToProps = {});
}
+// Use it to avoid it be exposed to user.
+const tmpDuringScope = {} as {
+ el: Element;
+ isShapeDirty: boolean;
+ isStyleDirty: boolean;
+};
+const customDuringAPI = {
+ // Usually other props do not need to be changed in animation during.
+ setAttr(key: TransformProps, val: unknown): void {
+ assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `setAttr`.');
+ tmpDuringScope.el[key] = val as number;
+ },
+ getAttr(key: TransformProps): unknown {
+ assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `getAttr`.');
+ return tmpDuringScope.el[key];
+ },
+ setShape(key: string, val: unknown): void {
+ // In custom series, el other than Path can also has `shape` for intepolating props.
+ const shape = (tmpDuringScope.el as any).shape || ((tmpDuringScope.el as any).shape = {});
+ shape[key] = val;
+ tmpDuringScope.isShapeDirty = true;
+ },
+ getShape(key: string): unknown {
+ const shape = (tmpDuringScope.el as any).shape;
+ if (shape) {
+ return shape[key];
+ }
+ },
+ setStyle(key: string, val: unknown): void {
+ const style = (tmpDuringScope.el as Displayable).style;
+ if (style) {
+ style[key] = val;
+ tmpDuringScope.isStyleDirty = true;
+ }
+ },
+ getStyle(key: string): unknown {
+ const style = (tmpDuringScope.el as Displayable).style;
+ if (style) {
+ return style[key];
+ }
+ }
+};
+
function elUpdateDuringAnimation(this: Element, key: string): void {
const innerEl = inner(this);
// FIXME `this.markRedraw();` directly ?
innerEl.orginalDuring.call(this, key);
const customDuring = innerEl.customDuring;
- const thisPath = this as graphicUtil.Path;
- const thisText = this as graphicUtil.Text;
- let dirtyStyle = false;
-
- // 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.
- const shapeCurr = tmpDuringElProps.shape = thisPath.shape;
- const xCurr = tmpDuringElProps.x = this.x;
- const yCurr = tmpDuringElProps.y = this.y;
- const scaleXCurr = tmpDuringElProps.scaleX = this.scaleX;
- const scaleYCurr = tmpDuringElProps.scaleY = this.scaleY;
- const originXCurr = tmpDuringElProps.originX = this.originX;
- const originYCurr = tmpDuringElProps.originY = this.originY;
- const rotationCurr = tmpDuringElProps.rotation = this.rotation;
-
- // PENDING:
- // Do not expose other style in case that is not stable.
- const isText = this.type === 'text';
- // Always assign in case that user modify `.style`.
- tmpDuringElProps.style = tmpDuringStyle;
- const textCurr = tmpDuringStyle.text = isText ? thisText.style.text : null;
-
- customDuring(tmpDuringElProps);
-
- tmpDuringElProps.shape !== shapeCurr && (thisPath.shape = tmpDuringElProps.shape);
- // Consider prop on prototype.
- tmpDuringElProps.x !== xCurr && (this.x = tmpDuringElProps.x);
- tmpDuringElProps.y !== yCurr && (this.y = tmpDuringElProps.y);
- tmpDuringElProps.scaleX !== scaleXCurr && (this.scaleX = tmpDuringElProps.scaleX);
- tmpDuringElProps.scaleY !== scaleYCurr && (this.scaleY = tmpDuringElProps.scaleY);
- tmpDuringElProps.originX !== originXCurr && (this.originX = tmpDuringElProps.originX);
- tmpDuringElProps.originY !== originYCurr && (this.originY = tmpDuringElProps.originY);
- tmpDuringElProps.rotation !== rotationCurr && (this.rotation = tmpDuringElProps.rotation);
-
- if (isText) {
- const currTmpStl = tmpDuringElProps.style; // Allow user modify `.style`.
- currTmpStl && currTmpStl.text !== textCurr && (thisText.style.text = currTmpStl.text, dirtyStyle = true);
- }
-
- dirtyStyle && this.dirty();
- // markRedraw() will be called by default.
+
+ tmpDuringScope.el = this;
+ tmpDuringScope.isShapeDirty = false;
+ tmpDuringScope.isStyleDirty = false;
+
+ customDuring(customDuringAPI);
+
+ if (tmpDuringScope.isShapeDirty && (this as graphicUtil.Path).dirtyShape) {
+ (this as graphicUtil.Path).dirtyShape();
+ }
+ if (tmpDuringScope.isStyleDirty && (this as Displayable).dirtyStyle) {
+ (this as Displayable).dirtyStyle();
+ }
+ // markRedraw() will be called by default in during.
// FIXME: if in future meet the case that some prop will be both modified in `during` and `state`,
// consider the issue that the prop might be incorrect when return to "normal" state.
diff --git a/test/custom-transition.html b/test/custom-transition.html
index 2d0f762..a51d31d 100644
--- a/test/custom-transition.html
+++ b/test/custom-transition.html
@@ -40,7 +40,7 @@ under the License.
<div id="spiral-fixed-extent"></div>
<div id="spiral-dynamic-extent"></div>
<div id="texture-bar-by-clipPath"></div>
- <div id="enter-animation"></div>
+ <div id="enter-animation-and-merge"></div>
<div id="enter-animation2"></div>
<div id="enter-animation-clipPath"></div>
<div id="style-animation"></div>
@@ -185,10 +185,10 @@ under the License.
fill: color.inner,
stroke: color.border
},
- during: function (elProps) {
- elProps.shape.points = makeShapePoints(
- api, valOnRadius, elProps.shape.valOnAngle
- );
+ during: function (apiDuring) {
+ apiDuring.setShape('points', makeShapePoints(
+ api, valOnRadius, apiDuring.getShape('valOnAngle')
+ ));
}
});
}
@@ -230,12 +230,12 @@ under the License.
verticalAlign: 'middle'
},
z2: 50,
- during: function (elProps) {
- var iValOnAngle = elProps.shape.valOnAngle;
+ during: function (apiDuring) {
+ var iValOnAngle = apiDuring.getShape('valOnAngle');
var point = makeLabelPosition(api, valOnRadius, iValOnAngle);
- elProps.x = point[0];
- elProps.y = point[1];
- elProps.style.text = getText(iValOnAngle);
+ apiDuring.setAttr('x', point[0]);
+ apiDuring.setAttr('y', point[1]);
+ apiDuring.setStyle('text', getText(iValOnAngle));
}
});
@@ -414,9 +414,13 @@ under the License.
fill: color.inner,
stroke: color.border
},
- during: function (elProps) {
- var shp = elProps.shape;
- shp.points = makeShapePoints(params, shp.widthRadius, shp.startRadius, shp.endRadian);
+ during: function (apiDuring) {
+ apiDuring.setShape('points', makeShapePoints(
+ params,
+ apiDuring.getShape('widthRadius'),
+ apiDuring.getShape('startRadius'),
+ apiDuring.getShape('endRadian')
+ ));
}
});
}
@@ -476,12 +480,17 @@ under the License.
}
},
z2: 50,
- during: function (elProps) {
- var shp = elProps.shape;
- var point = makeLabelPosition(params, shp.widthRadius, shp.startRadius, shp.endRadian);
- elProps.x = point[0];
- elProps.y = point[1];
- elProps.style.text = makeText(shp.endRadian);
+ during: function (apiDuring) {
+ var endRadian = apiDuring.getShape('endRadian');
+ var point = makeLabelPosition(
+ params,
+ apiDuring.getShape('widthRadius'),
+ apiDuring.getShape('startRadius'),
+ endRadian
+ );
+ apiDuring.setAttr('x', point[0]);
+ apiDuring.setAttr('y', point[1]);
+ apiDuring.setStyle('text', makeText(endRadian));
}
});
@@ -659,8 +668,11 @@ under the License.
$transition: 'polarEndRadian',
$enterFrom: { polarEndRadian: 0 }
},
- during: function (elProps) {
- elProps.shape.points = makePionterPoints(params, elProps.shape.polarEndRadian);
+ during: function (apiDuring) {
+ apiDuring.setShape(
+ 'points',
+ makePionterPoints(params, apiDuring.getShape('polarEndRadian'))
+ );
}
},
}, {
@@ -694,8 +706,8 @@ under the License.
verticalAlign: 'middle',
$enterFrom: { opacity: 0 }
},
- during: function (elProps) {
- elProps.style.text = makeText(elProps.shape.valOnRadian);
+ during: function (apiDuring) {
+ apiDuring.setStyle('text', makeText(apiDuring.getShape('valOnRadian')));
}
}]
};
@@ -852,11 +864,12 @@ under the License.
}]
};
- var chart = testHelper.create(echarts, 'enter-animation', {
+ var chart = testHelper.create(echarts, 'enter-animation-and-merge', {
title: [
'(1) Move dataZoom, position should have transition animation.',
'(2) Use dataZoom hide a data item, and then show it, ensure the **fade in** animation not be interupted.',
- '(3) click button to setOption merge.'
+ '(3) click button to setOption merge.',
+ '(4) Repeat (2), should be correct.'
],
height: 300,
option: option,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org