Skip to content

Commit

Permalink
feat(v2/radar): 自定义 radar tooltip,允许横向对比显示 tooltip (#1337)
Browse files Browse the repository at this point in the history
* feat(v2/radar): 自定义 radar tooltip,允许横向对比显示 tooltip

* refactor(v2/radar): 修改雷达图 cr 建议

* refactor(v2/radar): 修改 cr 建议

* feat(v2/radar): 增加 xy crosshairs 的tooltip demo
  • Loading branch information
visiky authored Jul 27, 2020
1 parent 758b4e3 commit f9e1e5c
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 18 deletions.
34 changes: 22 additions & 12 deletions __tests__/data/radar.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
const categories = ['销售', '市场营销', '发展', '客户支持', '信息技术', '行政管理'];
/** 预算支出 */
const data1 = [43000, 19000, 60000, 35000, 17000, 10000];
/** 实际支出 */
const data2 = [50000, 39000, 42000, 31000, 26000, 14000];

export const SINGLE_DATA = categories.map((d, idx) => ({ name: d, value: data1[idx] }));
export const SERIES_DATA = [];
categories.forEach((d, idx) => {
SERIES_DATA.push({ name: d, value: data1[idx], type: '预算支出' });
SERIES_DATA.push({ name: d, value: data2[idx], type: '实际支出' });
});
export const SINGLE_DATA = [
{ name: '销售', value: 43000 },
{ name: '市场营销', value: 19000 },
{ name: '发展', value: 60000 },
{ name: '客户支持', value: 35000 },
{ name: '信息技术', value: 17000 },
{ name: '行政管理', value: 10000 },
];
export const SERIES_DATA = [
{ name: '销售', value: 43000, type: '预算支出' },
{ name: '销售', value: 50000, type: '实际支出' },
{ name: '市场营销', value: 19000, type: '预算支出' },
{ name: '市场营销', value: 39000, type: '实际支出' },
{ name: '发展', value: 60000, type: '预算支出' },
{ name: '发展', value: 42000, type: '实际支出' },
{ name: '客户支持', value: 35000, type: '预算支出' },
{ name: '客户支持', value: 31000, type: '实际支出' },
{ name: '信息技术', value: 17000, type: '预算支出' },
{ name: '信息技术', value: 26000, type: '实际支出' },
{ name: '行政管理', value: 10000, type: '预算支出' },
{ name: '行政管理', value: 14000, type: '实际支出' },
];
4 changes: 2 additions & 2 deletions __tests__/unit/plots/pie/interaction-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('register interaction', () => {
context.event = { data: { data: { type: 'item3', value: 13 } } };
action.change();

delay(5000);
delay(500);
const annotations = context.view.getComponents().filter((co) => co.type === 'annotation');
expect(annotations[0].extra.content).toBe('item3');
expect(annotations[1].extra.content).toBe(13);
Expand All @@ -52,7 +52,7 @@ describe('register interaction', () => {
it('触发 pie-statistic:reset', async () => {
action.reset();

delay(5000);
delay(500);
const annotations = context.view.getComponents().filter((co) => co.type === 'annotation');
expect(annotations[0].extra.content).toBe('Total');
});
Expand Down
6 changes: 3 additions & 3 deletions __tests__/unit/plots/pie/statistic-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ describe('中心文本 - 指标卡', () => {
});

it('自定义中心文本内容: update statistic title & content, 动态数据', async () => {
await delay(5000);
await delay(500);
pie.update({
...pie.options,
statistic: {
Expand Down Expand Up @@ -161,7 +161,7 @@ describe('中心文本 - 指标卡', () => {
});

it('自定义中心文本样式: update statistic title style & content style', async () => {
await delay(5000);
await delay(500);
pie.update({
...pie.options,
statistic: {
Expand Down Expand Up @@ -249,7 +249,7 @@ describe('中心文本 - 指标卡', () => {
// expect(annotations.length).toBe(1);
// expect(annotations[0].component.get('type')).toBe('image');

// await delay(5000);
// await delay(500);
// pie.update({
// ...pie.options,
// annotations: [
Expand Down
117 changes: 116 additions & 1 deletion __tests__/unit/plots/radar/tooltip-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Radar } from '../../../../src';
import { SERIES_DATA } from '../../../data/radar';
import { SINGLE_DATA, SERIES_DATA } from '../../../data/radar';
import { createDiv } from '../../../utils/dom';

describe('radar tooltip', () => {
Expand All @@ -25,3 +25,118 @@ describe('radar tooltip', () => {
expect(radar.chart.options.tooltip.showCrosshairs).toBe(true);
});
});

describe('radar, 自定义 tooltip', () => {
it('xField*yField', () => {
const radar = new Radar(createDiv(), {
width: 400,
height: 300,
data: SINGLE_DATA,
xField: 'name',
yField: 'value',
radius: 0.8,
tooltip: {
title: '开销',
},
interactions: [{ name: 'radar-tooltip' }],
});

radar.render();
expect(radar.chart).toBeDefined();
expect(radar.chart.geometries.length).toBe(1);
expect(radar.chart.geometries[0].elements.length).toBe(1);
});

it('xField*yField*seriesField', () => {
const radar = new Radar(createDiv(), {
width: 400,
height: 300,
data: SERIES_DATA,
xField: 'name',
yField: 'value',
seriesField: 'type',
radius: 0.8,
tooltip: {
shared: false,
},
interactions: [{ name: 'radar-tooltip' }],
});

radar.render();
expect(radar.chart).toBeDefined();
expect(radar.chart.geometries.length).toBe(1);
expect(radar.chart.geometries[0].elements.length).toBe(2);
expect(radar.chart.interactions['radar-tooltip']).toBeDefined();
});

it('xField*yField*seriesField, with sharedTooltip', () => {
const radar = new Radar(createDiv(), {
width: 400,
height: 300,
data: SERIES_DATA,
xField: 'name',
yField: 'value',
seriesField: 'type',
radius: 0.8,
tooltip: {
showTitle: false,
shared: true,
itemTpl: `<li class="g2-tooltip-list-item" data-index={index} style="margin-bottom:4px;display:flex;">
<span style="background-color:{color};" class="g2-tooltip-marker"></span>
<span style="display:inline-flex;flex:1;justify-content:space-between">
<span>{name}:{title}</span><span>{value}</span>
</span>
</li>`,
},
interactions: [{ name: 'radar-tooltip' }],
});

radar.render();
expect(radar.chart).toBeDefined();
expect(radar.chart.geometries.length).toBe(1);
expect(radar.chart.geometries[0].elements.length).toBe(2);
});

it('"xy" crosshairs', () => {
const radar = new Radar(createDiv(), {
width: 400,
height: 300,
data: SERIES_DATA,
xField: 'name',
yField: 'value',
seriesField: 'type',
radius: 0.8,
tooltip: {
shared: true,
showCrosshairs: true,
crosshairs: {
type: 'xy',
line: {
style: {
stroke: '#565656',
lineDash: [4],
},
},
follow: true,
},
},
interactions: [
{
name: 'radar-tooltip',
cfg: {
start: [{ trigger: 'plot:mousemove', action: 'radar-tooltip:show' }],
end: [{ trigger: 'plot:mouseleave', action: 'radar-tooltip:hide' }],
},
},
],
});

radar.render();
const tooltipController = radar.chart.getController('radar-tooltip');
// @ts-ignore
const tooltipCfg = tooltipController.getTooltipCfg();
expect(tooltipCfg.shared).toBe(true);
expect(tooltipCfg.showCrosshairs).toBe(true);
expect(tooltipCfg.crosshairs.type).toBe('xy');
});
});
1 change: 1 addition & 0 deletions src/plots/radar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Plot } from '../../core/plot';
import { Adaptor } from '../../core/adaptor';
import { RadarOptions } from './types';
import { adaptor } from './adaptor';
import './interaction';

export { RadarOptions };

Expand Down
8 changes: 8 additions & 0 deletions src/plots/radar/interaction/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { registerAction, registerInteraction } from '@antv/g2';
import { RadarTooltipAction } from './radar-tooltip-action';

registerAction('radar-tooltip', RadarTooltipAction);
registerInteraction('radar-tooltip', {
start: [{ trigger: 'element:mouseenter', action: 'radar-tooltip:show' }],
end: [{ trigger: 'element:mouseleave', action: 'radar-tooltip:hide' }],
});
67 changes: 67 additions & 0 deletions src/plots/radar/interaction/radar-tooltip-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { registerComponentController } from '@antv/g2';
import { getTooltipItems } from '@antv/g2/lib/util/tooltip';
import TooltipController from '@antv/g2/lib/chart/controller/tooltip';
import { Action } from '@antv/g2/lib/interaction';
import { isNil } from '@antv/util';
import { Point } from '../../../types';

export class RadarTooltipController extends TooltipController {
public get name(): string {
return 'radar-tooltip';
}

public getTooltipItems(point: Point) {
const { shared, title: cfgTitle } = this.getTooltipCfg();
const hintItems = super.getTooltipItems(point);

if (hintItems.length > 0) {
const geometry = this.view.geometries[0];
const dataArray = geometry.dataArray;
const title = hintItems[0].name;
const result = [];
dataArray.forEach((mappingData) => {
mappingData.forEach((d) => {
const items = getTooltipItems(d, geometry);
const item = items[0];
if (!shared && item && item.name === title) {
const displayTitle = isNil(cfgTitle) ? title : cfgTitle;
result.push({ ...item, name: item.title, title: displayTitle });
} else if (shared && item) {
const displayTitle = isNil(cfgTitle) ? item.name || title : cfgTitle;
result.push({ ...item, name: item.title, title: displayTitle });
}
});
});

return result;
}
return [];
}
}
registerComponentController('radar-tooltip', RadarTooltipController);

/**
* 雷达图 tooltip 激活 action
*/
export class RadarTooltipAction extends Action {
init() {
const { view } = this.context;
view.removeInteraction('tooltip');
}

public show() {
const { event } = this.context;
const controller = this.getTooltipController();
controller.showTooltip({ x: event.x, y: event.y });
}

public hide() {
const controller = this.getTooltipController();
controller.hideTooltip();
}

private getTooltipController() {
const { view } = this.context;
return view.getController('radar-tooltip') as TooltipController;
}
}
2 changes: 2 additions & 0 deletions src/plots/radar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { Options } from '../../types';
import { ShapeStyle } from '../../types/style';

export interface RadarOptions extends Options {
/** x 字段 */
readonly xField: string;
/** y 字段,映射雷达图的射线长度 */
readonly yField: string;
/** 分组字段 */
readonly seriesField?: string;
Expand Down

0 comments on commit f9e1e5c

Please sign in to comment.