Skip to content

Commit 305071b

Browse files
authored
Merge pull request #4408 from VisActor/feat/brush-api
Feat/brush api & interactive api
2 parents 0236b4b + b5921c9 commit 305071b

File tree

20 files changed

+192
-59
lines changed

20 files changed

+192
-59
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vchart",
5+
"comment": "feat: add brush api before change",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vchart"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vchart",
5+
"comment": "git commit -m 'feat: add interactive api",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vchart"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vchart",
5+
"comment": "feat: add brush clear api and disable dimension hover config. close#4400",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vchart"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vchart",
5+
"comment": "feat: interactive params add event. feat #4421",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vchart"
10+
}

packages/vchart/src/compile/compiler.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ export class Compiler implements ICompiler {
7171

7272
protected _container: IRenderContainer;
7373
protected _option: IRenderOption;
74+
getOption() {
75+
return this._option;
76+
}
7477
// 已释放标记
7578
private _released: boolean = false;
7679

@@ -498,8 +501,8 @@ export class Compiler implements ICompiler {
498501
const animationState = markAnimationStates.every(state => state === AnimationStateEnum.appear)
499502
? AnimationStateEnum.appear
500503
: markAnimationStates.every(state => state === AnimationStateEnum.disappear)
501-
? AnimationStateEnum.disappear
502-
: AnimationStateEnum.none;
504+
? AnimationStateEnum.disappear
505+
: AnimationStateEnum.none;
503506
if (!this._stage.context) {
504507
this._stage.context = {};
505508
}

packages/vchart/src/compile/interface/compilable-item.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { IMorphConfig } from '../../animation/spec';
66
import type { IBoundsLike } from '@visactor/vutils';
77
import type { EventSourceType, EventType } from '../../event/interface';
88
import type { IMark, IMarkGraphic } from '../../mark/interface';
9-
import type { LayoutState } from '../interface/compiler';
9+
import type { IRenderOption, LayoutState } from '../interface/compiler';
1010
import type { MarkAnimationSpec } from '../../animation/interface';
1111

1212
export type CompilerListenerParameters = {
@@ -34,6 +34,7 @@ export interface IGrammarItemMap<T extends IGrammarItem> {
3434
export type ICompilerModel = Record<GrammarType, IProductMap<IGrammarItem>>;
3535

3636
export interface ICompiler {
37+
getOption: () => IRenderOption;
3738
isInited?: boolean;
3839
readonly stateAnimationConfig?: MarkAnimationSpec;
3940
getCanvas: () => HTMLCanvasElement | undefined;

packages/vchart/src/component/brush/brush.ts

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Brush as BrushComponent, IOperateType as BrushEvent } from '@visactor/v
88
import type { IBounds, IPointLike, Maybe } from '@visactor/vutils';
99
// eslint-disable-next-line no-duplicate-imports
1010
import { array, polygonIntersectPolygon, isValid, last } from '@visactor/vutils';
11-
import type { IModelRenderOption, IModelSpecInfo } from '../../model/interface';
11+
import type { IModelSpecInfo } from '../../model/interface';
1212
import type { IRegion } from '../../region/interface';
1313
import type { IGraphic, IGroup, INode, IPolygon } from '@visactor/vrender-core';
1414
import { transformToGraphic } from '../../util/style';
@@ -24,6 +24,7 @@ import { getSpecInfo } from '../util';
2424
import { brush } from '../../theme/builtin/common/component/brush';
2525
import { isReverse, statePointToData } from '../data-zoom/util';
2626
import type { CartesianAxis } from '../axis/cartesian';
27+
import type { IRenderOption } from '../../compile/interface';
2728

2829
const IN_BRUSH_STATE = 'inBrush';
2930
const OUT_BRUSH_STATE = 'outOfBrush';
@@ -47,6 +48,8 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
4748
protected _relativeRegions!: IRegion[];
4849
protected _linkedSeries: ISeries[] = [];
4950

51+
protected _operateMask: IPolygon;
52+
5053
private _itemMap: { [regionId: string | number]: IMark[] } = {};
5154
private _linkedItemMap: { [seriesId: string | number]: IMark[] } = {};
5255

@@ -249,6 +252,10 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
249252
brushComponent.children[0].removeAllChild();
250253
}
251254

255+
protected _shouldEnableInteractive() {
256+
return (this.getOption().getCompiler().getOption() as IRenderOption).interactive !== false;
257+
}
258+
252259
protected _createBrushComponent(region: IRegion, componentIndex: number) {
253260
const interactiveAttr = this._getBrushInteractiveAttr(region);
254261
const brush = new BrushComponent({
@@ -265,38 +272,50 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
265272

266273
brush.addEventListener(BrushEvent.brushActive, (e: any) => {
267274
this._initMarkBrushState(componentIndex, OUT_BRUSH_STATE);
268-
this._emitEvent(ChartEvent.brushActive, region);
275+
this._emitEvent(ChartEvent.brushActive, region, e);
269276
});
270277

271278
brush.addEventListener(BrushEvent.drawStart, (e: any) => {
279+
if (this._spec.disableDimensionHoverWhenBrushing) {
280+
this._option.globalInstance.disableDimensionHoverEvent(true);
281+
}
272282
this._setRegionMarkPickable(region, true);
273-
this._emitEvent(ChartEvent.brushStart, region);
283+
this._emitEvent(ChartEvent.brushStart, region, e);
274284
});
275285

276286
brush.addEventListener(BrushEvent.moveStart, (e: any) => {
287+
if (this._spec.disableDimensionHoverWhenBrushing) {
288+
this._option.globalInstance.disableDimensionHoverEvent(true);
289+
}
277290
this._setRegionMarkPickable(region, true);
278-
this._emitEvent(ChartEvent.brushStart, region);
291+
this._emitEvent(ChartEvent.brushStart, region, e);
279292
});
280293

281294
brush.addEventListener(BrushEvent.drawing, (e: any) => {
282295
this._setRegionMarkPickable(region, false);
283296
this._handleBrushChange(region, e);
284-
this._emitEvent(ChartEvent.brushChange, region);
297+
this._emitEvent(ChartEvent.brushChange, region, e);
285298
});
286299

287300
brush.addEventListener(BrushEvent.moving, (e: any) => {
288301
this._setRegionMarkPickable(region, false);
289302
this._handleBrushChange(region, e);
290-
this._emitEvent(ChartEvent.brushChange, region);
303+
this._emitEvent(ChartEvent.brushChange, region, e);
291304
});
292305

293306
brush.addEventListener(BrushEvent.brushClear, (e: any) => {
307+
if (this._spec.disableDimensionHoverWhenBrushing) {
308+
this._option.globalInstance.disableDimensionHoverEvent(false);
309+
}
294310
this._setRegionMarkPickable(region, true);
295311
this._initMarkBrushState(componentIndex, '');
296-
this._emitEvent(ChartEvent.brushClear, region);
312+
this._emitEvent(ChartEvent.brushClear, region, e);
297313
});
298314

299315
brush.addEventListener(BrushEvent.drawEnd, (e: any) => {
316+
if (this._spec.disableDimensionHoverWhenBrushing) {
317+
this._option.globalInstance.disableDimensionHoverEvent(false);
318+
}
300319
this._setRegionMarkPickable(region, true);
301320
const { operateMask } = e.detail as any;
302321
const { updateElementsState = true } = this._spec;
@@ -305,29 +324,32 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
305324
if (this._spec.onBrushEnd(e) === true) {
306325
this.clearGraphic();
307326
this._initMarkBrushState(componentIndex, '');
308-
this._emitEvent(ChartEvent.brushClear, region);
327+
this._emitEvent(ChartEvent.brushClear, region, e);
309328
} else {
310329
this._spec.onBrushEnd(e);
311-
this._emitEvent(ChartEvent.brushEnd, region);
330+
this._emitEvent(ChartEvent.brushEnd, region, e);
312331
}
313332
} else {
314333
const inBrushData = this._extendDataInBrush(this._inBrushElementsMap);
315334
if ((!this._spec.zoomWhenEmpty && inBrushData.length > 0) || !updateElementsState) {
316335
this._setAxisAndDataZoom(operateMask, region);
317336
}
318-
this._emitEvent(ChartEvent.brushEnd, region);
337+
this._emitEvent(ChartEvent.brushEnd, region, e);
319338
}
320339
});
321340

322341
brush.addEventListener(BrushEvent.moveEnd, (e: any) => {
342+
if (this._spec.disableDimensionHoverWhenBrushing) {
343+
this._option.globalInstance.disableDimensionHoverEvent(false);
344+
}
323345
this._setRegionMarkPickable(region, true);
324346
const { operateMask } = e.detail as any;
325347
const { updateElementsState = true } = this._spec;
326348
const inBrushData = this._extendDataInBrush(this._inBrushElementsMap);
327349
if ((!this._spec.zoomWhenEmpty && inBrushData.length > 0) || updateElementsState) {
328350
this._setAxisAndDataZoom(operateMask, region);
329351
}
330-
this._emitEvent(ChartEvent.brushEnd, region);
352+
this._emitEvent(ChartEvent.brushEnd, region, e);
331353
});
332354
}
333355

@@ -346,7 +368,8 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
346368
maxX: seriesRegionEndX
347369
},
348370
xRange: [seriesRegionStartX, seriesRegionEndX],
349-
yRange: [seriesRegionStartY, seriesRegionEndY]
371+
yRange: [seriesRegionStartY, seriesRegionEndY],
372+
interactive: this._shouldEnableInteractive()
350373
} as BrushInteractiveRangeAttr;
351374
}
352375

@@ -374,6 +397,7 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
374397
/*** start: event dispatch ***/
375398
private _handleBrushChange(region: IRegion, e: any) {
376399
const { operateMask } = e.detail as any;
400+
this._operateMask = operateMask;
377401
const { updateElementsState = true } = this._spec;
378402
if (updateElementsState) {
379403
this._reconfigItem(operateMask, region);
@@ -403,7 +427,7 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
403427
return data;
404428
}
405429

406-
private _emitEvent(eventType: string, region: IRegion) {
430+
private _emitEvent(eventType: string, region: IRegion, e: any) {
407431
this.event.emit(eventType, {
408432
model: this,
409433
value: {
@@ -430,7 +454,8 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
430454
// 缩放记录
431455
zoomRecord: this._zoomRecord
432456
},
433-
vchart: this._option?.globalInstance
457+
vchart: this._option?.globalInstance,
458+
event: e
434459
});
435460
}
436461
/*** end: event dispatch ***/
@@ -767,6 +792,12 @@ export class Brush<T extends IBrushSpec = IBrushSpec> extends BaseComponent<T> i
767792
this._brushComponents = null;
768793
}
769794
}
795+
clearBrushStateAndMask() {
796+
this._relativeRegions.forEach((region: IRegion, componentIndex: number) => {
797+
this._initMarkBrushState(componentIndex, '');
798+
this._brushComponents[componentIndex].children[0].removeAllChild();
799+
});
800+
}
770801
}
771802

