原生JS实现文字在X轴方向循环移动

之前做了一个仿抖音的小项目练习,在做到视频播放页时,视频左下角有个视频信息的文字滚动效果,在网上找到了很多类似的效果,但都不太满意,所以今天就想自己来写一下实现。

主要思路

让文字像轮播图一样循环滚动,当文字内容末尾与容器末尾重合就拼接一个相同的文字内容在后面,同时当文字内容拼接过多(这里设置的大于两倍原文字内容长度时就开始删除),就删除开头的一个文字内容,保证文字内容长度合适。另外文字内容与文字内容之间的空格效果由于 innerHTML 的原因没有使用空格或者实体。因为使用空格的话html只会解析一个空格而使用实体的话innerHTML不会获取到实体解析的空格,在进行文字的拼接和删除时会造成空格太多。这里我内嵌了一个span并设置文颜色为透明来实现同样的效果。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    #box {
      background: red;
      width: 100px;
      height: 24px;
      margin-top: 500px;
      margin-left: 500px;
      position: relative;
      overflow: hidden;
    }

    #box1 {
      position: absolute;
      font-size: 14px;
      display: inline-block;
      white-space: nowrap;
    }

    .space {
      color: transparent
    }
  </style>
</head>

<body>
  <div id="box">
    <span id="box1">@只有你知道的故事<span class="space">kg</span></span>
  </div>
  <script>
   
      function marquee(parent,child,time) {
        let box = document.getElementById(parent);
        let box1 = document.getElementById(child);
        let speed = 1; //速度
        let text = box1.innerHTML; //初始文字内容
        let textWidth = box1.clientWidth; //单段文字内容宽度
        let boxWidth = box.clientWidth; //容器宽度
        let left = box1.offsetLeft; //文字相对于容器的偏移量
        let difLeft = boxWidth - textWidth; //文字宽度与容器宽度的差值
        //如果文字内容大于容器,文字进行滚动
        if (boxWidth < textWidth) {
          //定义定时器
          let intervalId = setInterval(function () {
            left -= speed;
            box1.style.left = left + "px";
            if (left == difLeft) {
              //删除多余的重复text,防止内容冗杂(单单实现需求的话这个if可以不添加)
              if (box1.clientWidth >= 2 * textWidth) {
                box1.innerHTML = box1.innerHTML.replace(text, ""); //删除开头多余的text
                left = box1.offsetLeft + textWidth; //删除后对偏移量进行重新计算
              }
              box1.innerHTML += text; //文字后面拼接
              difLeft = boxWidth - box1.clientWidth; //重新计算文字宽度与容器宽度的差值
            }
          }, time)
        }
      }
      marquee("box","box1",45);//调用函数
      /*
      写法二:简单粗暴
       function marquee(parent,child,time) {
        let box = document.getElementById(parent);
        let box1 = document.getElementById(child);
        let speed = 1 ; //速度
        let text = box1.innerHTML; //初始文字内容
        let textWidth = box1.clientWidth; //单段文字内容宽度
        let boxWidth = box.clientWidth; //容器宽度
        let left = box1.offsetLeft; //文字相对于容器的偏移量
        let difLeft = boxWidth - textWidth; //文字宽度与容器宽度的差值
        //如果文字内容大于容器,文字进行滚动
        if (boxWidth < textWidth) {
          //定义定时器
          let intervalId = setInterval(function () {
            left -= speed;
            box1.style.left = left + "px";
            console.log(left);
            if (left == difLeft) {
              //删除多余的重复text,防止内容冗杂(单单实现需求的话这个if可以不添加)
              box1.innerHTML += text; //文字后面拼接
              difLeft = boxWidth - box1.clientWidth; //重新计算文字宽度与容器宽度的差值
            }
            if (-left >= textWidth) {
                left = 0; //删除后对偏移量进行重新计算
              }
          }, time)
        }
      }
      */

  </script>
</body>

</html>

实现效果:

marquee_ev

Last modification:October 19, 2020
如果觉得我的文章对你有用,请随意赞赏