Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: tooltip enterable and showDelay #310

Merged
merged 5 commits into from
Dec 11, 2023
Merged
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
2 changes: 1 addition & 1 deletion __tests__/integration/components/tooltip/tooltip-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const Tooltip1 = () => {

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', (e: any) => {
tooltip.show(e.offsetX, e.offsetY);
Expand Down
7 changes: 4 additions & 3 deletions __tests__/integration/components/tooltip/tooltip-10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,20 @@ export const Tooltip10 = () => {
{ value: 1.2312323, name: '第四项', index: 1, color: 'green' },
{ value: 1.2312323, name: '第五项', index: 1, color: 'blue' },
],
enterable: true,
},
})
);

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', (e: any) => {
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseleave', () => {
tooltip.hide();
group.addEventListener('mouseleave', (e: any) => {
tooltip.hide(e.clientX, e.clientY);
});

return group;
Expand Down
17 changes: 3 additions & 14 deletions __tests__/integration/components/tooltip/tooltip-2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,15 @@ export const Tooltip2 = () => {
);

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
let isPointerInTooltip = false;
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
});
tooltip.getContainer().addEventListener('mouseenter', () => {
isPointerInTooltip = true;
});
tooltip.getContainer().addEventListener('mouseleave', () => {
isPointerInTooltip = false;
tooltip.show(e.offsetX, e.offsetY);
});

