Skip to content

Commit

Permalink
feat(tooltip): add marker
Browse files Browse the repository at this point in the history
  • Loading branch information
pearmini committed Aug 17, 2023
1 parent 328aeea commit bba8eb2
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 24 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions __tests__/plots/interaction/index.ts
Expand Up @@ -68,3 +68,4 @@ export { mockAreaSliderFilterLabel } from './mock-area-slider-filter-label';
export { commitsPointLegendFilter } from './commits-point-legend-filter';
export { settleWeatherLegendFilter } from './seattle-weather-legend-filter';
export { countriesBubbleMultiLegends } from './countries-bubble-multi-legends';
export { pointsPointTooltipMarker } from './points-point-tooltip-marker';
1 change: 1 addition & 0 deletions __tests__/plots/interaction/indices-line-chart-facet.ts
Expand Up @@ -40,6 +40,7 @@ export async function indicesLineChartFacet(): Promise<G2Spec> {
body: false,
crosshairs: true,
crosshairsStrokeWidth: 30,
marker: false,
},
},
};
Expand Down
Expand Up @@ -17,7 +17,7 @@ export function pointsPointRegressionQuadInset(): G2Spec {
scale: { x: { domain: [-4, 4] }, y: { domain: [-2, 14] } },
axis: { x: { title: false }, y: { title: false } },
interaction: {
tooltip: { body: false, crosshairsStrokeWidth: 30 },
tooltip: { body: false, crosshairsStrokeWidth: 30, marker: false },
},
children: [
{
Expand Down
Expand Up @@ -16,7 +16,7 @@ export function pointsPointRegressionQuadTranspose(): G2Spec {
scale: { x: { domain: [-4, 4] }, y: { domain: [-2, 14] } },
axis: { x: { title: false }, y: { title: false } },
interaction: {
tooltip: { body: false, crosshairsStrokeWidth: 30 },
tooltip: { body: false, crosshairsStrokeWidth: 30, marker: false },
},
coordinate: { transform: [{ type: 'transpose' }] },
children: [
Expand Down
Expand Up @@ -16,7 +16,7 @@ export function pointsPointRegressionQuad(): G2Spec {
scale: { x: { domain: [-4, 4] }, y: { domain: [-2, 14] } },
axis: { x: { title: false }, y: { title: false } },
interaction: {
tooltip: { body: false, crosshairsStrokeWidth: 30 },
tooltip: { body: false, crosshairsStrokeWidth: 30, marker: false },
},
children: [
{
Expand Down
53 changes: 53 additions & 0 deletions __tests__/plots/interaction/points-point-tooltip-marker.ts
@@ -0,0 +1,53 @@
import { regressionQuad } from 'd3-regression';
import { G2Spec, PLOT_CLASS_NAME } from '../../../src';
import { points } from '../../data/points';
import { step } from './utils';

const regression = regressionQuad()
.x((d) => d.x)
// @ts-ignore
.y((d) => d.y)
.domain([-4, 4]);

export function pointsPointTooltipMarker(): G2Spec {
return {
type: 'line',
inset: 30,
data: {
value: points,
transform: [{ type: 'custom', callback: regression }],
},
encode: {
x: (d) => d[0],
y: (d) => d[1],
},
style: {
stroke: '#30BF78',
lineWidth: 2,
},
scale: { x: { domain: [-4, 4] }, y: { domain: [-2, 14] } },
axis: { x: { title: false }, y: { title: false } },
interaction: {
tooltip: {
body: false,
crosshairs: false,
markerR: 20,
markerStrokeWidth: 5,
markerStroke: 'yellow',
},
},
};
}

pointsPointTooltipMarker.tooltip = true;

pointsPointTooltipMarker.steps = ({ canvas }) => {
const { document } = canvas;
const [plot] = document.getElementsByClassName(PLOT_CLASS_NAME);
return [
step(plot, 'pointermove', {
offsetX: 450,
offsetY: 350,
}),
];
};
1 change: 1 addition & 0 deletions __tests__/plots/interaction/score-by-item-area-radar.ts
Expand Up @@ -19,6 +19,7 @@ export function scoreByItemAreaRadar(): G2Spec {
interaction: {
tooltip: {
body: false,
marker: false,
crosshairsLineDash: [4, 4],
crosshairsStrokeWidth: 10,
},
Expand Down
1 change: 1 addition & 0 deletions __tests__/plots/tooltip/indices-line-chart-facet.ts
Expand Up @@ -38,6 +38,7 @@ export async function indicesLineChartFacet(): Promise<G2Spec> {
series: true,
facet: true,
crosshairs: true,
marker: false,
},
},
};
Expand Down
36 changes: 19 additions & 17 deletions site/docs/spec/interaction/tooltip.zh.md
Expand Up @@ -34,23 +34,25 @@ chart.render();

## 选项

| 属性 | 描述 | 类型 | 默认值 |
| ------------------------- | ------------------------------------------- | ------------------------------------------- | ------------ |
| wait | 提示信息更新的时间间隔,单位为毫秒 | `number` | 50 |
| leading | 是否在时间间隔开始的时候更新提示信息 | `boolean` | true |
| trailing | 是否在时间间隔结束的时候更新提示信息 | `boolean` | false |
| shared | 相同 x 的元素是否共享 tooltip | `boolean` | false |
| series | 是否是系列元素的 tooltip | `boolean` | - |
| body | 是否展示 tooltip | `boolean` | true |
| groupName | 是否使用 groupName | `boolean` | true |
| position | tooltip 位置 | `TooltipPosition` | - |
| mount | tooltip 渲染的 dom 节点 | `string` \| `HTMLElement` | 图表容器 |
| bounding | tooltip 渲染的限制区域,超出会自动调整位置 | `BBox` | 图表区域大小 |
| crosshairs | 是否暂时指示线 | `boolean` | - |
| `crosshairs${StyleAttrs}` | 指示线的样式 | `number \| string` | - |
| render | 自定义 tooltip 渲染函数 | `(event, options) => HTMLElement \| string` | - |
| sort | item 排序器 | `(d: TooltipItemValue) => any` | - |
| filter | item 筛选器 | `(d: TooltipItemValue) => any` | - |
| 属性 | 描述 | 类型 | 默认值 |
| ------------------------- | -------------------------------------------- | ------------------------------------------- | ------------ |
| wait | 提示信息更新的时间间隔,单位为毫秒 | `number` | 50 |
| leading | 是否在时间间隔开始的时候更新提示信息 | `boolean` | true |
| trailing | 是否在时间间隔结束的时候更新提示信息 | `boolean` | false |
| shared | 相同 x 的元素是否共享 tooltip | `boolean` | false |
| series | 是否是系列元素的 tooltip | `boolean` | - |
| body | 是否展示 tooltip | `boolean` | true |
| marker | 是否展示 marker | `boolean` | true |
| groupName | 是否使用 groupName | `boolean` | true |
| position | tooltip 位置 | `TooltipPosition` | - |
| mount | tooltip 渲染的 dom 节点 | `string` \| `HTMLElement` | 图表容器 |
| bounding | tooltip 渲染的限制区域,超出会自动调整位置 | `BBox` | 图表区域大小 |
| crosshairs | 是否暂时指示线 | `boolean` | - |
| `crosshairs${StyleAttrs}` | 指示线的样式 | `number \| string` | - |
| `marker${StyleAttrs}` | marker 的样式 | `number \| string` | - |
| render | 自定义 tooltip 渲染函数 | `(event, options) => HTMLElement \| string` | - |
| sort | item 排序器 | `(d: TooltipItemValue) => any` | - |
| filter | item 筛选器 | `(d: TooltipItemValue) => any` | - |
| disableNative | 是否响应原生事件(pointerover 和 pointerout) | true | `boolean` |

```ts
Expand Down
50 changes: 47 additions & 3 deletions src/interaction/tooltip.ts
@@ -1,4 +1,4 @@
import { DisplayObject, IElement, Line } from '@antv/g';
import { Circle, DisplayObject, IElement, Line } from '@antv/g';
import { sort, group, mean, bisector, minIndex } from 'd3-array';
import { deepMix, lowerFirst, throttle } from '@antv/util';
import { Tooltip as TooltipComponent } from '@antv/gui';
Expand Down Expand Up @@ -333,6 +333,38 @@ function hideRuleY(root) {
}
}

function updateMarker(root, { data, style, items }) {
if (root.markers) root.markers.forEach((d) => d.remove());
const markers = data.map((d) => {
const [{ color, element }, point] = d;
const fill =
color || // encode value
element.style.fill ||
element.style.stroke;
const shape = new Circle({
style: {
cx: point[0],
cy: point[1],
fill,
r: 4,
stroke: '#fff',
strokeWidth: 2,
...style,
},
});
return shape;
});
for (const marker of markers) root.appendChild(marker);
root.markers = markers;
}

function hideMarker(root) {
if (root.markers) {
root.markers.forEach((d) => d.remove());
root.markers = [];
}
}

function interactionKeyof(markState, key) {
return Array.from(markState.values()).some(
// @ts-ignore
Expand Down Expand Up @@ -384,6 +416,7 @@ export function seriesTooltip(
mount,
bounding,
disableNative = false,
marker = true,
style: _style = {},
...rest
}: Record<string, any>,
Expand Down Expand Up @@ -430,7 +463,6 @@ export function seriesTooltip(
}),
);

const ruleStyle = subObject(style, 'crosshairs');
const { x: scaleX } = scale;

// Apply offset for band scale x.
Expand Down Expand Up @@ -499,7 +531,7 @@ export function seriesTooltip(
const d = seriesData(element, index);
const { x, y } = d;
const p = coordinate.map([(x || 0) + offsetX, y || 0]);
selectedSeriesData.push([d, p] as const);
selectedSeriesData.push([{ ...d, element }, p] as const);
}
}

Expand Down Expand Up @@ -557,6 +589,7 @@ export function seriesTooltip(

if (crosshairs) {
const points = filteredSeriesData.map((d) => d[1]);
const ruleStyle = subObject(style, 'crosshairs');
updateRuleY(root, points, {
...ruleStyle,
plotWidth,
Expand All @@ -572,6 +605,15 @@ export function seriesTooltip(
});
}

if (marker) {
const markerStyles = subObject(style, 'marker');
updateMarker(root, {
data: filteredSeriesData,
items: tooltipData.items,
style: markerStyles,
});
}

emitter.emit('tooltip:show', {
...event,
nativeEvent: true,
Expand All @@ -585,6 +627,7 @@ export function seriesTooltip(
const hide = () => {
hideTooltip({ root, single, emitter, mount });
if (crosshairs) hideRuleY(root);
if (marker) hideMarker(root);
};

const onTooltipShow = ({ nativeEvent, data }) => {
Expand Down Expand Up @@ -622,6 +665,7 @@ export function seriesTooltip(
emitter.off('tooltip:hide', onTooltipHide);
destroyTooltip(root);
if (crosshairs) hideRuleY(root);
if (marker) hideMarker(root);
};
}

Expand Down
4 changes: 3 additions & 1 deletion src/spec/interaction.ts
Expand Up @@ -175,6 +175,7 @@ export type TooltipInteraction = {
facet?: boolean;
body?: boolean;
crosshairs?: boolean;
marker?: boolean;
groupName?: boolean;
position?: TooltipStyleProps['position'];
bounding?: BBox;
Expand All @@ -186,7 +187,8 @@ export type TooltipInteraction = {
event, // @todo
options: { title: 'string'; items: TooltipItemValue[] },
) => HTMLElement | string;
} & Record<`crosshairs${any}`, any>;
} & Record<`crosshairs${any}`, any> &
Record<`marker${any}`, any>;

export type FisheyeInteraction = {
type?: 'fisheye';
Expand Down

0 comments on commit bba8eb2

Please sign in to comment.