This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch graphic-animation
in repository https://gitbox.apache.org/repos/asf/echarts.git
The following commit(s) were added to refs/heads/graphic-animation by this push:
new 72ea7a6 feat(graphic): support clipPath
72ea7a6 is described below
commit 72ea7a6897d650a91f853fba82a22a279f23c150
Author: pissang <[email protected]>
AuthorDate: Fri Dec 10 20:48:38 2021 +0800
feat(graphic): support clipPath
---
src/animation/customGraphicKeyframeAnimation.ts | 19 +++++---
src/component/graphic/GraphicModel.ts | 9 +++-
src/component/graphic/GraphicView.ts | 65 ++++++++++++++++++++-----
src/util/model.ts | 5 +-
4 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/src/animation/customGraphicKeyframeAnimation.ts
b/src/animation/customGraphicKeyframeAnimation.ts
index a585313..0de270a 100644
--- a/src/animation/customGraphicKeyframeAnimation.ts
+++ b/src/animation/customGraphicKeyframeAnimation.ts
@@ -91,10 +91,21 @@ export function applyKeyframeAnimation<T extends
Record<string, any>>(
let animator: ReturnType<Element['animate']>;
let endFrameIsSet = false;
+
+ // Sort keyframes by percent.
+ keyframes.sort((a, b) => a.percent - b.percent);
+
each(keyframes, kf => {
// Stop current animation.
const animators = el.animators;
const kfValues = targetPropName ? kf[targetPropName] : kf;
+
+ if (__DEV__) {
+ if (kf.percent >= 1) {
+ endFrameIsSet = true;
+ }
+ }
+
if (!kfValues) {
return;
}
@@ -111,14 +122,8 @@ export function applyKeyframeAnimation<T extends
Record<string, any>>(
return;
}
- if (__DEV__) {
- if (kf.percent >= 1) {
- endFrameIsSet = true;
- }
- }
-
if (!animator) {
- animator = el.animate(targetPropName, animationOpts.loop);
+ animator = el.animate(targetPropName, animationOpts.loop,
true);
animator.scope = 'keyframe';
}
for (let i = 0; i < animators.length; i++) {
diff --git a/src/component/graphic/GraphicModel.ts
b/src/component/graphic/GraphicModel.ts
index bf619a1..5f32583 100644
--- a/src/component/graphic/GraphicModel.ts
+++ b/src/component/graphic/GraphicModel.ts
@@ -110,7 +110,11 @@ interface GraphicComponentBaseElementOption extends
*/
info?: GraphicExtraElementInfo;
- textContent?: GraphicComponentTextOption;
+
+ // `false` means remove the clipPath
+ clipPath?: Omit<GraphicComponentZRPathOption, 'clipPath'> | false;
+
+ textContent?: Omit<GraphicComponentTextOption, 'clipPath'>;
textConfig?: ElementTextConfig;
$action?: 'merge' | 'replace' | 'remove';
@@ -270,6 +274,9 @@ function mergeNewElOptionToExist(
copyTransitionInfo(newElOption, existElOption, 'shape');
copyTransitionInfo(newElOption, existElOption, 'style');
copyTransitionInfo(newElOption, existElOption, 'extra');
+
+ // Copy clipPath
+ newElOption.clipPath = existElOption.clipPath;
}
else {
existList[index] = newElOptCopy;
diff --git a/src/component/graphic/GraphicView.ts
b/src/component/graphic/GraphicView.ts
index 131a223..7dadea8 100644
--- a/src/component/graphic/GraphicView.ts
+++ b/src/component/graphic/GraphicView.ts
@@ -67,6 +67,7 @@ export const inner = modelUtil.makeInner<{
height: number;
isNew: boolean;
id: string;
+ type: string;
option: GraphicComponentElementOption
}, Element>();
// ------------------------
@@ -167,7 +168,9 @@ export class GraphicComponentView extends ComponentView {
}
const $action = elOption.$action || 'merge';
- if ($action === 'merge') {
+ const isMerge = $action === 'merge';
+ const isReplace = $action === 'replace';
+ if (isMerge) {
const isInit = !elExisting;
let el = elExisting;
if (isInit) {
@@ -188,7 +191,7 @@ export class GraphicComponentView extends ComponentView {
updateZ(el, elOption, globalZ, globalZLevel);
}
}
- else if ($action === 'replace') {
+ else if (isReplace) {
removeEl(elExisting, elOption, elMap, graphicModel);
const el = createEl(id, targetElParent, elOption.type, elMap);
if (el) {
@@ -209,18 +212,49 @@ export class GraphicComponentView extends ComponentView {
const el = elMap.get(id);
if (el && textContentOption) {
- if ($action === 'merge') {
+ if (isMerge) {
const textContentExisting = el.getTextContent();
textContentExisting
? textContentExisting.attr(textContentOption)
: el.setTextContent(new
graphicUtil.Text(textContentOption));
}
- else if ($action === 'replace') {
+ else if (isReplace) {
el.setTextContent(new graphicUtil.Text(textContentOption));
}
}
if (el) {
+ const clipPathOption = elOption.clipPath;
+ if (clipPathOption) {
+ const clipPathType = clipPathOption.type;
+ let clipPath: graphicUtil.Path;
+ let isInit = false;
+ if (isMerge) {
+ const oldClipPath = el.getClipPath();
+ isInit = !oldClipPath
+ || inner(oldClipPath).type !== clipPathType;
+ clipPath = isInit ? newEl(clipPathType) as
graphicUtil.Path : oldClipPath;
+ }
+ else if (isReplace) {
+ isInit = true;
+ clipPath = newEl(clipPathType) as graphicUtil.Path;
+ }
+
+ el.setClipPath(clipPath);
+
+ applyUpdateTransition(
+ clipPath,
+ clipPathOption,
+ graphicModel,
+ { isInit}
+ );
+ applyKeyframeAnimation(
+ clipPath,
+ clipPathOption.keyframeAnimation,
+ graphicModel
+ );
+ }
+
const elInner = inner(el);
el.setTextConfig(textConfig);
@@ -345,13 +379,8 @@ export class GraphicComponentView extends ComponentView {
this._clear();
}
}
-function createEl(
- id: string,
- targetElParent: graphicUtil.Group,
- graphicType: string,
- elMap: ElementMap
-): Element {
+function newEl(graphicType: string) {
if (__DEV__) {
zrUtil.assert(graphicType, 'graphic type MUST be set');
}
@@ -365,10 +394,22 @@ function createEl(
) as { new(opt: GraphicComponentElementOption): Element; };
if (__DEV__) {
- zrUtil.assert(Clz, 'graphic type can not be found');
+ zrUtil.assert(Clz, `graphic type ${graphicType} can not be found`);
}
const el = new Clz({});
+ inner(el).type = graphicType;
+ return el;
+}
+function createEl(
+ id: string,
+ targetElParent: graphicUtil.Group,
+ graphicType: string,
+ elMap: ElementMap
+): Element {
+
+ const el = newEl(graphicType);
+
targetElParent.add(el);
elMap.set(id, el);
inner(el).id = id;
@@ -413,7 +454,7 @@ function getCleanedElOption(
): Omit<GraphicComponentElementOption, 'textContent'> {
elOption = zrUtil.extend({}, elOption);
zrUtil.each(
- ['id', 'parentId', '$action', 'hv', 'bounding',
'textContent'].concat(layoutUtil.LOCATION_PARAMS),
+ ['id', 'parentId', '$action', 'hv', 'bounding', 'textContent',
'clipPath'].concat(layoutUtil.LOCATION_PARAMS),
function (name) {
delete (elOption as any)[name];
}
diff --git a/src/util/model.ts b/src/util/model.ts
index 9f78c15..2495723 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -51,9 +51,12 @@ import SeriesModel from '../model/Series';
import CartesianAxisModel from '../coord/cartesian/AxisModel';
import GridModel from '../coord/cartesian/GridModel';
import { isNumeric, getRandomIdBase, getPrecision, round } from './number';
-import { interpolateNumber } from 'zrender/src/animation/Animator';
import { warn } from './log';
+function interpolateNumber(p0: number, p1: number, percent: number): number {
+ return (p1 - p0) * percent + p0;
+}
+
/**
* Make the name displayable. But we should
* make sure it is not duplicated with user
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]