From c473639c21a395717db58302512bb1a78c08e8be Mon Sep 17 00:00:00 2001 From: SHUANG SU Date: Mon, 23 Sep 2019 03:16:52 +0800 Subject: [PATCH] feat: provide `echarts.registerShape` and `echarts.getShapeClass` for custom shape in `custom series` and `graphic component`. --- src/chart/custom.js | 10 ++++++- src/component/graphic.js | 18 +++++++++++- src/export.js | 1 + src/util/graphic.js | 61 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/chart/custom.js b/src/chart/custom.js index 7c31bb7bb..784e59c15 100644 --- a/src/chart/custom.js +++ b/src/chart/custom.js @@ -231,6 +231,8 @@ function createEl(elOption) { var graphicType = elOption.type; var el; + // Those graphic elements are not shapes. They should not be + // overwritten by users, so do them first. if (graphicType === 'path') { var shape = elOption.shape; // Using pathRect brings convenience to users sacle svg path. @@ -255,8 +257,14 @@ function createEl(elOption) { el = new graphicUtil.Text({}); el.__customText = elOption.style.text; } + else if (graphicType === 'group') { + el = new graphicUtil.Group(); + } + else if (graphicType === 'compoundPath') { + throw new Error('"compoundPath" is not supported yet.'); + } else { - var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + var Clz = graphicUtil.getShapeClass(graphicType); if (__DEV__) { zrUtil.assert(Clz, 'graphic type "' + graphicType + '" can not be found.'); diff --git a/src/component/graphic.js b/src/component/graphic.js index 92674a70e..e689db1bd 100644 --- a/src/component/graphic.js +++ b/src/component/graphic.js @@ -26,6 +26,18 @@ import * as graphicUtil from '../util/graphic'; import * as layoutUtil from '../util/layout'; import {parsePercent} from '../util/number'; +var _nonShapeGraphicElements = { + + // Reserved but not supported in graphic component. + path: null, + compoundPath: null, + + // Supported in graphic component. + group: graphicUtil.Group, + image: graphicUtil.Image, + text: graphicUtil.Text +}; + // ------------- // Preprocessor // ------------- @@ -440,7 +452,11 @@ function createEl(id, targetElParent, elOption, elMap) { zrUtil.assert(graphicType, 'graphic type MUST be set'); } - var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)]; + var Clz = _nonShapeGraphicElements.hasOwnProperty(graphicType) + // Those graphic elements are not shapes. They should not be + // overwritten by users, so do them first. + ? _nonShapeGraphicElements[graphicType] + : graphicUtil.getShapeClass(graphicType); if (__DEV__) { zrUtil.assert(Clz, 'graphic type can not be found'); diff --git a/src/export.js b/src/export.js index dded75c77..6ddd62ecc 100644 --- a/src/export.js +++ b/src/export.js @@ -71,6 +71,7 @@ zrUtil.each( 'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText', 'getFont', 'updateProps', 'initProps', 'getTransform', 'clipPointsByRect', 'clipRectByRect', + 'registerShape', 'getShapeClass', 'Group', 'Image', 'Text', diff --git a/src/util/graphic.js b/src/util/graphic.js index 38b2b854c..0ca633d3f 100644 --- a/src/util/graphic.js +++ b/src/util/graphic.js @@ -65,6 +65,8 @@ var NORMAL = 'normal'; var _highlightNextDigit = 1; var _highlightKeyMap = {}; +var _customShapeMap = {}; + /** * Extend shape with parameters @@ -80,6 +82,53 @@ export function extendPath(pathData, opts) { return pathTool.extendFromString(pathData, opts); } +/** + * Register a user defined shape. + * The shape class can be fetched by `getShapeClass` + * This method will not overwrite the built-in shapes. + * The shape can be used in `custom series` and + * `graphic component` by declaring `{type: name}`. + * + * @param {string} name + * @param {Object} ShapeClass Can be generated by `extendShape`. + */ +export function registerShape(name, ShapeClass) { + _customShapeMap[name] = ShapeClass; +} + +/** + * Find shape class registered by `registerShape`. Usually used in + * fetching user defined shape. + * + * [Caution]: + * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared + * to use user registered shapes. + * Because the built-in shape (see `getBuiltInShape`) will be registered by + * `registerShape` by default. That enables users to get both built-in + * shapes as well as the shapes belonging to themsleves. But users can overwrite + * the built-in shapes by using names like 'circle', 'rect' via calling + * `registerShape`. So the echarts inner featrues should not fetch shapes from here + * in case that it is overwritten by users, except that some features, like + * `custom series`, `graphic component`, do it deliberately. + * + * (2) In the features like `custom series`, `graphic component`, the user input + * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic + * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names + * are reserved names, that is, if some user register a shape named `'image'`, + * the shape will not be used. If we intending to add some more reserved names + * in feature, that might bring break changes (disable some existing user shape + * names). But that case probably rearly happen. So we dont make more mechanism + * to resolve this issue here. + * + * @param {string} name + * @return {Object} The shape class. If not found, return nothing. + */ +export function getShapeClass(name) { + if (_customShapeMap.hasOwnProperty(name)) { + return _customShapeMap[name]; + } +} + /** * Create a path element from path data string * @param {string} pathData @@ -1377,6 +1426,18 @@ function nearZero(val) { return val <= (1e-6) && val >= -(1e-6); } +// Register built-in shapes. These shapes might be overwirtten +// by users, although we do not recommend that. +registerShape('circle', Circle); +registerShape('sector', Sector); +registerShape('ring', Ring); +registerShape('polygon', Polygon); +registerShape('polyline', Polyline); +registerShape('rect', Rect); +registerShape('line', Line); +registerShape('bezierCurve', BezierCurve); +registerShape('arc', Arc); + export { Group, ZImage as Image, -- GitLab