Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/vchart/src/component/tooltip/processor/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ export abstract class BaseTooltipProcessor {
return TooltipResult.failed;
};

protected _getTooltipContent = (data: TooltipData | undefined, params: TooltipHandlerParams): ITooltipActual => {
if (isNil(data)) {
return null;
}

this.clearCache();

// 更新 this._cacheActiveSpec
this._updateViewSpec(data, params);
return this._cacheActiveSpec;
};

protected _preprocessDimensionInfo(dimensionInfo?: IDimensionInfo[]): IDimensionInfo[] | undefined {
const newDimensionInfo: IDimensionInfo[] = [];
dimensionInfo?.forEach(info => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ export class DimensionTooltipProcessor extends BaseTooltipProcessor {
return targetDimensionInfo;
}

getTooltipContent(info: DimensionTooltipInfo, params: BaseEventParams, changePositionOnly: boolean) {
const newParams: TooltipHandlerParams = {
...(params as TooltipHandlerParams),
dimensionInfo: this._preprocessDimensionInfo(info),
changePositionOnly,
tooltip: this.component
};
return this._getTooltipContent(info, newParams);
}

/** 获取触发 tooltip 需要的信息 */
getMouseEventData(params: BaseEventParams): MouseEventData {
return {
Expand Down
2 changes: 2 additions & 0 deletions packages/vchart/src/component/tooltip/processor/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { IDimensionInfo } from '../../../event/events/dimension/interface';
import type { Datum } from '../../../typings/common';
import type { BaseEventParams } from '../../../event/interface';
import type { ITooltip, TooltipResult } from '../interface/common';
import type { ITooltipActual } from '../../../typings';

export type DimensionTooltipInfo = IDimensionInfo[];

Expand All @@ -29,6 +30,7 @@ export interface ITooltipProcessor<T> {
clearCache: () => void;
showTooltip: (info: T, params: BaseEventParams, changePositionOnly: boolean) => TooltipResult;
getMouseEventData: (params: BaseEventParams) => MouseEventData;
getTooltipContent: (info: T, params: BaseEventParams, changePositionOnly: boolean) => ITooltipActual;
}

export interface ITooltipProcessorConstructor {
Expand Down
55 changes: 55 additions & 0 deletions packages/vchart/src/component/tooltip/processor/mark-tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,61 @@ export class MarkTooltipProcessor extends BaseTooltipProcessor {
return this._showTooltipByHandler(tooltipData, newParams);
}

getTooltipContent(info: MarkTooltipInfo, params: BaseEventParams, changePositionOnly: boolean) {
const { datum, series } = info;
const tooltipSpec = this.component.getSpec();
const tooltipData = [{ datum: [datum], series }];
const helper = series.tooltipHelper;
const seriesSpec = series.getSpec()?.tooltip as ITooltipSpec;
const seriesCheckOverlap = seriesSpec?.mark?.checkOverlap;
let checkOverlap = false;

if (seriesCheckOverlap === true || (tooltipSpec.mark?.checkOverlap === true && seriesCheckOverlap !== false)) {
const activeTriggers = helper?.activeTriggerSet.mark;

if (activeTriggers) {
checkOverlap = true;
const chart = this.component.getChart();
// compute layer offset
const layer = chart.getCompiler().getStage().getLayer(undefined);
const point = { x: params.event.viewX, y: params.event.viewY };
layer.globalTransMatrix.transformPoint({ x: params.event.viewX, y: params.event.viewY }, point);

activeTriggers.forEach(mark => {
mark.getGraphics().forEach(g => {
if (
g !== params.node &&
g &&
g.containsPoint(point.x, point.y, IContainPointMode.GLOBAL, g.stage.getPickerService())
) {
tooltipData[0].datum.push(getDatumOfGraphic(g));
}
});
});
}
}

const newParams: TooltipHandlerParams = {
...(params as any),
model: series, // 在 label 支持 mark tooltip 后,eventParam.model 可能是 label 组件,而 tooltip 中需要的是 series
changePositionOnly,
tooltip: this.component
};
if (changePositionOnly && checkOverlap) {
const cacheData = this._cacheActiveSpec && this._cacheActiveSpec.data;

if (
!cacheData ||
(cacheData as IDimensionData[])[0].series !== tooltipData[0].series ||
(cacheData as IDimensionData[])[0].datum.length !== tooltipData[0].datum.length ||
(cacheData as IDimensionData[])[0].datum.some((d, index) => d !== tooltipData[0].datum[index])
) {
newParams.changePositionOnly = false;
}
}
return this._getTooltipContent(tooltipData, newParams);
}

/** 获取触发 tooltip 需要的信息 */
getMouseEventData(params: BaseEventParams): MouseEventData {
let info: MarkTooltipInfo | undefined;
Expand Down
4 changes: 2 additions & 2 deletions packages/vchart/src/component/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,10 +611,10 @@ export class Tooltip extends BaseComponent<any> implements ITooltip {
}

const result = showTooltip(datum, options, this);
if (result !== 'none') {
if (result !== null) {
this._alwaysShow = !!options?.alwaysShow;
}
return result;
return result === null ? 'none' : result;
}

/** 手动隐藏 tooltip,返回是否成功 */
Expand Down
96 changes: 67 additions & 29 deletions packages/vchart/src/component/tooltip/utils/show-tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { Tooltip } from '../tooltip';
import type { IComponentOption } from '../../interface';
import { isDiscrete } from '@visactor/vscale';
import type { TooltipHandlerParams } from '../interface/common';
import type { DimensionTooltipInfo, MarkTooltipInfo } from '../processor';

const getDataArrayFromFieldArray = (fields: string[], datum?: Datum) =>
isValid(datum) ? fields.map(f => datum[f]) : undefined;
Expand Down Expand Up @@ -43,7 +44,38 @@ type MarkInfo = {
dimType?: string;
};

export function showTooltip(datum: Datum, options: IShowTooltipOption, component: Tooltip): TooltipActiveType | 'none' {
export function showTooltip(datum: Datum, options: IShowTooltipOption, component: Tooltip): TooltipActiveType | null {
const mockInfo = getTooltipMockInfo(datum, options, component);
if (mockInfo === null) {
return null;
}
const componentOptions = component.getOption() as IComponentOption;
const { info, params, activeType } = mockInfo;

if (activeType === 'dimension') {
component.processor.dimension.showTooltip(info as DimensionTooltipInfo, params, false);
} else if (activeType === 'mark') {
component.processor.mark.showTooltip(info as MarkTooltipInfo, params, false);
}

// 全局唯一 tooltip
const vchart = componentOptions.globalInstance;
if (VChart.globalConfig.uniqueTooltip) {
VChart.hideTooltip(vchart.id);
}

return activeType;
}

export function getTooltipMockInfo(
datum: Datum,
options: IShowTooltipOption,
component: Tooltip
): {
info: DimensionTooltipInfo | MarkTooltipInfo;
params: TooltipHandlerParams;
activeType: TooltipActiveType;
} | null {
const opt: IShowTooltipOption = {
regionIndex: 0,
...options
Expand All @@ -56,7 +88,7 @@ export function showTooltip(datum: Datum, options: IShowTooltipOption, component
isValid(opt.regionIndex) ? [opt.regionIndex] : undefined
)[0];
if (!region) {
return 'none';
return null;
}

// 查询图元信息
Expand Down Expand Up @@ -99,11 +131,11 @@ export function showTooltip(datum: Datum, options: IShowTooltipOption, component
};
};

// 显示tooltip
// 获取 tooltip 内容
if (activeType === 'dimension') {
const firstInfo = markInfoList[0];
if (!firstInfo) {
return 'none';
return null;
}

// 将markInfoList按系列分组
Expand All @@ -128,7 +160,7 @@ export function showTooltip(datum: Datum, options: IShowTooltipOption, component
];

if (isValid(firstInfo.dimType)) {
mockDimensionInfo[0].position = firstInfo.pos[firstInfo.dimType];
mockDimensionInfo[0].position = firstInfo.pos[firstInfo.dimType as keyof IPoint];
mockDimensionInfo[0].dimType = firstInfo.dimType;
}

Expand All @@ -147,20 +179,15 @@ export function showTooltip(datum: Datum, options: IShowTooltipOption, component
}),
item: undefined
};

component.processor.dimension.showTooltip(mockDimensionInfo, mockParams, false);

// 全局唯一 tooltip
const vchart = componentOptions.globalInstance;
if (VChart.globalConfig.uniqueTooltip) {
VChart.hideTooltip(vchart.id);
}

return activeType;
return {
info: mockDimensionInfo,
params: mockParams,
activeType
};
} else if (activeType === 'mark') {
const info = markInfoList[0];
if (!info) {
return 'none';
return null;
}
const mockDatum = {
...getOriginDatum(info),
Expand Down Expand Up @@ -191,24 +218,35 @@ export function showTooltip(datum: Datum, options: IShowTooltipOption, component
item: undefined
} as any;

component.processor.mark.showTooltip(
{
return {
info: {
datum: mockDatum,
mark: null,
series: info.series
},
mockParams,
false
);

// 全局唯一 tooltip
const vchart = componentOptions.globalInstance;
if (VChart.globalConfig.uniqueTooltip) {
VChart.hideTooltip(vchart.id);
}
return activeType;
params: mockParams,
activeType
};
}
return null;
}

export function getTooltipContent(datum: Datum, options: IShowTooltipOption, component: Tooltip) {
const mockInfo = getTooltipMockInfo(datum, options, component);
if (mockInfo === null) {
return null;
}
const { info, params, activeType } = mockInfo;

// 需要初始化 tooltip processor
// @ts-ignore
component._initProcessor();
if (activeType === 'dimension') {
return component.processor.dimension.getTooltipContent(info as DimensionTooltipInfo, params, false);
} else if (activeType === 'mark') {
return component.processor.mark.getTooltipContent(info as MarkTooltipInfo, params, false);
}
return 'none';
return null;
}

export const getMarkInfoList = (datum: Datum, region: IRegion) => {
Expand Down
14 changes: 13 additions & 1 deletion packages/vchart/src/core/vchart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import type { IMark, IMarkGraphic, MarkConstructor } from '../mark/interface';
import { registerDataSetInstanceParser, registerDataSetInstanceTransform } from '../data/register';
import { dataToDataView } from '../data/initialize';
import { copyDataView } from '../data/transforms/copy-data-view';
import type { ITooltipHandler } from '../typings/tooltip';
import type { ITooltipActual, ITooltipHandler } from '../typings/tooltip';
import type { Tooltip } from '../component/tooltip';
import type {
Datum,
Expand Down Expand Up @@ -117,6 +117,7 @@ import { registerElementHighlight } from '../interaction/triggers/element-highli
import { registerElementSelect } from '../interaction/triggers/element-select';
import type { IVChartPluginService } from '../plugin/vchart/interface';
import { VChartPluginService } from '../plugin/vchart/plugin-service';
import { getTooltipContent } from '../component/tooltip/utils/show-tooltip';

export class VChart implements IVChart {
readonly id = createID();
Expand Down Expand Up @@ -1642,6 +1643,17 @@ export class VChart implements IVChart {
return (isValid(datum) && tooltip?.showTooltip(datum, options) !== 'none') ?? false;
}

/**
* 获取 tooltip 内容
* @param datum 原始数据
* @param options
* @returns
*/
getTooltipContent(datum: Datum, options: IShowTooltipOption): ITooltipActual | null {
const tooltip = this._getTooltipComponent();
return getTooltipContent(datum, options, tooltip);
}

/**
* 手动调用,关闭 tooltip
* @returns
Expand Down
Loading