How does JS elegantly realize the automatic scrolling display of modules

need

When working on a large-screen visualization project in the past few days, I encountered a requirement that when a scroll bar appears in a certain area , let it scroll and display data in a loop.

Of course, as an excellent development, we can also optimize it: when the mouse is placed, stop the automatic scrolling; move the mouse out of the area and start scrolling again.

accomplish

Basic implementation ideas

Before realizing the function, we need to understand three parameters

  • Visual height clientHeight
  • The height of the scroll bar from the top scrollTop
  • The height of the scrolling area scrollHeight

According to the information in the above figure, we can easily implement the automatic scrolling logic of the scroll bar:

When scrollHeight is greater than clientHeight , the element needs to be scrolled, scrollTop ++; when scrollTop + clientHeight is equal to scrollHeight , that is, the element scrolls to the bottom, and we can make scrollTop equal to 0.

Converted to code:

// 获取滚动区域的DOM
let parentDom = document.getElementById("XXX")
// 判断是否有滚动条
if(parentDom.scrollHeight <= parentDom.clientHeight) return
// 如果滚动到底部,scrollTop = 0;
if (
  parentDom.scrollTop + parentDom.clientHeight ===
  parentDom.scrollHeight
) {
  parentDom.scrollTop = 0;
} else {
  // 滚动条自增
  parentDom.scrollTop++; 
}

Of course, we need to set a timer to let this logic execute repeatedly.

const scroll = () => {
  // 上述代码
};
let timer= setInterval(scroll, 100);

At this point, our basic idea is completed. When there are multiple areas in our project that need to be scrolled, we should encapsulate this method for reuse.

Code Encapsulation and Reuse

Let's take the mainstream vue as an example to encapsulate the code. The most appropriate way should be to use it as a command in vue .

To read the following tutorials, you need to have basic knowledge of vue commands, you can refer to the tutorials on the vue official website .

Basic Structure of Instructions

First, we create the scroll.js file and write the most basic structure of the instruction

// 实现滚动条自动滚动功能
const directive = {
  inserted(el, binding) {
    ...
  },
};
export default directive

Introduce this file in main.js

import Vue from "vue";
import App from "./App.vue";
import directive from "./change";

Vue.config.productionTip = false;
// 注册名为 scroll 的指令
Vue.directive("scroll", directive);
new Vue({
  render: (h) => h(App),
}).$mount("#app");

At this point, we created a command called v-scroll , we directly use

// App.vue
<template>
  <div id="app" v-scroll>
    // XXXXX这里是您的自定义html
  </div>
</template>

perfect command

Combined with our original implementation ideas, we can improve the instructions

// js实现动态变化的数字
const directive = {
    
    
  inserted(el) {
    
    
    //el就是绑定的dom对象
    if (!el) return;
    const scroll = () => {
    
    
      let parentDom = el;
      // 判断是否有滚动条
      if(parentDom.scrollHeight <= parentDom.clientHeight) return
      //判断元素是否滚动到底部(可视高度+距离顶部=整个高度)
      if (
        parentDom.scrollTop + parentDom.clientHeight ===
        parentDom.scrollHeight
      ) {
    
    
        parentDom.scrollTop = 0;
      } else {
    
    
        parentDom.scrollTop++; // 元素自增距离顶部
      }
    };
    let timer = setInterval(scroll, 100);
};
export default directive;

Now the function of our command is complete. Of course, it still has a flaw. When the mouse moves into this element, it cannot stop automatically, and moving away from this area cannot resume automatic scrolling. We only need to bind the onmouseenter and onmouseleave events on the dom .

inserted(el) {
    
    
      // .....
      let timer = setInterval(scroll, rate);
      el.onmouseenter = () => {
    
    
        clearInterval(timer);
        timer = null;
      };
      el.onmouseleave = function () {
    
    
        timer = setInterval(scroll, 100);
      };
    },
  },

command by value

Even better, we can also customize this scrolling speed by passing values ​​through elements. The second parameter binding.value of the vue instruction hook function can accept parameters.

// App.vue
<template>
  <div id="app" v-scroll="100">
    // XXXXX这里是您的自定义html
  </div>
</template>

At this point, the value of binding.value is 100, and we further optimize the code

    inserted(el, binding) {
    
    
      const rate = binding?.value ??   100;
      if (!el) return;
      const scroll = () => {
    
    
        // ...省略
      };
      let timer: any = setInterval(scroll, rate);
      el.onmouseenter = () => {
    
    
        clearInterval(timer);
        timer = null;
      };
      el.onmouseleave = function () {
    
    
        timer = setInterval(scroll, rate);
      };
    },

You're done! !

If you have gained something after reading it, come to a one-click triple combo!

Guess you like

Origin blog.csdn.net/weixin_46769087/article/details/128298417