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

不一样的“悬停几秒后执行函数”? #9

Open
vortesnail opened this issue Oct 31, 2019 · 0 comments
Open

不一样的“悬停几秒后执行函数”? #9

vortesnail opened this issue Oct 31, 2019 · 0 comments

Comments

@vortesnail
Copy link
Owner

大家好,我是 vortesnail。

前言:

最近这几个星期,一直都在维护自己的基于 React 的开源播放器组件,以为功能基本都差不多了,却忽视了播放器一个很重要的功能:鼠标悬停在视频播放界面时,在一定时间后鼠标会消失,视频下方的控制栏也会隐藏,呈现视频的最大可视化。但是鼠标稍微一动,一切恢复如初。用一张简单的 gif 图来说明的话,是下面这样子的:
屏幕录制-2019-10-31-11.18.41 (1).gif
有点犯难,它不是简单地移到元素(如视频)上,2秒后让它执行鼠标消失和控制栏消失的操作,因为一旦鼠标一动一点,都要恢复原样,不过好在结合 防抖 的思想以及自己的一些思考,实现了这个功能,并将其封装为一个工具函数,可供大家使用,当然,其中也有不足,也请各位能给予意见,我会结合给的意见更新这篇博客。

开始:

如果你现在需要使用这个功能,你希望用起来尽量简单,并且能达到你的使用要求,思来想去,给你暴露 4 个参数最为妥当:

  • element:你所希望操作的元素(比如上面 gif 中 “我是视频”这个 div 元素)
  • secondsLaterDoFn:你设定的时间之后,想做什么操作(比如上面 gif 中“鼠标消失,控制栏消失”)
  • seconds:你希望的时间,单位:ms(比如上面 gif 中我设定的时间为 2000ms)
  • reNormalFn:回归原样的操作(比如上面 gif 中控制栏和鼠标都回来)

那么,我们现在写一个函数,把这四个参数传进去,并对传入的 element 写两个监听事件,以及我们的清除定时器函数:

function HoverSD(element, secondsLaterDoFn, seconds, reNormalFn) {
  var timeout;
  var ele = element, secondsLDF = secondsLaterDoFn, secs = seconds, reNFn = reNormalFn;
  
  var clearTimer = function() {
    timeout && clearTimeout(timeout);
  }

  this.secondsHoverEX = function() {
    ele.addEventListener('mousemove', rebuildTimer);
    ele.addEventListener('mouseleave', clearTimer);
  }
}

window.HoverSD = HoverSD;

你也发现了, rebuildTimer 和 clearTimer 是个啥玩意儿?别急。
我们整理一下思路:在鼠标移到这个元素上面之后,我们要有一个定时器,在设定的时间过后,执行操作,但是,我们在设定的时间之内,又移动了鼠标,这时候需要把之前设定的定时器清除,重新开一个定时器,重新计时,这里的思想和 防抖 一模一样,于是我们初步的 rebuildTimer 如下:

var rebuildTimer = function() {
  var context = this;
  var args = arguments;
  clearTimer();
  timeout = setTimeout(() => {
    secondsLDF.apply(context, args);
  }, secs);
}

意思就是,当我们 mousemove 的时候,就会执行 rebuildTimer 函数,在这个函数内部,清除定时器,即每次移动之后,重新计时,执行 secondsLDF 。

可是我们传入的参数 reNormalFn (即 reNFn )并没有用到啊,它是用来恢复原状态的操作,我们直接插入在清除定时器之前就可以了。

var rebuildTimer = function() {
  var context = this;
  var args = arguments;
  
  reNFn.apply(context, args);
  
  clearTimer();
  timeout = setTimeout(() => {
    secondsLDF.apply(context, args);
  }, secs);
}

那我们在特定的时候想要移出这个元素的监听事件怎么办呢?比如在 React 中我们在 componentDidMount 中用了,需要在 componentWillUnmount 中去除监听事件,防止内存占用,那我们就需要再写一个移除事件的函数:

this.removeElemEventListener = function() {
  ele.removeEventListener('mousemove', rebuildTimer);
  ele.removeEventListener('mouseleave', clearTimer);
}

注意, removeEventListener 的参数,必须与监听时候的执行函数完全相同,且 不能有参数,不能有参数,不能有参数!!! ,我一开始就是写的有参数形式,怎么搞都搞不对。。。

现在把它封装成一个工具函数,放到 npm 上,直接安装使用,为了兼顾在不配置 webpack 情况下以及低版本浏览器情况下,我们可以这样来做:

// all code
function HoverSD(element, secondsLaterDoFn, seconds, reNormalFn) {
  var timeout;
  var ele = element, secondsLDF = secondsLaterDoFn, secs = seconds, reNFn = reNormalFn;

  var rebuildTimer = function() {
    var context = this;
    var args = arguments;
    reNFn.apply(context, args);
    clearTimer();
    timeout = setTimeout(() => {
      secondsLDF.apply(context, args);
    }, secs);
  }
  
  var clearTimer = function() {
    timeout && clearTimeout(timeout);
  }

  this.secondsHoverEX = function() {
    ele.addEventListener('mousemove', rebuildTimer);
    ele.addEventListener('mouseleave', clearTimer);
  }
  
  this.removeElemEventListener = function() {
    ele.removeEventListener('mousemove', rebuildTimer);
    ele.removeEventListener('mouseleave', clearTimer);
  }
}

window.HoverSD = HoverSD;

将主要的核心函数 secondsHoverEX 和 removeElemEventListener 通过 this. 暴露出来,再将这个函数暴露到 window 全局,安装之后可以直接通过

let hoversd = new window.HoverSD(elem, fn1, 2000, fn2);
hoversd.secondsHoverEX();
// ...
// other code here
// ...
hoversd.removeElemEventListener();

即可完成使用。

本篇文章收录于我的 个人blog,后续会致力于推出越来越多文章以及开源工具,如有帮助,赏个 star,谢谢各位老爷了!

后记:

非常感谢大家能看到最后,如果有朋友想要提出意见,欢迎来 github/issue 给我提建议,也可在下方评论直接提出,我个人觉得这个工具函数适用的场景还是蛮多的,如果能帮助到你,欢迎来此项目下赏个 star 。我会在项目主页关于此工具的使用做更详细的介绍,欢迎访问:
github项目地址:https://github.com/vortesnail/hover-seconds-do

当然,厚着脸皮也希望大家能支持下我的基于 React 的开源播放器组件:https://github.com/vortesnail/qier-player
68747470733a2f2f69302e6864736c622e636f6d2f6266732f616c62756d2f646334363438326563343235656266373866383530316662343466303566386230316362646134622e706e67.png
下次再见,拜拜啦~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant