diff --git a/common/changes/@visactor/vchart/fix-prevent-handler_2024-08-01-09-23.json b/common/changes/@visactor/vchart/fix-prevent-handler_2024-08-01-09-23.json new file mode 100644 index 0000000000..1b601c4a9c --- /dev/null +++ b/common/changes/@visactor/vchart/fix-prevent-handler_2024-08-01-09-23.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vchart", + "comment": "fix: prevent trigger original event in panEnd composite event #2931", + "type": "none" + } + ], + "packageName": "@visactor/vchart" +} \ No newline at end of file diff --git a/packages/vchart/src/event/bubble.ts b/packages/vchart/src/event/bubble.ts index b1f7c88f94..95ef27f5a6 100644 --- a/packages/vchart/src/event/bubble.ts +++ b/packages/vchart/src/event/bubble.ts @@ -37,10 +37,28 @@ export class Bubble { return this; } + preventHandler(handler: EventHandler): this { + if (handler) { + handler.prevented = true; + } + return this; + } + + allowHandler(handler: EventHandler): this { + if (handler) { + handler.prevented = false; + } + return this; + } + getHandlers(level: EventBubbleLevel): EventHandler[] { return this._levelNodes.get(level)?.map(node => node.handler) || []; } + getAllHandlers(): EventHandler[] { + return Array.from(this._map.values()).map(node => node.handler) || []; + } + getCount() { return this._map.size; } diff --git a/packages/vchart/src/event/event-dispatcher.ts b/packages/vchart/src/event/event-dispatcher.ts index 6e05b0c25a..8709fd7d98 100644 --- a/packages/vchart/src/event/event-dispatcher.ts +++ b/packages/vchart/src/event/event-dispatcher.ts @@ -12,7 +12,8 @@ import type { EventParams, EventFilter, EventSourceType, - InteractionEventParam + InteractionEventParam, + EventCallback } from './interface'; import type { VChart } from '../core/vchart'; import type { CompilerListenerParameters } from '../compile/interface'; @@ -170,6 +171,32 @@ export class EventDispatcher implements IEventDispatcher { return this; } + prevent(eType: Evt, except?: EventCallback): this { + const eventTypes = ['canvas', 'chart', 'window'] as EventSourceType[]; + eventTypes.forEach(type => { + const bubble = this.getEventBubble(type).get(eType); + if (bubble) { + bubble.getAllHandlers().forEach(handler => { + if (!except || handler.callback !== except) { + bubble.preventHandler(handler); + } + }); + } + }); + return this; + } + + allow(eType: Evt): this { + const eventTypes = ['canvas', 'chart', 'window'] as EventSourceType[]; + eventTypes.forEach(type => { + const bubble = this.getEventBubble(type).get(eType); + if (bubble) { + bubble.getAllHandlers().forEach(handler => bubble.allowHandler(handler)); + } + }); + return this; + } + clear(): void { for (const entry of this._viewListeners.entries()) { this._compiler.removeEventListener(Event_Source_Type.chart, entry[0], entry[1]); @@ -333,7 +360,7 @@ export class EventDispatcher implements IEventDispatcher { ): boolean { const result = handlers.map(handler => { const filter = handler.filter as EventFilter; - if (!handler.query || this._filter(filter, type, params)) { + if (!handler.prevented && (!handler.query || this._filter(filter, type, params))) { const callback = handler.wrappedCallback || handler.callback; const stopBubble = callback.call(null, this._prepareParams(filter, params)); const doStopBubble = stopBubble ?? handler.query?.consume; diff --git a/packages/vchart/src/event/event.ts b/packages/vchart/src/event/event.ts index f2be49fd86..c06a8d7362 100644 --- a/packages/vchart/src/event/event.ts +++ b/packages/vchart/src/event/event.ts @@ -111,6 +111,16 @@ export class Event implements IEvent { return this; } + prevent(eType: Evt, except?: EventCallback) { + this._eventDispatcher.prevent(eType, except); + return this; + } + + allow(eType: Evt) { + this._eventDispatcher.allow(eType); + return this; + } + release(): void { this._eventDispatcher.clear(); this._composedEventMap.clear(); diff --git a/packages/vchart/src/event/interface.ts b/packages/vchart/src/event/interface.ts index 82d157cc5a..2ff9a42b4a 100644 --- a/packages/vchart/src/event/interface.ts +++ b/packages/vchart/src/event/interface.ts @@ -209,6 +209,8 @@ export type EventHandler = { wrappedCallback?: EventCallback; // 转换后的事件筛选配置 filter?: EventFilter; + // handler 是否被禁止触发 + prevented?: boolean; }; export type ExtendEventParam = EventParams & { @@ -316,6 +318,8 @@ export interface IEventDispatcher { dispatch: (eType: Evt, params?: EventParamsDefinition[Evt], level?: EventBubbleLevel) => this; clear: () => void; release: () => void; + prevent: (eType: Evt, except: EventCallback) => void; + allow: (eType: Evt) => void; } export interface IEvent { @@ -335,6 +339,8 @@ export interface IEvent { release: () => void; getComposedEventMap: () => Map, { eventType: EventType; event: IComposedEvent }>; + prevent: (eType: Evt, except: EventCallback) => void; + allow: (eType: Evt) => void; } export interface IComposedEvent { diff --git a/packages/vchart/src/interaction/zoom/zoomable.ts b/packages/vchart/src/interaction/zoom/zoomable.ts index 49eee1fae6..b2c26d3fcc 100644 --- a/packages/vchart/src/interaction/zoom/zoomable.ts +++ b/packages/vchart/src/interaction/zoom/zoomable.ts @@ -164,7 +164,6 @@ export class Zoomable implements IZoomable { const zoomEndParams: [string] | [string, EventQuery] = this._isGestureListener ? [this._getZoomTriggerEvent('zoomEnd')] : [this._getZoomTriggerEvent('zoomEnd'), { level: Event_Bubble_Level.chart, consume: false }]; - // pc端没有scrollEnd事件,所以漫游模式下scroll仅支持realTime (event as any).on( ...zoomEndParams, @@ -469,12 +468,16 @@ export class Zoomable implements IZoomable { this._zoomableTrigger.pointerId = null; this._eventObj.off(move, { level: Event_Bubble_Level.chart, source: Event_Source_Type.chart }, mousemove as any); this._eventObj.off(end, { level: Event_Bubble_Level.chart, source: Event_Source_Type.window }, mouseup as any); + this._eventObj.allow(end); }, delayTime); + const mousemove = delayMap[delayType]((params: BaseEventParams) => { if (!this._zoomableTrigger.parserDragEvent(params.event)) { return; } this._clickEnable = false; + this._eventObj.prevent(end, mouseup as any); + const event = params.event; const dx = event.canvasX - moveX; const dy = event.canvasY - moveY;