group.addEventListener('mouseenter', () => {
tooltip.show();
});
group.addEventListener('mouseleave', () => {
timeout(() => {
if (!isPointerInTooltip) {
tooltip.hide();
}
});
group.addEventListener('mouseleave', (e: any) => {
tooltip.hide(e.clientX, e.clientY);
});
return group;
};
Expand Down
2 changes: 1 addition & 1 deletion __tests__/integration/components/tooltip/tooltip-3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const Tooltip3 = () => {

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', () => {
tooltip.show();
Expand Down
6 changes: 3 additions & 3 deletions __tests__/integration/components/tooltip/tooltip-4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export const Tooltip4 = () => {

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', () => {
tooltip.show();
});
group.addEventListener('mouseleave', () => {
tooltip.hide();
group.addEventListener('mouseleave', (e: any) => {
tooltip.hide(e.offsetX, e.offsetY);
});
return group;
};
Expand Down
2 changes: 1 addition & 1 deletion __tests__/integration/components/tooltip/tooltip-5.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const Tooltip5 = () => {

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', () => {
tooltip.show();
Expand Down
2 changes: 1 addition & 1 deletion __tests__/integration/components/tooltip/tooltip-6.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const Tooltip6 = () => {

document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
group.addEventListener('mousemove', (e: any) => {
tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
/** 1: 通过 React 渲染Tooltip节点 */
// ReactDOM.render(
// <div>
Expand Down
2 changes: 1 addition & 1 deletion __tests__/integration/components/tooltip/tooltip-7.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const Tooltip7 = () => {
document.getElementsByTagName('body')[0].appendChild(tooltip.HTMLTooltipElement);
}

tooltip.position = [e.offsetX, e.offsetY];
tooltip.show(e.offsetX, e.offsetY);
});
group.addEventListener('mouseenter', (e: any) => {
tooltip?.show(e.offsetX, e.offsetY);
Expand Down
77 changes: 58 additions & 19 deletions src/ui/tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { substitute, createDOM } from '@antv/util';
import { Component } from '../../core';
import { Group } from '../../shapes';
import { applyStyleSheet, throttle } from '../../util';
import { BBox, applyStyleSheet } from '../../util';
import { getClassNames, getDefaultTooltipStyle } from './constant';
import type { TooltipOptions, TooltipPosition, TooltipStyleProps } from './types';

Expand All @@ -10,6 +10,8 @@ export type { TooltipStyleProps, TooltipOptions };
export class Tooltip extends Component<TooltipStyleProps> {
public static tag = 'tooltip';

private timestamp = -1;

public get HTMLTooltipElement() {
return this.element;
}
Expand All @@ -18,12 +20,6 @@ export class Tooltip extends Component<TooltipStyleProps> {
return this.element;
}

public set position([x, y]: [number, number]) {
this.attributes.x = x;
this.attributes.y = y;
this.updatePosition();
}

private get elementSize() {
const width = this.element.offsetWidth;
const height = this.element.offsetHeight;
Expand Down Expand Up @@ -89,19 +85,32 @@ export class Tooltip extends Component<TooltipStyleProps> {
* 如果设置了坐标值,显示过程中会立即更新位置并关闭过渡动画
*/
public show(x?: number, y?: number) {
const disableTransition = x !== undefined && y !== undefined;
if (disableTransition) {
const transition = this.element.style.transition;
this.element.style.transition = 'none';
this.position = [x ?? +this.attributes.x, y ?? +this.attributes.y];
setTimeout(() => {
this.element.style.transition = transition;
}, 10);
if (x !== undefined && y !== undefined) {
const isToggle = this.element.style.visibility === 'hidden';
const setPosition = () => {
this.attributes.x = x ?? this.attributes.x;
this.attributes.y = y ?? this.attributes.y;
this.updatePosition();
};
// 只有从 hidden 状态变为 visible 状态时才需要关闭过渡动画
isToggle ? this.closeTransition(setPosition) : setPosition();
}
this.element.style.visibility = 'visible';
}

public hide() {
/**
* 如果 hide 时传入了坐标值,那么只有当鼠标不在 tooltip 上时才会隐藏
* 对于 enterable = true 的时候,需要传入 x y,为了避免问题,建议上层在使用的时候,都传入 x y
* @param x
* @param y
* @returns
*/
public hide(x = 0, y = 0) {
const { enterable } = this.attributes;

// 如果当前鼠标在 tooltip 上,则不隐藏
if (enterable && this.isCursorEntered(x, y)) return;

this.element.style.visibility = 'hidden';
}

Expand Down Expand Up @@ -186,10 +195,15 @@ export class Tooltip extends Component<TooltipStyleProps> {
/**
* 更新tooltip的位置
*/
@throttle(100, true)
private updatePosition() {
// 尝试当前的位置使用默认position能否放下
// 如果不能,则改变取溢出边的反向position
const { showDelay = 60 } = this.attributes;

const currentTimestamp = Date.now();
if (this.timestamp > 0 && currentTimestamp - this.timestamp < showDelay) return;

this.timestamp = currentTimestamp;
// 尝试当前的位置使用默认 position 能否放下
// 如果不能,则改变取溢出边的反向 position
/**
* 默认位置
* ⬇️
Expand Down Expand Up @@ -241,4 +255,29 @@ export class Tooltip extends Component<TooltipStyleProps> {
const correctedPositionString = correctivePosition.join('-');
return this.getRelativeOffsetFromCursor(correctedPositionString as TooltipPosition);
}

private isCursorEntered(clientX: number, clientY: number) {
// 是可捕获的,并且点在 tooltip dom 上
if (this.element) {
const { x, y, width, height } = this.element.getBoundingClientRect();
// const { container } = this.attributes;
// const { x: cx, y: cy } = container;

// console.log(1113, [clientX, clientY], [x, y, width, height], [cx, cy], new BBox(x - cx, y - cy, width, height).isPointIn(cursorX, cursorY));

return new BBox(x, y, width, height).isPointIn(clientX, clientY);
}
return false;
}

private closeTransition(callback: () => void) {
const transition = this.element.style.transition;
this.element.style.transition = 'none';

callback();

setTimeout(() => {
this.element.style.transition = transition;
}, 10);
}
}
2 changes: 2 additions & 0 deletions src/ui/tooltip/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export type TooltipStyleProps = GroupStyleProps & {
offset?: [number, number];
/** 指针是否可进入 */
enterable?: boolean;
/** 配合 enterable = true 使用,指定延迟显示的毫秒数,默认为 60ms */
showDelay?: number;
/** 画布的左上角坐标 */
container: {
x: number;
Expand Down
8 changes: 8 additions & 0 deletions src/util/bbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export class BBox {
left: this.left,
};
}

/**
* 点是否在 bbox 中
* @param p
*/
public isPointIn(x: number, y: number) {
return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom;
}
}

export function getRenderBBox(element: DisplayObject) {
Expand Down
Loading