回到课程

"Smart" 工具提示

重要程度: 5

编写一个函数,仅在访问者将鼠标移动到它上面而非通过它时,才会显示元素上的工具提示。

换句话说,如果访问者把鼠标移动到元素上,然后停下 —— 显示工具提示。如果访问者将鼠标快速移过元素,那就不需要显示,谁想要多余的内容呢?

从技术上说,我们可以测量鼠标在元素上的经过速度,如果速度很慢,那么我们认为它在元素上并显示工具提示,如果速度太快 —— 那么我们就忽略它。

为它创建一个通用对象 new HoverIntent(options),加上 options

  • elem —— 要跟踪的元素。
  • over —— 如果鼠标缓慢地移动元素,调用该函数。
  • out —— 当鼠标离开元素时,调用函数(如果 over 被调用过了)。

在工具提示中使用此类对象的示例:

// 工具提示样本
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";

// 对象将跟踪鼠标,并调用 over/out
new HoverIntent({
  elem,
  over() {
    tooltip.style.left = elem.getBoundingClientRect().left + 'px';
    tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
    document.body.append(tooltip);
  },
  out() {
    tooltip.remove();
  }
});

示例:

如果鼠标移动速度超过 “clock”,那么不会发生任何事件,如果速度很慢或者在它们上面停下来,那么就会有一个工具提示。

请注意:当光标在 clock 子元素之间移动时,工具提示不会“一闪而过(blink)”。

打开带有测试的沙箱。

算法看起来很简单:

  1. onmouseover/out 处理器放在元素上。也可以在这里使用 onmouseenter/leave,但它们并不常用,而且如果我们使用委托,它们就会无效。
  2. 当鼠标光标进入元素时,开始测量 mousemove 上的速度。
  3. 如果速度慢,则运行 over
  4. 之后如果离开了元素,而且 over 也被执行了,则运行 out

问题是:“如何测量速度?”

第一个想法是:每 100ms 运行一次我们的函数,并测量前一个坐标和新坐标之间的距离。如果它很小,那么速度就很小。

不幸的是,在 JavaScript 中无法获取“当前鼠标坐标”。没有像 getCurrentMouseCoordinates() 这样的函数。

获取坐标的唯一方法是监听鼠标事件,就像 mousemove

因此我们可以在 mousemove 上设置一个处理器来跟踪坐标并记住它们。然后我们可以比较它们,每 100ms 比较一次。

P.S. 请注意:解决方案测试使用 dispatchEvent 来查看工具提示是否正确。

使用沙箱的测试功能打开解决方案。