复杂背景下的字符雨动画实现

前言

最近有个需求,和这个很像,但是又不完全一样

这个是chokcoco 老师的作品【Web动画】科技感十足的暗黑字符雨动画

问题

大佬的解决方案很好,但是在我们的实际场景中,会有点不足。

当我们的背景不再是黑色或者说不再是纯色的时候,通过遮罩来控制文字颜色的方法就会显示弊端。

看例子:

会出现色条。

由于我们遮罩的这个条算是要上下移动的,而且背景如果是图片的话,背景颜色会更加的复杂,所以也很难通过渐变什么的手段来做颜色上的适配。

所以我们现在的核心问题其实就是,还有没有什么方法,能让一行文字有不同的颜色表现。

background-clip

background-clip 是一个 CSS 属性,用于指定背景图片或颜色的绘制区域。它决定了背景图片或颜色的绘制范围,可以是整个元素、边框盒、内边距框或者文字区域。

这个属性接受以下几个值:

  • border-box:默认值。背景将被绘制到边框盒的内边距框之下。
  • padding-box:背景将被绘制到内边距框之内,而不包括边框区域。
  • content-box:背景将被绘制到内容框的内部,而不包括内边距和边框区域。
  • text:背景将被绘制到文本内容的区域内,背景将被剪切成文字的形状。
  • no-clip:背景将被绘制到整个元素的区域内,不进行剪裁。

我们这里是为了让文字变色,所以我们将这里的值设置为text

看一下实际效果:

这里我们的实现原理就是:

  • 设置color: transparentbackground-clip: text让文字的颜色为背景的颜色,同时把背景的颜色隐藏了
  • 再通过动画设置background-position,来改变文字的颜色

这种做法本质上并没有什么不一样,只是通过background-clip: text把背景的颜色和文字的颜色结合在一起,这样就不会有色条的出现。

这种方法有点缺陷,因为设置了color: transparent,所以可能会有一瞬间,文字的颜色是隐藏了的,但是通过调整颜色和动画,它的影响可以被缩小。

代码

js 复制代码
<!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>
      body {
        padding-top: 50px;
      }
      .container {
        width: 100px;
        height: 600px;
        background: linear-gradient(blue, yellow 100%);
        display: flex;
        justify-content: center;
        position: relative;
      }

      .text {
        width: 30px;
        text-align: center;
        height: 100%;
        position: relative;
        font-size: 30px;
        background-position: 0 -300px;
        background-size: 100% 100%;
        background-repeat: no-repeat;
        background: linear-gradient(
          transparent 0,
          rgba(12, 249, 182, 0.9) 30%,
          transparent 75%,
          blue
        );
        background-clip: text;
        color: transparent;
        font-weight: bold;
        word-break: break-all;
        animation: move 2s infinite linear;
      }

      @keyframes move {
        0% {
          background-position: 0 -300px;
        }
        20% {
          background-position: 0 -300px;
        }
        100% {
          background-position: 0 700px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="text">这是一个寂寞的天, 下着有些伤心的雨</div>
    </div>
  </body>
  <script></script>
</html>

mix-blend-mode

第二种方法是还是利用遮罩的手段,只是我们对遮罩后的背景颜色加了混合。

目的是消除遮罩层与原有底层由于色差而出现的色块。

mix-blend-mode 是一个 CSS 属性,用于控制元素的背景与其背后元素的混合方式。这个属性允许你通过不同的混合模式来创建各种视觉效果,比如透明、叠加、差值等。

我们可以看一下上面的动图,我们在设置好了渐变的背景色,和黑色的渐变遮罩层后,通过添加不同的mix-blend-mode的属性值,就能有不同的表现形式。

这里我们可以看见取值为lightenscreen的时候,表现会好一点。

但是这个不是绝对的,和我们所使用的颜色搭配有很大的关系。

下面是一些属性值的含义:

  • screen:将两个颜色值的相反值相乘得到结果,产生一个较亮的混合色。类似于叠加一个半透明白色图层。
  • overlay:根据底层色调调整顶层色调的混合模式。如果底层色较亮,则会加深顶层色的颜色,如果底层色较暗,则会减淡顶层色的颜色。
  • darken:将两个颜色值进行比较,保留较暗的颜色。
  • lighten:将两个颜色值进行比较,保留较亮的颜色。
  • difference:将两个颜色值进行比较,产生一个反差的混合色。
  • color-dodge:根据底层色进行颜色减淡。

这个方法相对于上一种方法,优点在于,调试的好的话,几乎是完美的。

那么缺点就是,需要大量的调试颜色以及属性值,如果调试不好的话,那么还是会出现色块。

这是最终效果:

代码

js 复制代码
<!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>
      .container {
        width: 100px;
        height: 600px;
        background: linear-gradient(blue, yellow 100%);
        display: flex;
        justify-content: center;
        position: relative;
      }

      .text {
        width: 30px;
        text-align: center;
        height: 100%;
        position: relative;
        font-size: 30px;
        background-position: 0 0px;
        background-size: 100% 100%;
        background-repeat: no-repeat;
        mix-blend-mode: screen;
        color: rgb(12, 249, 182);
        font-weight: bold;
        word-break: break-all;
      }
      .text::before {
        content: '';
        position: absolute;
        top: 0px;
        left: 0px;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          rgba(0, 0, 0, 0.9),
          transparent 75%,
          transparent
        );
        background-size: 100% 100%;
        background-repeat: no-repeat;
        animation: move 2s infinite linear;
      }
      @keyframes move {
        0% {
          background-position: 0 -300px;
        }
        20% {
          background-position: 0 -300px;
        }
        100% {
          background-position: 0 600px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="text">这是一个寂寞的天, 下着有些伤心的雨</div>
    </div>
  </body>
  <script></script>
</html>

总结

在复杂背景情况下,想要做到文字完美的变色,需要结合实际情况和一定工作量的调试,借助background-clip 或者mix-blend-mode,还是很有希望能调试出来完美效果的。

参考

【Web动画】科技感十足的暗黑字符雨动画

利用混合模式,让文字智能适配背景颜色

相关推荐
学习使我快乐013 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19953 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
黄尚圈圈4 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水5 小时前
简洁之道 - React Hook Form
前端
正小安7 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch9 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光9 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   9 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   9 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d