Requirements: 1. Automatic scrolling of a certain area of the page; 2. Stop at the current scrolling position when the mouse is rolled in, and continue scrolling at the current position after the mouse is left; 2, automatic scrolling area can be freely selected; Whether to stop scrolling is configurable. Train of thought: 1, access to the specified scroll area of the element node, and the content of the scroll, 2, get the scroll area and the height of the scrolling content, if the content height is greater than the area to scroll the scroll, 3, to achieve seamless effect when rolling, we need to insert a copy of scroll area to the original scroll the content at the end of fill behind the data element to get out of container, Achieve uninterrupted effect. ① In order to get a function done, we do not need to copy the style in the stylesheet, so we use the head to dynamically insert the style tag. ② But here we need to pay attention to is that if a page has multiple need to scroll area, because each scroll height, speed, mouse slide pause, etc., are independent, so we create style should also be independent, cut create again should delete the original style tag, So we add an ID attribute to the style table as the only criterion. Code:

/** * sets scroll * for the specified element@param { classname } key- Globally unique identifier for each scroll element, this class name needs to be set to the parent node of the scroll container, * key must be passed in, otherwise it is easy to pollute the style *@param { classname } content- Scroll content selector, used to determine which content to scroll *@param { classname } container- Scroll container selector, the content to scroll in the container, if not passed in the content's parent node *@param { number } speed- Scroll speed. 1 is the baseline. If you want fast, set the number less than 1; if you want slow, set the number greater than 1 *@param { boolean } paused- Whether scrolling should be paused when the mouse moves into the scroll container */
export function setRollEffect({
  key = ' ',
  content = ' ',
  container = ' ',
  speed = 1,
  paused = true,}) {
  // Get the height of the scroll content and get the element node that the scroll understands
  const contentNode = document.querySelector(`${key} ${content}`);
  const { offsetHeight, childNodes } = contentNode;
  
  // Get the height of the scroll container
  let containerH = 0;
  if (container) containerH = document.querySelector(`${key} ${container}`).offsetHeight;
  else containerH = contentNode.parentNode.offsetHeight;
  
  // No scrolling is required when the height of the container is greater than the height of the scrolling content
  if (containerH >= offsetHeight) return;
  // Insert a copy of the scroll at the end
  childNodes.forEach((item, index) = > {
    contentNode.append(item.cloneNode(true));
  });
  
  const nodeKey = key ? key : content
  /** * gets the style sheet for all scroll tokens */
  const styleList = document.querySelectorAll('head style[roll-id]');
  styleList.forEach(item= > {
    if (item['roll-id'] === nodeKey) item.remove();
  });

  // Create a style tag
  const style = document.createElement('style');
  // Create the content of the style tag, which is the animation needed for scrolling
  const keyframeName = nodeKey.match(/\w+/g).join(' ');
  const keyFrames = `\
    @keyframes ${keyframeName}{\ 0% {\ transform: translate3d(0, 0, 0); \ }\ 100% {\ transform: translate3d(0, -${offsetHeight}px, 0); ` \} \};

  // Moving 20 pixels takes 1s as a baseline for scrolling speed to calculate how long it takes for the original list to scroll through
  const animation = `
    ${key} ${content} {\
      animation: ${(offsetHeight / 20) * speed}s ${keyframeName}linear infinite normal; \} \${key} ${content}:hover {\
      animation-play-state: ${paused ? 'paused' : 'unset'}; } \ `;

  /** * Assign the constructed animation style content to style, insert the style stylesheet into the head and set the style to a roll-id. If the key does not exist, set content to a roll-id. This is to avoid repeating the CSS style */ with the same class name to head when the method is called again
  style.innerHTML = keyFrames + animation;
  style.setAttribute('roll-id', nodeKey);
  style['roll-id'] = nodeKey;
  document.getElementsByTagName('head') [0].appendChild(style);
}
Copy the code