| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import { reactive } from 'vue';
- export interface TriggerState {
- visible: boolean;
- x: number;
- y: number;
- }
- export interface TriggerHandle {
- state: TriggerState;
- onEnter: (e: MouseEvent) => void;
- onMove: (e: MouseEvent) => void;
- onLeave: () => void;
- onBtnEnter: () => void;
- onBtnLeave: () => void;
- destroy: () => void;
- }
- export interface TriggerOptions {
- /** 鼠标停顿多久后显示按钮 (ms),默认 400 */
- pauseDelay?: number;
- /** 按钮显示后多久自动消失 (ms),默认 3000 */
- hideDelay?: number;
- }
- /**
- * 创建一个悬浮按钮触发器实例。
- * 每个需要数据解读的 DOM 元素(卡片行、表格行、3D 标记等)对应一个 trigger。
- *
- * 使用方式:
- * 1. 在 v-for 中为每行数据 createTrigger()
- * 2. 将 onEnter/onMove/onLeave 绑定到容器元素的 mouseenter/mousemove/mouseleave
- * 3. 将 DataInterpretationBtn 放在容器内,绑定 state 和 onBtnEnter/onBtnLeave
- */
- export function createTrigger(options?: TriggerOptions): TriggerHandle {
- const PAUSE_DELAY = options?.pauseDelay ?? 400;
- const HIDE_DELAY = options?.hideDelay ?? 3000;
- const state = reactive<TriggerState>({
- visible: false,
- x: 0,
- y: 0,
- });
- let pauseTimer: ReturnType<typeof setTimeout> | null = null;
- let hideTimer: ReturnType<typeof setTimeout> | null = null;
- function trackMouse(e: MouseEvent) {
- const target = e.currentTarget as HTMLElement;
- const rect = target.getBoundingClientRect();
- state.x = e.clientX - rect.left - 36;
- state.y = e.clientY - rect.top - 34;
- }
- function startPauseTimer() {
- pauseTimer = setTimeout(() => {
- state.visible = true;
- startHideTimer();
- }, PAUSE_DELAY);
- }
- function resetPauseTimer() {
- if (pauseTimer) {
- clearTimeout(pauseTimer);
- pauseTimer = null;
- }
- }
- function startHideTimer() {
- clearHideTimer();
- hideTimer = setTimeout(() => {
- state.visible = false;
- }, HIDE_DELAY);
- }
- function clearHideTimer() {
- if (hideTimer) {
- clearTimeout(hideTimer);
- hideTimer = null;
- }
- }
- function onEnter(e: MouseEvent) {
- clearHideTimer();
- trackMouse(e);
- startPauseTimer();
- }
- function onMove(e: MouseEvent) {
- if (state.visible) return;
- trackMouse(e);
- resetPauseTimer();
- startPauseTimer();
- }
- function onLeave() {
- resetPauseTimer();
- clearHideTimer();
- state.visible = false;
- }
- function onBtnEnter() {
- clearHideTimer();
- }
- function onBtnLeave() {
- startHideTimer();
- }
- function destroy() {
- resetPauseTimer();
- clearHideTimer();
- }
- return {
- state,
- onEnter,
- onMove,
- onLeave,
- onBtnEnter,
- onBtnLeave,
- destroy,
- };
- }
|