36
头图
Welcome to my public account: front-end detective

In daily work, timers are used in many occasions, such as delayed loading, timed query, etc., but the control of timers is sometimes a little troublesome, such as mouse move in to stop, move out and start again. This time, I will introduce a few methods to better control the timer with CSS. Let’s learn about it together. I believe it can bring a different experience.

1. Hover delay trigger

There is such a scene, when the mouse hovers on an element 1s , the event will be triggered, and the dissatisfaction 1s will not trigger. Frequent trigger events. If it is implemented with js , it may be like this

 var timer = null
el.addEventListener('mouseover', () => {
  timer && clearTimeout(timer)
  timer = setTimeout(() => {
    // 具体逻辑
  }, 1000)
})

is this correct? Wait, this is not over yet, this is only a delay, it will still be triggered after the mouse leaves, and the timer needs to be canceled when the mouse leaves

 el.addEventListener('mouseout', () => {
  timer && clearTimeout(timer)
})

In addition, when using mouseout also need to consider the dom nested structure , because these events will still fire in the process of 父级 -> 子级 , in short, there will be a lot of details , it is easy to trigger by mistake.

Now the turning point is coming. If you borrow CSS, you can effectively avoid the above problems. As follows, first add a delay to the element that needs to be triggered transition

 button:hover{
  opacity: 0.999; /*无关紧要的样式*/
  transition: 0s 1s opacity; /*延时 1s */
}

Only one insignificant style is needed here. If opacity has been used, it is possible to use other ones, such as transform:translateZ(.1px) , which is also feasible. Then add the listener transitionend method

GlobalEventHandlers.ontransitionend - Web API Interface Reference | MDN (mozilla.org)
 el.addEventListener('transitionend', () => {
  // 具体逻辑
})

This is the end of it. No timer, no cancellation, and no need to consider dom structure, perfect realization.

The following is a small example, after hover is triggered after a period of time alert

Kapture 2022-09-11 at 15.56.37

The principle is the same as above, the complete code can be viewed online demo: hover_alert(runjs.work)

🤔If you encounter such a need in the future, you can stop and think about it. Many interactions related to mouseover can be implemented in this way.

2. Long press trigger event

Long press is also a relatively common requirement, which can be well differentiated from click events, thus giving more interactive capabilities.

However, there is no such event in the native js . If you want to implement a long press event, you usually need to use a timer and a mouse press event, as follows

 el.onmousedown = function(){
    this.timer && clearTimeout(this.timer);
    this.timer = settimeout(function(){
        //业务代码
    },1000)
}
el.onmouseup = function(){
    this.timer && clearTimeout(this.timer);
}

It is a timer and a timer cancellation scenario, which is similar to the previous example, and can also be implemented with CSS. Since it is a mouse press, it can be associated with :active , so it can be implemented in this way

 button:hover:active{
  opacity: .999; /*无关紧要的样式*/
  transition: opacity 1s; /*延时 1s */
}

Then listen again transitionend method

 el.addEventListener('transitionend', () => {
  // 具体逻辑
})

Is it very convenient? The following is a small case that has been done before, which realizes long-press trigger element selection

Kapture 2022-09-13 at 10.37.01

The complete code can be viewed online demo: long press the box to select (runjs.work)

3. Carousel and Pause

Let’s look at a more interesting example, the carousel.

Usually the carousel will play automatically, and then the mouse hover will pause the carousel. The usual practice is like this

 function autoPlay(){
  timer && clearInterval(timer)
  timer = setInterval(function(){
    // 轮播逻辑
  }, 1000)
}
autoPlay()
view.onmouseover = function(){
    timer && clearInterval(timer)
}
el.onmouseout = function(){
    autoPlay()
}

It is the cancellation and setting of the timer again. It is too annoying to bind a bunch of events. Can you change it? Of course you can, with CSS animations, everything is easy to do.

Different from the previous one, here is setInterval , which can be triggered repeatedly, so what can be repeatedly triggered in CSS? That's right, CSS animations !

When the number of CSS animation settings is infinite , it can loop infinitely, which is very similar to this timer effect, and can directly pause and play the animation through :hover . To monitor the trigger of each animation, you can use animationiteration this method, which means that each animation is triggered once

GlobalEventHandlers.onanimationiteration - Web API Interface Reference | MDN (mozilla.org)

So implementing this way of thinking is

 .view {
  animation: scroll 1s infinite; /*每1s动画,无限循环*/
}
.view:hover{
  animation-play-state: paused; /*hover暂停*/
}
@keyframes scroll {
  to {
    transform: translateZ(.1px); /*无关紧要的样式*/
  }
}

Then listen for animationiteration event

 view.addEventListener("animationiteration", () => {
  // 轮播逻辑
})

Did you leave out most of the js code? It is also easier to understand and control.

The following is a carousel implemented by animationiteration instead of setInterval

Kapture 2022-09-11 at 16.43.49

The complete code can be viewed online demo: css_banner(runjs.work)

Fourth, to summarize

The above are a few alternatives where you may not need a timer. Compared with timers, CSS has more advantages in controlling the start and pause of timers. Let's summarize

  1. :hover cooperate with transition delay, transitionend monitoring can realize mouse trigger effect after delay
  2. :active with transition delay, transitionend monitor can achieve long-press trigger effect
  3. CSS animation settings infinite post-coupling animationiteration monitoring can achieve periodic triggering effect
  4. The console animation can be paused and played directly through :hover

Of course, not only the above cases can be used, anyone who interacts with CSS ( :hover , :active ) with similar functions can think in this direction, is it possible to achieve more elegant? 🤔

Finally, if you think it's good and helpful to you, please like, bookmark, and forward ❤❤❤

Welcome to my public account: front-end detective

XboxYan
18.1k 声望14.1k 粉丝