You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2021/06/30 10:21:58 UTC
[echarts] 02/02: fix(type): provide more accurate type of custom
series.
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch enhance-morph
in repository https://gitbox.apache.org/repos/asf/echarts.git
commit 69726733df3e5a6bcf10b663dfdf99cc0afe7fbc
Author: pissang <bm...@gmail.com>
AuthorDate: Wed Jun 30 18:20:31 2021 +0800
fix(type): provide more accurate type of custom series.
---
src/chart/custom/CustomSeries.ts | 134 ++++++++++++++++++++++++++++-----------
src/chart/custom/CustomView.ts | 77 +++++++++++++---------
src/chart/custom/prepare.ts | 3 +-
3 files changed, 146 insertions(+), 68 deletions(-)
diff --git a/src/chart/custom/CustomSeries.ts b/src/chart/custom/CustomSeries.ts
index 0c9d52b..c9e4d7d 100644
--- a/src/chart/custom/CustomSeries.ts
+++ b/src/chart/custom/CustomSeries.ts
@@ -20,13 +20,11 @@
import Displayable from 'zrender/src/graphic/Displayable';
import { ImageStyleProps } from 'zrender/src/graphic/Image';
import { PathProps, PathStyleProps } from 'zrender/src/graphic/Path';
-import { PatternObject } from 'zrender/src/graphic/Pattern';
import { ZRenderType } from 'zrender/src/zrender';
import { BarGridLayoutOptionForCustomSeries, BarGridLayoutResult } from '../../layout/barGrid';
import {
BlurScope,
CallbackDataParams,
- DecalObject,
Dictionary,
DimensionLoose,
ItemStyleOption,
@@ -52,6 +50,19 @@ import createListFromArray from '../helper/createListFromArray';
import { makeInner } from '../../util/model';
import { CoordinateSystem } from '../../coord/CoordinateSystem';
import SeriesModel from '../../model/Series';
+import {
+ Arc,
+ BezierCurve,
+ Circle,
+ CompoundPath,
+ Ellipse,
+ Line,
+ Polygon,
+ Polyline,
+ Rect,
+ Ring,
+ Sector
+} from '../../util/graphic';
export interface LooseElementProps extends ElementProps {
@@ -111,16 +122,21 @@ type ShapeMorphingOption = {
morph?: boolean
};
-export interface CustomDuringAPI {
+export interface CustomBaseDuringAPI {
// Usually other props do not need to be changed in animation during.
- setTransform(key: TransformProp, val: unknown): CustomDuringAPI
- getTransform(key: TransformProp): unknown;
- setShape(key: string, val: unknown): CustomDuringAPI;
- getShape(key: string): unknown;
- setStyle(key: string, val: unknown): CustomDuringAPI
- getStyle(key: string): unknown;
- setExtra(key: string, val: unknown): CustomDuringAPI
+ setTransform(key: TransformProp, val: number): this
+ getTransform(key: TransformProp): number;
+ setExtra(key: string, val: unknown): this
getExtra(key: string): unknown
+}
+export interface CustomDuringAPI<
+ StyleOpt extends object = object,
+ ShapeOpt extends object = object
+> extends CustomBaseDuringAPI {
+ setShape<T extends keyof ShapeOpt>(key: T, val: ShapeOpt[T]): this;
+ getShape<T extends keyof ShapeOpt>(key: T): ShapeOpt[T];
+ setStyle<T extends keyof StyleOpt>(key: T, val: StyleOpt[T]): this
+ getStyle<T extends keyof StyleOpt>(key: T): StyleOpt[T];
};
@@ -136,11 +152,11 @@ export interface CustomBaseElementOption extends Partial<Pick<
// `false` means remove the textContent.
textContent?: CustomTextOption | false;
// `false` means remove the clipPath
- clipPath?: CustomZRPathOption | false;
+ clipPath?: CustomBaseZRPathOption | false;
// `extra` can be set in any el option for custom prop for annimation duration.
- extra?: TransitionAnyOption;
+ extra?: Dictionary<any> & TransitionAnyOption;
// updateDuringAnimation
- during?(params: CustomDuringAPI): void;
+ during?(params: CustomBaseDuringAPI): void;
focus?: 'none' | 'self' | 'series' | ArrayLike<number>
blurScope?: BlurScope
@@ -149,6 +165,10 @@ export interface CustomDisplayableOption extends CustomBaseElementOption, Partia
Displayable, 'zlevel' | 'z' | 'z2' | 'invisible'
>> {
style?: ZRStyleProps & TransitionAnyOption;
+ during?(params: CustomDuringAPI): void;
+ /**
+ * @deprecated
+ */
// `false` means remove emphasis trigger.
styleEmphasis?: ZRStyleProps | false;
emphasis?: CustomDisplayableOptionOnState;
@@ -160,6 +180,9 @@ export interface CustomDisplayableOptionOnState extends Partial<Pick<
>> {
// `false` means remove emphasis trigger.
style?: (ZRStyleProps & TransitionAnyOption) | false;
+
+
+ during?(params: CustomDuringAPI): void;
}
export interface CustomGroupOption extends CustomBaseElementOption {
type: 'group';
@@ -167,32 +190,55 @@ export interface CustomGroupOption extends CustomBaseElementOption {
height?: number;
// @deprecated
diffChildrenByName?: boolean;
- // Can only set focus, blur on the root element.
- children: Omit<CustomElementOption, 'focus' | 'blurScope'>[];
+ children: CustomChildElementOption[];
$mergeChildren: false | 'byName' | 'byIndex';
}
-export interface CustomZRPathOption extends CustomDisplayableOption, ShapeMorphingOption {
+export interface CustomBaseZRPathOption<T extends PathProps['shape'] = PathProps['shape']>
+ extends CustomDisplayableOption, ShapeMorphingOption {
autoBatch?: boolean;
- shape?: PathProps['shape'] & TransitionAnyOption;
- style?: CustomDisplayableOption['style'] & {
- decal?: DecalObject;
- // Only internal usage. Any user specified value will be overwritten.
- __decalPattern?: PatternObject;
- };
+ shape?: T & TransitionAnyOption;
+ style?: PathProps['style']
+ during?(params: CustomDuringAPI<PathStyleProps, T>): void;
+}
+
+interface BuiltinShapes {
+ 'circle': Circle['shape']
+ 'rect': Rect['shape']
+ 'sector': Sector['shape']
+ 'poygon': Polygon['shape']
+ 'polyline': Polyline['shape']
+ 'line': Line['shape']
+ 'arc': Arc['shape']
+ 'bezierCurve': BezierCurve['shape']
+ 'ring': Ring['shape']
+ 'ellipse': Ellipse['shape'],
+ 'compoundPath': CompoundPath['shape']
+}
+
+export interface CustomBuitinPathOption<T extends keyof BuiltinShapes>
+ extends CustomBaseZRPathOption<BuiltinShapes[T]> {
+ type: T
}
-export interface CustomSVGPathOption extends CustomDisplayableOption, ShapeMorphingOption {
+export interface CustomSVGPathOption extends CustomBaseZRPathOption<CustomSVGPathShapeOption> {
type: 'path';
- shape?: {
- // SVG Path, like 'M0,0 L0,-20 L70,-1 L70,0 Z'
- pathData?: string;
- // "d" is the alias of `pathData` follows the SVG convention.
- d?: string;
- layout?: 'center' | 'cover';
- x?: number;
- y?: number;
- width?: number;
- height?: number;
- } & TransitionAnyOption;
+}
+
+type CreateCustomBuitinPathOption<T extends keyof BuiltinShapes> = T extends any
+ ? CustomBuitinPathOption<T> : never;
+
+export type CustomPathOption = CreateCustomBuitinPathOption<keyof BuiltinShapes>
+ | CustomSVGPathOption;
+
+interface CustomSVGPathShapeOption {
+ // SVG Path, like 'M0,0 L0,-20 L70,-1 L70,0 Z'
+ pathData?: string;
+ // "d" is the alias of `pathData` follows the SVG convention.
+ d?: string;
+ layout?: 'center' | 'cover';
+ x?: number;
+ y?: number;
+ width?: number;
+ height?: number;
}
export interface CustomImageOption extends CustomDisplayableOption {
type: 'image';
@@ -207,8 +253,17 @@ export interface CustomImageOptionOnState extends CustomDisplayableOptionOnState
export interface CustomTextOption extends CustomDisplayableOption {
type: 'text';
}
-export type CustomElementOption = CustomZRPathOption | CustomSVGPathOption | CustomImageOption | CustomTextOption;
-export type CustomElementOptionOnState = CustomDisplayableOptionOnState | CustomImageOptionOnState;
+
+export type CustomElementOption = CustomPathOption
+ | CustomImageOption
+ | CustomTextOption
+ | CustomGroupOption;
+
+// Can only set focus, blur on the root element.
+export type CustomChildElementOption = Omit<CustomElementOption, 'focus' | 'blurScope'>;
+
+export type CustomElementOptionOnState = CustomDisplayableOptionOnState
+ | CustomImageOptionOnState;
export interface CustomSeriesRenderItemAPI extends
CustomSeriesRenderItemCoordinateSystemAPI {
@@ -253,12 +308,17 @@ export type WrapEncodeDefRet = Dictionary<number[]>;
export interface CustomSeriesRenderItemParams {
context: Dictionary<unknown>;
+ dataIndex: number;
seriesId: string;
seriesName: string;
seriesIndex: number;
coordSys: CustomSeriesRenderItemParamsCoordSys;
- dataInsideLength: number;
encode: WrapEncodeDefRet;
+
+ dataIndexInside: number;
+ dataInsideLength: number;
+
+ actionType?: string;
}
type CustomSeriesRenderItem = (
params: CustomSeriesRenderItemParams,
diff --git a/src/chart/custom/CustomView.ts b/src/chart/custom/CustomView.ts
index ce5713a..44bc7ad 100644
--- a/src/chart/custom/CustomView.ts
+++ b/src/chart/custom/CustomView.ts
@@ -78,7 +78,7 @@ import CustomSeriesModel, {
CustomElementOption,
CustomElementOptionOnState,
CustomSVGPathOption,
- CustomZRPathOption,
+ CustomBaseZRPathOption,
CustomDisplayableOption,
CustomSeriesRenderItemAPI,
CustomSeriesRenderItemParams,
@@ -91,7 +91,8 @@ import CustomSeriesModel, {
NON_STYLE_VISUAL_PROPS,
customInnerStore,
LooseElementProps,
- PrepareCustomInfo
+ PrepareCustomInfo,
+ CustomPathOption
} from './CustomSeries';
import {
prepareShapeOrExtraAllPropsFinal,
@@ -100,6 +101,7 @@ import {
prepareTransformAllPropsFinal,
prepareTransformTransitionFrom
} from './prepare';
+import { PatternObject } from 'zrender/src/graphic/Pattern';
const transformPropNamesStr = keys(TRANSFORM_PROPS).join(', ');
@@ -363,6 +365,7 @@ function createEl(elOption: CustomElementOption): Element {
return el;
}
+
/**
* ----------------------------------------------------------
* [STRATEGY_MERGE] Merge properties or erase all properties:
@@ -415,6 +418,11 @@ function createEl(elOption: CustomElementOption): Element {
*
* @return if `isMorphTo`, return `allPropsFinal`.
*/
+
+interface InnerCustomZRPathOptionStyle extends PathStyleProps {
+ __decalPattern: PatternObject
+}
+
function updateElNormal(
// Can be null/undefined
api: ExtensionAPI,
@@ -435,7 +443,7 @@ function updateElNormal(
}
// Do some normalization on style.
- const styleOpt = elOption && elOption.style;
+ const styleOpt = elOption && (elOption as CustomDisplayableOption).style;
if (styleOpt) {
if (el.type === 'text') {
@@ -450,13 +458,13 @@ function updateElNormal(
}
let decalPattern;
- const decalObj = isPath(el) ? (styleOpt as CustomZRPathOption['style']).decal : null;
+ const decalObj = isPath(el) ? (styleOpt as CustomBaseZRPathOption['style']).decal : null;
if (api && decalObj) {
(decalObj as InnerDecalObject).dirty = true;
decalPattern = createOrUpdatePatternFromDecal(decalObj, api);
}
// Always overwrite in case user specify this prop.
- (styleOpt as CustomZRPathOption['style']).__decalPattern = decalPattern;
+ (styleOpt as InnerCustomZRPathOptionStyle).__decalPattern = decalPattern;
}
// Save the meta info for further morphing. Like apply on the sub morphing elements.
@@ -488,10 +496,10 @@ function applyMiscProps(
hasOwn(elOption, 'silent') && (el.silent = elOption.silent);
hasOwn(elOption, 'ignore') && (el.ignore = elOption.ignore);
if (isDisplayable(el)) {
- hasOwn(elOption, 'invisible') && (el.invisible = elOption.invisible);
+ hasOwn(elOption, 'invisible') && (el.invisible = (elOption as CustomDisplayableOption).invisible);
}
if (isPath(el)) {
- hasOwn(elOption, 'autoBatch') && (el.autoBatch = (elOption as CustomZRPathOption).autoBatch);
+ hasOwn(elOption, 'autoBatch') && (el.autoBatch = (elOption as CustomBaseZRPathOption).autoBatch);
}
if (!isTextContent) {
@@ -516,7 +524,7 @@ function applyPropsDirectly(
// Good for performance but bad for compatibility control.
elDisplayable.useStyle(styleOpt);
- const decalPattern = (styleOpt as CustomZRPathOption['style']).__decalPattern;
+ const decalPattern = (styleOpt as InnerCustomZRPathOptionStyle).__decalPattern;
if (decalPattern) {
elDisplayable.style.decal = decalPattern;
}
@@ -598,13 +606,13 @@ const customDuringAPI: CustomDuringAPI = {
tmpDuringScope.el[key] = val as number;
return this;
},
- getTransform(key: TransformProp): unknown {
+ getTransform(key: TransformProp): number {
if (__DEV__) {
assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.');
}
return tmpDuringScope.el[key];
},
- setShape(key: string, val: unknown) {
+ setShape(key: any, val: unknown) {
if (__DEV__) {
assertNotReserved(key);
}
@@ -614,7 +622,7 @@ const customDuringAPI: CustomDuringAPI = {
tmpDuringScope.isShapeDirty = true;
return this;
},
- getShape(key: string): unknown {
+ getShape(key: any): any {
if (__DEV__) {
assertNotReserved(key);
}
@@ -623,7 +631,7 @@ const customDuringAPI: CustomDuringAPI = {
return shape[key];
}
},
- setStyle(key: string, val: unknown) {
+ setStyle(key: any, val: unknown) {
if (__DEV__) {
assertNotReserved(key);
}
@@ -639,7 +647,7 @@ const customDuringAPI: CustomDuringAPI = {
}
return this;
},
- getStyle(key: string): unknown {
+ getStyle(key: any): any {
if (__DEV__) {
assertNotReserved(key);
}
@@ -648,7 +656,7 @@ const customDuringAPI: CustomDuringAPI = {
return style[key];
}
},
- setExtra(key: string, val: unknown) {
+ setExtra(key: any, val: unknown) {
if (__DEV__) {
assertNotReserved(key);
}
@@ -785,7 +793,7 @@ function updateZ(
elDisplayable.z = currentZ;
elDisplayable.zlevel = currentZLevel;
// z2 must not be null/undefined, otherwise sort error may occur.
- const optZ2 = elOption.z2;
+ const optZ2 = (elOption as CustomDisplayableOption).z2;
optZ2 != null && (elDisplayable.z2 = optZ2 || 0);
for (let i = 0; i < STATES.length; i++) {
@@ -799,7 +807,10 @@ function updateZForEachState(
state: DisplayState
): void {
const isNormal = state === NORMAL;
- const elStateOpt = isNormal ? elOption : retrieveStateOption(elOption, state as DisplayStateNonNormal);
+ const elStateOpt = isNormal ? elOption : retrieveStateOption(
+ elOption as CustomElementOption,
+ state as DisplayStateNonNormal
+ );
const optZ2 = elStateOpt ? elStateOpt.z2 : null;
let stateObj;
if (optZ2 != null) {
@@ -860,7 +871,7 @@ function makeRenderItem(
coordSys: prepareResult.coordSys,
dataInsideLength: data.count(),
encode: wrapEncodeDef(customSeries.getData())
- };
+ } as CustomSeriesRenderItemParams;
// If someday intending to refactor them to a class, should consider do not
// break change: currently these attribute member are encapsulated in a closure
@@ -920,7 +931,7 @@ function makeRenderItem(
dataIndex: data.getRawIndex(dataIndexInside),
// Can be used for optimization when zoom or roam.
actionType: payload ? payload.type : null
- }, userParams),
+ } as CustomSeriesRenderItemParams, userParams),
userAPI
);
};
@@ -1209,7 +1220,7 @@ function doCreateOrUpdateEl(
}
// Need to set morph: false explictly to disable automatically morphing.
- if ((elOption as CustomZRPathOption).morph === false) {
+ if ((elOption as CustomBaseZRPathOption).morph === false) {
(el as ECElement).disableMorphing = true;
}
else if ((el as ECElement).disableMorphing) {
@@ -1273,8 +1284,8 @@ function doCreateOrUpdateEl(
function doesElNeedRecreate(el: Element, elOption: CustomElementOption, seriesModel: CustomSeriesModel): boolean {
const elInner = customInnerStore(el);
const elOptionType = elOption.type;
- const elOptionShape = (elOption as CustomZRPathOption).shape;
- const elOptionStyle = elOption.style;
+ const elOptionShape = (elOption as CustomBaseZRPathOption).shape;
+ const elOptionStyle = (elOption as CustomDisplayableOption).style;
return (
// Always create new if universal transition is enabled.
// Because we do transition after render. It needs to know what old element is. Replacement will loose it.
@@ -1309,7 +1320,7 @@ function doCreateOrUpdateClipPath(
// Based on the "merge" principle, if no clipPath provided,
// do nothing. The exists clip will be totally removed only if
// `el.clipPath` is `false`. Otherwise it will be merged/replaced.
- const clipPathOpt = elOption.clipPath;
+ const clipPathOpt = elOption.clipPath as CustomPathOption | false;
if (clipPathOpt === false) {
if (el && el.getClipPath()) {
el.removeClipPath();
@@ -1317,7 +1328,11 @@ function doCreateOrUpdateClipPath(
}
else if (clipPathOpt) {
let clipPath = el.getClipPath();
- if (clipPath && doesElNeedRecreate(clipPath, clipPathOpt, seriesModel)) {
+ if (clipPath && doesElNeedRecreate(
+ clipPath,
+ clipPathOpt,
+ seriesModel
+ )) {
clipPath = null;
}
if (!clipPath) {
@@ -1385,7 +1400,7 @@ function doCreateOrUpdateAttachedTx(
updateElNormal(
null, textContent, dataIndex, txConOptNormal, null, seriesModel, isInit, true
);
- const txConStlOptNormal = txConOptNormal && txConOptNormal.style;
+ const txConStlOptNormal = txConOptNormal && (txConOptNormal as CustomDisplayableOption).style;
for (let i = 0; i < STATES.length; i++) {
const stateName = STATES[i];
if (stateName !== NORMAL) {
@@ -1411,7 +1426,9 @@ function processTxInfo(
attachedTxInfo: AttachedTxInfo
): void {
const stateOpt = !state ? elOption : retrieveStateOption(elOption, state);
- const styleOpt = !state ? elOption.style : retrieveStyleOptionOnState(elOption, stateOpt, EMPHASIS);
+ const styleOpt = !state
+ ? (elOption as CustomDisplayableOption).style
+ : retrieveStyleOptionOnState(elOption, stateOpt, EMPHASIS);
const elType = elOption.type;
let txCfg = stateOpt ? stateOpt.textConfig : null;
@@ -1444,7 +1461,7 @@ function processTxInfo(
!txConOptNormal.type && (txConOptNormal.type = 'text');
if (__DEV__) {
// Do not tolerate incorret type for forward compat.
- txConOptNormal.type !== 'text' && assert(
+ assert(
txConOptNormal.type === 'text',
'textContent.type must be "text"'
);
@@ -1459,7 +1476,7 @@ function processTxInfo(
function retrieveStateOption(
elOption: CustomElementOption, state: DisplayStateNonNormal
): CustomElementOptionOnState {
- return !state ? elOption : elOption ? elOption[state] : null;
+ return !state ? elOption : elOption ? (elOption as CustomDisplayableOption)[state] : null;
}
function retrieveStyleOptionOnState(
@@ -1469,7 +1486,7 @@ function retrieveStyleOptionOnState(
): CustomElementOptionOnState['style'] {
let style = stateOption && stateOption.style;
if (style == null && state === EMPHASIS && stateOptionNormal) {
- style = stateOptionNormal.styleEmphasis;
+ style = (stateOptionNormal as CustomDisplayableOption).styleEmphasis;
}
return style;
}
@@ -1514,7 +1531,7 @@ function mergeChildren(
diffGroupChildren({
api: api,
oldChildren: el.children() || [],
- newChildren: newChildren || [],
+ newChildren: newChildren as CustomElementOption[] || [],
dataIndex: dataIndex,
seriesModel: seriesModel,
group: el
@@ -1532,7 +1549,7 @@ function mergeChildren(
api,
el.childAt(index),
dataIndex,
- newChildren[index],
+ newChildren[index] as CustomElementOption,
seriesModel,
el,
false
diff --git a/src/chart/custom/prepare.ts b/src/chart/custom/prepare.ts
index 67ceed0..37f8d99 100644
--- a/src/chart/custom/prepare.ts
+++ b/src/chart/custom/prepare.ts
@@ -21,6 +21,7 @@ import Transformable from 'zrender/src/core/Transformable';
import Element, { ElementProps } from 'zrender/src/Element';
import { Dictionary } from '../../util/types';
import {
+ CustomDisplayableOption,
CustomElementOption,
customInnerStore,
LooseElementProps,
@@ -242,7 +243,7 @@ export function prepareTransformAllPropsFinal(
export function prepareStyleTransitionFrom(
fromEl: Element,
elOption: CustomElementOption,
- styleOpt: CustomElementOption['style'],
+ styleOpt: CustomDisplayableOption['style'],
transFromProps: LooseElementProps,
isInit: boolean
): void {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org