Bootstrap

多种方法实现文本擦除效果

在实现文本擦除效果时,有多种方法可以使用,具体使用如下:

1. 纯 CSS 方法 - 使用 text-decoration

利用 text-decoration: line-through; 可以模拟擦除效果,但这种方法的局限性在于无法完全控制动画效果,且不适合动态显示文本。

<div class="text-container">
  <p class="erase-text">这是第一行需要擦除的文本。</p>
  <p class="erase-text">第二行文本也需要擦除。</p>
  <p class="erase-text">这种方法很简单,但无法做出动态效果。</p>
</div>
.erase-text {
  text-decoration: line-through;
  line-height: 1.5;
}

 展示为:

优点:简单易用,适用于静态页面或不可编辑的文本。

缺点:无法实现动画效果,且不能控制擦除进度,效果较为生硬。

2. CSS 动画实现擦除效果(clip-path 或 width)

通过使用 CSS 动画和 clip-path 或调整 width,可以实现文本逐渐擦除的效果。这里使用 width 动态改变来模拟擦除效果。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      .text-container {
        position: relative;
        line-height: 1.5;
      }

      .erase-text {
        display: inline-block;
        position: relative;
        overflow: hidden;
        white-space: nowrap;
      }

      .erase-text::after {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 0;
        height: 100%;
        background-color: white;
        animation: erase 5s forwards;
      }

      @keyframes erase {
        0% {
          width: 0;
        }

        100% {
          width: 100%;
        }
      }
    </style>
  </head>
  <body>
    <div class="text-container">
      <span class="erase-text">在人生的道路上,挫折与挑战是不可避免的,但正是这些困难塑造了更强大的我们。</span>
      <span class="erase-text">成功并非一蹴而就,而是由无数个坚持的瞬间累积而成。</span>
      <span class="erase-text">相信自己,勇敢追梦,哪怕步伐缓慢,只要不停下,终会抵达心中的远方。</span>
    </div>
  </body>
</html>

效果为:从右往左展示内容。

本质:使用一个伪元素遮盖内容。

优点:纯 CSS 实现,不依赖 JavaScript,性能开销小,适合简单的动画。动画效果平滑,过渡自然,且可控。

缺点:动画只能从开始到结束逐步执行,难以控制进度或动态停止。

3. JavaScript 控制 width 或 height 的方法

通过 JavaScript 代码控制元素的 width 或 height,可以动态调整文本擦除的进度,更加灵活且可控。通过设置定时器,可以逐步将文本的可见部分缩小,实现擦除效果。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      .text-container {
        position: relative;
        line-height: 1.5;
      }

      .erase-text {
        display: inline-block;
        position: relative;
        overflow: hidden;
        white-space: nowrap;
      }

      .erase-text span {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: white;
      }
    </style>
  </head>
  <body>
    <div class="text-container">
      <p class="erase-text">
        <span></span>在人生的道路上,挫折与挑战是不可避免的,但正是这些困难塑造了更强大的我们。
      </p>
      <p class="erase-text">
        <span></span>成功并非一蹴而就,而是由无数个坚持的瞬间累积而成。
      </p>
      <p class="erase-text">
        <span></span>无论前路多么艰难,只要你心怀信念,脚踏实地,终会迎来属于自己的曙光。
      </p>
    </div>

    <script>
      // 选择所有的擦除文本容器
      const eraseTexts = document.querySelectorAll('.erase-text');

      // 动态控制擦除效果
      eraseTexts.forEach((textElement) => {
        const spanElement = textElement.querySelector('span'); // 获取 span 作为擦除层
        const textWidth = textElement.offsetWidth; // 获取文本容器的宽度
        let currentWidth = 0; // 当前擦除宽度
        const interval = 50; // 设置更新频率,单位:毫秒

        // 定时器逐步更新宽度
        const eraseInterval = setInterval(() => {
          currentWidth += 2; // 每次增加2px的宽度
          spanElement.style.width = currentWidth + 'px'; // 动态调整宽度

          // 当擦除完成时,停止定时器
          if (currentWidth >= textWidth) {
            clearInterval(eraseInterval);
          }
        }, interval);
      });
    </script>
  </body>
</html>

效果展示:

优点:能够根据需要动态调整擦除的速度和进度。

缺点:相对于纯 CSS 方案,代码量较大,性能也受到影响,尤其是有大量文本时。

最后,每种方法有其适用的场景,开发者可以根据实际需求选择合适的方法。

4. 引出:渐进效果展示文本

类似的方法,将一段文本按照渐进的效果展示出来。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      :root {
        --erase-start: 5%;
      }
      .container {
        width: 80%;
        margin: 1em auto;
        line-height: 2;
        position: relative;
      }
      p {
        margin: 0;
        padding: 0;
      }
      .eraser {
        position: absolute;
        top: 0;
        left: 0;
      }
      .text {
        background: linear-gradient(to right, transparent var(--erase-start), #fff calc(var(--erase-start) + 100px));
        /* 文字只是撑开行盒宽度,不需要看见具体文本 */
        color: transparent;
        animation: eraser 5s infinite;
      }
      @keyframes eraser {
        to {
          --erase-start: 100%;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <p>
        在人生的道路上,挫折与挑战是不可避免的,但正是这些困难塑造了更强大的我们。成功并非一蹴而就,而是由无数个坚持的瞬间累积而成。无论前路多么艰难,只要你心怀信念,脚踏实地,终会迎来属于自己的曙光。不要害怕失败,它是成长的阶梯;不要畏惧孤独,它是沉淀的机会。你所经历的每一份苦难,都会在未来化作照亮前路的光。相信自己,勇敢追梦,哪怕步伐缓慢,只要不停下,终会抵达心中的远方。
      </p>
      <p class="eraser">
        <!-- 重点:将复制后的文本放到一个行盒内 -->
        <span class="text">
          在人生的道路上,挫折与挑战是不可避免的,但正是这些困难塑造了更强大的我们。成功并非一蹴而就,而是由无数个坚持的瞬间累积而成。无论前路多么艰难,只要你心怀信念,脚踏实地,终会迎来属于自己的曙光。不要害怕失败,它是成长的阶梯;不要畏惧孤独,它是沉淀的机会。你所经历的每一份苦难,都会在未来化作照亮前路的光。相信自己,勇敢追梦,哪怕步伐缓慢,只要不停下,终会抵达心中的远方。
        </span>
      </p>
    </div>
  </body>
</html>

效果展示如下,没有渐变的效果,一段时间后完全展示。

原因为:CSS 动画生效的前提,要有一个数值类的 CSS 属性。而 --erase-start 是一个变量,不是 CSS 属性。

解决方法:将变量变成 CSS 属性。

/* 自定义CSS属性,属性的命名规范以 -- 开头 */
@property --erase-start {
  /* 语法规则:百分比 */
  syntax: '<percentage>';
  inherits: false;
  /* 初始值 */
  initial-value: 0%;
}

此时成功实现:

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;