diff --git a/docs/common/brush.en.md b/docs/common/brush.en.md index bddd8f1f5e3..eaaea18fb84 100644 --- a/docs/common/brush.en.md +++ b/docs/common/brush.en.md @@ -8,12 +8,13 @@ Configuration of brush interaction. Types of _BrushCfg_ are as follows: -| Properties | Type | Description | -| ---------- | --------- | ------------------------------------------------------------------------------------------------ | -| enabled | _boolean_ | 是否开启 brush 刷选交互,默认为:'false' | -| type | _string_ | brush 类型,可选项:'rect' \| 'x-rect' \| 'y-rect' \| 'cirlce' \| 'path' (polygon). 默认: 'rect' | -| action | _string_ | brush action, options: 'filter' \| 'highlight'. Default: 'filter' | -| mask | _MaskCfg_ | Configuration of mask. | +| Properties | Type | Description | +| ---------- | ----------- | ------------------------------------------------------------------------------------------------ | +| enabled | _boolean_ | 是否开启 brush 刷选交互,默认为:'false' | +| type | _string_ | brush 类型,可选项:'rect' \| 'x-rect' \| 'y-rect' \| 'cirlce' \| 'path' (polygon). 默认: 'rect' | +| action | _string_ | brush action, options: 'filter' \| 'highlight'. Default: 'filter' | +| mask | _MaskCfg_ | Configuration of mask. | +| button | _ButtonCfg_ | Configuration of rRset Button,works when action is equal to 'filter' | Types of _MaskCfg_ are as follows: @@ -21,6 +22,34 @@ Types of _MaskCfg_ are as follows: | ---------- | ------------ | ----------- | | style | _ShapeAttrs_ | mask 样式 | +Types of _ButtonCfg_ are as follows: + +```ts +export type ButtonCfg = { + /** + * padding of button + */ + padding?: number | number[]; + /** + * text of button + */ + text?: string; + /** + * custom style of text + */ + textStyle?: { + default?: ShapeAttrs; + }; + /** + * custom style of button + */ + buttonStyle?: { + default?: ShapeAttrs; + active?: ShapeAttrs; + }; +}; +``` + **Events** 1. List of vents of `brush-filter` interaction, diff --git a/docs/common/brush.zh.md b/docs/common/brush.zh.md index 20d34945ea2..ce8f66f5251 100644 --- a/docs/common/brush.zh.md +++ b/docs/common/brush.zh.md @@ -14,6 +14,7 @@ _BrushCfg_ 类型定义如下: | type | _string_ | brush 类型,可选项:'rect' \| 'x-rect' \| 'y-rect' \| 'cirlce' \| 'path'(不规则矩形). 默认: 'rect' | | action | _string_ | brush 操作,可选项:'filter' \| 'highlight'(对应 '筛选过滤' 和 '高亮强调'). 默认: 'filter'. | | mask | _MaskCfg_ | 刷选交互的蒙层 mask UI 配置 | +| button | _ButtonCfg_ | 刷选交互的重置按钮配置,只在 action 为 filter 的时候,生效 | _MaskCfg_ 类型定义如下: @@ -21,6 +22,34 @@ _MaskCfg_ 类型定义如下: | ----- | ------------ | --------- | | style | _ShapeAttrs_ | mask 样式 | +_ButtonCfg_ 类型定义如下: + +```ts +export type ButtonCfg = { + /** + * 文本与按钮边缘的间距 + */ + padding?: number | number[]; + /** + * 按钮文本 + */ + text?: string; + /** + * 自定义文本样式 + */ + textStyle?: { + default?: ShapeAttrs; + }; + /** + * 自定义按钮样式 + */ + buttonStyle?: { + default?: ShapeAttrs; + active?: ShapeAttrs; + }; +}; +``` + **事件** brush 交互相关事件: diff --git a/src/adaptor/brush.ts b/src/adaptor/brush.ts index d27ce53d0ed..cf225e03b2d 100644 --- a/src/adaptor/brush.ts +++ b/src/adaptor/brush.ts @@ -44,6 +44,16 @@ export function brushInteraction(params: Params) } interactions.push(obj); }); + + // 塞入 button 配置 (G2Plot 的封装) + if (brush?.action !== 'highlight') { + interactions.push({ + type: 'filter-action', + cfg: { + buttonConfig: brush.button, + }, + }); + } } return deepAssign({}, params, { options: { interactions } }); } diff --git a/src/interactions/actions/drill-down.ts b/src/interactions/actions/drill-down.ts index 0f9667a29d2..f46837cba43 100644 --- a/src/interactions/actions/drill-down.ts +++ b/src/interactions/actions/drill-down.ts @@ -8,7 +8,8 @@ import { deepAssign } from '../../utils/deep-assign'; const PADDING = 4; // 面包屑位置距离树图的距离 const PADDING_LEFT = 0; -export const PADDING_TOP = 5; +// 面包屑位置距离树图的顶部距离 +const PADDING_TOP = 5; /** Group name of breadCrumb: 面包屑 */ export const BREAD_CRUMB_NAME = 'drilldown-bread-crumb'; @@ -57,6 +58,7 @@ type HistoryCache = { /** * @description 下钻交互的 action + * @author liuzhenying * * 适用于:hierarchy plot */ diff --git a/src/interactions/actions/reset-button.ts b/src/interactions/actions/reset-button.ts new file mode 100644 index 00000000000..5973d56db60 --- /dev/null +++ b/src/interactions/actions/reset-button.ts @@ -0,0 +1,161 @@ +import { Action, IGroup, Util } from '@antv/g2'; +import { get } from '@antv/util'; +import { BBox, ButtonCfg } from '../../types'; +import { deepAssign, normalPadding } from '../../utils'; + +const PADDING_RIGHT = 10; +const PADDING_TOP = 5; + +/** + * Action 中的 Button 按钮配置 + * + * 可能的使用场景:brush filter + */ +export const BUTTON_ACTION_CONFIG: ButtonCfg = { + padding: [8, 10], + text: 'reset', + textStyle: { + default: { + x: 0, + y: 0, + fontSize: 12, + fill: '#333333', + cursor: 'pointer', + }, + }, + buttonStyle: { + default: { + fill: '#f7f7f7', + stroke: '#cccccc', + cursor: 'pointer', + }, + active: { + fill: '#e6e6e6', + }, + }, +}; + +/** + * @override 复写 G2 Button Action, 后续直接使用 GUI + */ +class ButtonAction extends Action { + private buttonGroup: IGroup = null; + private buttonCfg = { + name: 'button', + ...BUTTON_ACTION_CONFIG, + }; + + /** + * 获取 mix 默认的配置和用户配置 + */ + private getButtonCfg(): ButtonCfg & { name: string } { + const { view } = this.context; + const buttonCfg: ButtonCfg = get(view, ['interactions', 'filter-action', 'cfg', 'buttonConfig']); + + return deepAssign(this.buttonCfg, buttonCfg, this.cfg); + } + + /** + * 绘制 Button 和 文本 + */ + private drawButton() { + const config = this.getButtonCfg(); + const group = this.context.view.foregroundGroup.addGroup({ + name: config.name, + }); + const textShape = this.drawText(group); + this.drawBackground(group, textShape.getBBox()); + + this.buttonGroup = group; + } + + /** + * 绘制文本 + */ + private drawText(group: IGroup) { + const config = this.getButtonCfg(); + // 添加文本 + return group.addShape({ + type: 'text', + name: 'button-text', + attrs: { + text: config.text, + ...config.textStyle?.default, + }, + }); + } + + private drawBackground(group: IGroup, bbox: BBox) { + const config = this.getButtonCfg(); + const padding = normalPadding(config.padding); + // 添加背景按钮 + const buttonShape = group.addShape({ + type: 'rect', + name: 'button-rect', + attrs: { + x: bbox.x - padding[3], + y: bbox.y - padding[0], + width: bbox.width + padding[1] + padding[3], + height: bbox.height + padding[0] + padding[2], + ...config.buttonStyle?.default, + }, + }); + buttonShape.toBack(); // 在后面 + + // active 效果内置 + group.on('mouseenter', () => { + buttonShape.attr(config.buttonStyle?.active); + }); + group.on('mouseleave', () => { + buttonShape.attr(config.buttonStyle?.default); + }); + + return buttonShape; + } + + // 重置位置 + private resetPosition() { + const view = this.context.view; + const coord = view.getCoordinate(); + const point = coord.convert({ x: 1, y: 1 }); // 后面直接改成左上角 + const buttonGroup = this.buttonGroup; + const bbox = buttonGroup.getBBox(); + const matrix = Util.transform(null, [ + ['t', point.x - bbox.width - PADDING_RIGHT, point.y + bbox.height + PADDING_TOP], + ]); + buttonGroup.setMatrix(matrix); + } + + /** + * 显示 + */ + public show() { + if (!this.buttonGroup) { + this.drawButton(); + } + this.resetPosition(); + this.buttonGroup.show(); + } + + /** + * 隐藏 + */ + public hide() { + if (this.buttonGroup) { + this.buttonGroup.hide(); + } + } + + /** + * 销毁 + */ + public destroy() { + const buttonGroup = this.buttonGroup; + if (buttonGroup) { + buttonGroup.remove(); + } + super.destroy(); + } +} + +export { ButtonAction }; diff --git a/src/interactions/brush.ts b/src/interactions/brush.ts index 2d0bd7c6087..752e0882bae 100644 --- a/src/interactions/brush.ts +++ b/src/interactions/brush.ts @@ -1,5 +1,12 @@ -import { registerInteraction } from '@antv/g2'; +import { registerAction, registerInteraction } from '@antv/g2'; import { BrushCfg } from '../types'; +import { ButtonAction } from './actions/reset-button'; + +registerAction('brush-reset-button', ButtonAction, { + name: 'brush-reset-button', +}); + +registerInteraction('filter-action', {}); /** * G2 已经内置了 brush、brush-x、brush-y 等交互,其它: @@ -45,10 +52,21 @@ export function getInteractionCfg(interactionType: string, brushType?: string, m { trigger: 'mouseup', isEnable: isPointInView, - action: ['brush:filter', 'brush:end', `${maskType}-mask:end`, `${maskType}-mask:hide`, 'reset-button:show'], + action: [ + 'brush:filter', + 'brush:end', + `${maskType}-mask:end`, + `${maskType}-mask:hide`, + 'brush-reset-button:show', + ], + }, + ], + rollback: [ + { + trigger: 'brush-reset-button:click', + action: ['brush:reset', 'brush-reset-button:hide', 'cursor:crosshair'], }, ], - rollback: [{ trigger: 'reset-button:click', action: ['brush:reset', 'reset-button:hide', 'cursor:crosshair'] }], }; case 'brush-highlight': return { diff --git a/src/types/button.ts b/src/types/button.ts new file mode 100644 index 00000000000..1533ba5fffb --- /dev/null +++ b/src/types/button.ts @@ -0,0 +1,30 @@ +import { ShapeAttrs } from '@antv/g2'; + +/** + * @description 一些按钮的类型定义,比如 brush filter 中的 Button + * + * 和 GUI Button 尽量保持一致 + */ +export type ButtonCfg = { + /** + * 文本与按钮边缘的间距 + */ + padding?: number | number[]; + /** + * 按钮文本 + */ + text?: string; + /** + * 自定义文本样式 + */ + textStyle?: { + default?: ShapeAttrs; + }; + /** + * 自定义按钮样式 + */ + buttonStyle?: { + default?: ShapeAttrs; + active?: ShapeAttrs; + }; +}; diff --git a/src/types/index.ts b/src/types/index.ts index 18b68a2674b..2e09b66e049 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,6 +7,7 @@ export * from './meta'; export * from './axis'; export * from './interaction'; export * from './locale'; +export * from './button'; /** 去除 readonly 修饰 */ export type Writable = { -readonly [P in keyof T]: T[P] }; diff --git a/src/types/interaction.ts b/src/types/interaction.ts index 71f2a12f03d..5f2ac607ebc 100644 --- a/src/types/interaction.ts +++ b/src/types/interaction.ts @@ -1,4 +1,5 @@ import { ShapeAttrs } from '@antv/g2'; +import { ButtonCfg } from './button'; export type Interaction = { readonly type: string; @@ -20,4 +21,6 @@ export type BrushCfg = { /** mask 蒙层样式 */ style?: ShapeAttrs; }; + /** brush button 的配置, 只在 action: 'filter' 的情况下适用 */ + readonly button?: ButtonCfg; }; diff --git a/src/utils/index.ts b/src/utils/index.ts index 38142717d55..788dd446c3c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -13,3 +13,4 @@ export { renderStatistic, renderGaugeStatistic } from './statistic'; export { measureTextWidth } from './measure-text'; export { isBetween, isRealNumber } from './number'; export * from './data'; +export * from './padding';