772803
export const registerBrush = () => {

packages/vchart/src/component/brush/interface.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { SymbolType } from '@visactor/vrender-core';
1+
import type { FederatedPointerEvent, SymbolType } from '@visactor/vrender-core';
22
import type { IPolygonMarkSpec } from '../../typings';
33
import type { IComponent } from '../interface';
44
import type { IDelayType } from '../../typings/event';
@@ -65,6 +65,16 @@ interface IBrushDataBindSpec {
6565
* 2) 散点图按照散点中心定位, 如果严格按照中心范围更新,会出现散点超出画布的现象
6666
*/
6767
axisRangeExpand?: number;
68+
/**
69+
* 框选前触发事件
70+
* 返回false, 则阻止后续逻辑
71+
*/
72+
beforeBrushChange?: (e: FederatedPointerEvent) => void | boolean;
73+
/**
74+
* 是否在框选时禁用维度 hover 事件
75+
* @default false
76+
*/
77+
disableDimensionHoverWhenBrushing?: boolean;
6878
}
6979

7080
export interface IBrushTheme {

packages/vchart/src/component/crosshair/interface/spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { IComponentSpec } from '../../base/interface';
55
import type { IComponent } from '../../interface';
66

77
export interface ICrossHair extends IComponent {
8+
enable: boolean;
89
clearAxisValue: () => void;
910
setAxisValue: (v: StringOrNumber, axis: IAxis) => void;
1011
layoutByValue: (enableRemain?: boolean) => void;

packages/vchart/src/component/tooltip/interface/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ export interface ITooltip extends IComponent {
4949
tooltipHandler?: ITooltipHandler;
5050
getVisible: () => boolean;
5151
showTooltip: (datum: Datum, options: IShowTooltipOption) => void;
52+
enable?: boolean;
5253
}

0 commit comments

Comments
 (0)