前端炫酷动画--文字(一)

目录

一、让文字适应纹理(过滤器)

二、交错排列的文字

三、标题动画

四、文字阴影

五、文字镂空效果

六、文字的交融展开(filter+调整字间距)

七、光标跟随效果【仿AI回复】

八、高度自动过渡+宽度适应内容

九、文字智能适配背景(blend)

十、不规则的文字环绕(shape-outside)

十一、多行文本擦除效果

十二、多行文本溢出处理

一、让文字适应纹理(过滤器)

  <svg viewBox="0 0 600 330">
    <defs>
      <filter id="conform">
        <feImage href="qiang.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none"
          result="ORIGIN_IMAGE"></feImage>
        <feColorMatrix in="ORIGIN_IMAGE" type="saturate" values="0" result="GRAY_IMAGE"></feColorMatrix>
        <feDisplacementMap in="SourceGraphic" in2="GRAY_IMAGE" scale="15" xChannelSelector="R" yChannelSelector="R"
          result="TEXTURED_TEXT"></feDisplacementMap>
        <feImage href="qiang.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none" result="BG">
        </feImage>
        <feColorMatrix in="TEXTURED_TEXT" result="OPACITY_TEXT" type="matrix" values="1 0 0 0 0
            0 1 0 0 0
            0 0 1 0 0
            0 0 0 .9 0"></feColorMatrix>
        <feBlend in="BG" in2="PACITY_TEXT" mode="multiply"></feBlend>
      </filter>
    </defs>
    <Image href="qiang.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none"></Image>
    <text x="50%" y="50%" font-size="10em" font-weight="bold" text-anchor="middle" alignment-baseline="middle"
      fill="#000" filter="url(#conform)">
      LOGO
    </text>
  </svg>
  • <filter id="conform">:定义了一个名为 conform 的过滤器
  • <feImage>:加载背景图像 qiang.jpg,并将其结果命名为 ORIGIN_IMAGE
  • <feColorMatrix>:将 ORIGIN_IMAGE 转换为灰度图像,结果命名为 GRAY_IMAGE
  • <feDisplacementMap>:使用 GRAY_IMAGE 对源图形进行位移映射,结果命名为 TEXTURED_TEXT
  • <feImage>:再次加载背景图像 qiang.jpg,结果命名为 BG
  • <feColorMatrix>:给TEXTURED_TEXT 调整透明度,结果命名为 OPACITY_TEXT
  • <feBlend>:将 BG 和 OPACITY_TEXT 进行乘法混合

二、交错排列的文字

    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap">
    <style>
      .overlap {
        text-transform: uppercase;
        font-family: "Luckiest Guy";
        color: white;
        font-size: 100px;
        letter-spacing: -10px;
      }
      .overlap span {
        text-shadow: 10px 0 10px #000;
        position: relative;
      }
    </style>
  </head>
  <body>
    <h1 class="overlap">Hello World</h1>
    <script>
      const overlap = document.querySelector(".overlap");
      overlap.innerHTML = overlap.textContent
      .split("")
      .map(
        (word, i, arr) => `<span style="z-index:${arr.length - i}">${word}</span>`
      )
      .join("");
    </script>
  </body>

三、标题动画

    <style>
      div {
        margin-top: 100px;
        display: flex;
        flex-direction: column;
        align-items: center;
      }
      .title {
        font-size: 42px;
        text-transform: uppercase;
        letter-spacing: 5px;
        transform: rotate(-10deg);
        display: flex;
      }
      .title span {
        opacity: 0;
        transform: skew(-10deg); /* 倾斜350度 */
        text-shadow: 1px 1px #533d4a, 2px 2px #533d4a, 3px 3px #533d4a,
          4px 4px #533d4a, 5px 5px #533d4a;
        /* 贝塞尔曲线做个动画轨迹 */
        animation: move 1s var(--d) cubic-bezier(0.46, -0.15, 0.49, 1.48)
          forwards;
      }
      @keyframes move {
        from {
          opacity: 0;
          transform: skew(-10deg) translateY(300%);
        }
        to {
          opacity: 1;
          transform: skew(-10deg) translateY(0);
        }
      }
    </style>
  </head>
  <body>
    <div>
      <p class="title" style="color: #e55643">这是会依次弹跳</p>
      <p class="title" style="color: #2b9f5e">的标题文字</p>
    </div>
    <script>
      const ps = document.querySelectorAll(".title");
      ps.forEach((p) => {
        const result = p.textContent
          .split("")
          .map((letter) => `<span>${letter}</span>`)
          .join(``);
        p.innerHTML = result;
      });
      // 依次弹跳效果
      const spans = document.querySelectorAll(".title span");
      for (let i = 0; i < spans.length; i++) {
        spans[i].style.setProperty("--d", i * 0.1 + "s");
      }
    </script>
  </body>

扩展:transform变形失效情况:

     1、元素未设置 position或display

     2、display: inline元素

     3、3D 变换时缺乏适当的 perspective

     4、父元素的overflow: hidden

     5、transform 与 z-index 层级冲突

四、文字阴影

右上角有白边,左下方添加灰色阴影,字体是"Luckiest Guy"

        text-shadow: 1px -1px #fff, -1px 1px #999, -10px 10px 5px #808080;

五、文字镂空效果

    <style>
      body {
        --bg: url(./yejing.jpg) no-repeat center/cover;
        background: var(--bg);
        height: 100vh;
      }
      .modal {
        background-color: rgba(0, 0, 0, 0.7);
        width: 100%;
        height: 100%;
      }
      .modal h1 {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 12vw;
        text-stroke: 1px #fff;
        -webkit-text-stroke: 1px #fff; /* 文字白色描边 */
        background: var(--bg);
        /* 设置背景只显示在文本区域内,使得文字背景呈现图片效果 */
        background-clip: text;
        -webkit-background-clip: text;
        color: transparent;
      }
    </style>
  </head>
  <body>
    <div class="modal"><h1>NightView</h1></div>
  </body>

六、文字的交融展开(filter+调整字间距)

    <style>
      .container {
        width: 100%;
        height: 100vh;
        background-color: black;
        text-align: center;
        line-height: 100vh;
        /* 对比度滤镜:使容器内容的对比度增加到原来的30倍,造成“交融” */
        filter: contrast(30);
      }
      .text {
        font-size: 100px;
        color: #fff;
        animation: showup 3s forwards;
      }
      /* 字间距从-50px变化到10px */
      @keyframes showup {
        from {
          letter-spacing: -50px;
          filter: blur(10px); /* 模糊滤镜:使文本模糊 */
        }
        to {
          letter-spacing: 10px;
          filter: blur(2px);
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <span class="text">Web Developer</span>
    </div>
  </body>

七、光标跟随效果【仿AI回复】

  <body>
    <div class="text-container">
      <div class="text"></div>
      <!-- 一开始光标样式在盒子左上角 -->
      <div class="cursor"></div>
    </div>
    <script>
      const textContainer = document.querySelector(".text-container");
      const textElem = document.querySelector(".text");
      const cursor = document.querySelector(".cursor");
      async function autoAppend() {
        function delay(duration) {
          return new Promise((resolve) => setTimeout(resolve, duration));
        }
        function transfer(text) {
          return `<p>${text.replace(/\n/g, "<br>")}</p>`;
        }
        const content = `这段代码主要在模仿AI回复用户提问后,进行解答的场景,主要是为了看下光标跟随文字效果是如何实现的`;
        for (let i = 0; i < content.length; i++) {
          let text = content.slice(0, i);
          let result = transfer(text);
          textElem.innerHTML = result;
          updateCursor();
          await delay(100);
        }
      }
      autoAppend();
      function getLastTextNode(node) {
        if (node.nodeType === Node.TEXT_NODE) {
          return node;
        }
        const children = node.childNodes;
        for (let i = children.length - 1; i >= 0; i--) {
          const child = children[i];
          const result = getLastTextNode(child);
          if (result) {
            return result;
          }
        }
        return null;
      }
      function updateCursor() {
        // 1、追加一个文字到末尾
        const lastTextNode = getLastTextNode(textElem);
        const textNode = document.createTextNode("字");
        if (lastTextNode) {
          lastTextNode.parentNode.appendChild(textNode);
        } else {
          textElem.appendChild(textNode);
        }
        //  2、获取追加的文字位置
        const range = document.createRange(); //框选范围对象
        range.setStart(textNode, 0);
        range.setEnd(textNode, 0);
        const rect = range.getBoundingClientRect();
        //  3、根据文字位置设置光标位置
        const containerRect = textContainer.getBoundingClientRect();
        const x = rect.x - containerRect.x;
        const y = rect.y - containerRect.y;
        cursor.style.transform = `translate(${x}px,${y}px)`;
        // 4、删除追加的文字
        textNode.parentNode.removeChild(textNode);
      }
    </script>
  </body>

八、高度自动过渡+宽度适应内容

  <style>
    .btn {
      width: 120px;
      background-color: #007bff;
      text-align: center;
      border-radius: 5px;
      cursor: pointer;
    }
    .detail {
      width: 120px;
      background-color: rosybrown;
      overflow: hidden;
      height: 0;
      transition: height 0.3s ease;
    }
     .news-type{
      /* 宽度适应内容,不写或者auto会占满容器 */
      width: fit-content;
      padding: 10px;
      background-color: yellowgreen;
    }
  </style>
</head>
<body>
  <div class="btn">hover me</div>
  <div class="detail">
    划过显示高度,高度自然过渡,css网格布局会有兼容性问题,其他css不够丝滑
  </div>
  <div class="news-type">热门话题</div>
  <script>
    const btn = document.querySelector(".btn");
    const detail = document.querySelector(".detail");
    btn.onmouseenter = function () {
      detail.style.height = detail.scrollHeight + "px";
    };
    btn.onmouseleave = function () {
      detail.style.height = "0";
    };
  </script>
</body>

九、文字智能适配背景(blend)

    <style>
      .banner {
        position: relative;
        width: 50%;
        height: 50vh;
        background: linear-gradient(-135deg, black 50%, white 50%);
      }
      .title {
        position: absolute;
        top: 50%;
        left: 54%;
        transform: translate(-50%, -50%);
        color: #fff;
        font-size: 3em;
        transition: 0.4s;
        mix-blend-mode: difference;/* 文字颜色与背景色进行差值混合 */
      }
      .banner:hover .title {
        transform: translate(-50%, -50%) translateX(-120px);
      }
    </style>
  </head>
  <body>
    <div class="banner">
      <h1 class="title">育人为渡&emsp;经久如一</h1>
    </div>
  </body>

十、不规则的文字环绕(shape-outside)

    <style>
      .avatar {
        width: 100px;
        height: 120px;
        float: left;
        margin-right: 1em;
        object-fit: cover;
        border-radius: 50%;
        shape-outside: circle(50% at 50% 50%);
      }
      p {
        line-height: 2;
      }
    </style>
  </head>
  <body>
    <div>
<img src="./qiang.jpg" class="avatar" />
<p>若头像图片是直角图形,环绕文字会直线环绕;若头像图片是圆形这种不规则图片,继续直线环绕就不太搭配;此时需要不规则的文字环绕:这里使用shape-outside。</p>
    </div>
  </body>

十一、多行文本擦除效果

    <style>
      body {
        background-color: #000;
        color: #fff;
      }
      .container {
        width: 80%;
        margin: 1em auto;
        line-height: 2;
        text-indent: 2em;
        position: relative;
      }
      .eraser {
        position: absolute;
        inset: 0;
      }
      .text {
        --p: 0%;
        background: linear-gradient(
          to right,
          #0000 var(--p),
          #000 calc(var(--p) + 30px)
        );
        color: transparent;
        animation: erase 5s linear forwards;
      }
      @property --p {
        syntax: "<percentage>";
        initial-value: 0%;
        inherits: false;
      }
      @keyframes erase {
        to {
          --p: 100%;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <p>
        当页面加载时,.text
        元素中的文本会逐渐被擦除,就像用橡皮擦从左到右擦除一样。这是因为背景渐变从左到右移动,覆盖了文本,使其看起来像是被擦除。其中,@property --p:
        定义了一个名为 --p 的 CSS 自定义属性,其语法为百分比 (<percentage>),初始值为 0%,且不继承,这样动画才能起效果,不然css变量无法让动画起效。
      </p>
      <p class="eraser">
        <span class="text">
          当页面加载时,.text
        元素中的文本会逐渐被擦除,就像用橡皮擦从左到右擦除一样。这是因为背景渐变从左到右移动,覆盖了文本,使其看起来像是被擦除。其中,@property --p:
        定义了一个名为 --p 的 CSS 自定义属性,其语法为百分比 (<percentage>),初始值为 0%,且不继承,这样动画才能起效果,不然css变量无法让动画起效。</span
        >
      </p>
    </div>
  </body>

十二、多行文本溢出处理

    <style>
      .singleText {
        width: 200px;
        height: 30px;
        line-height: 30px;
        margin-bottom: 20px;
        border: 1px solid #f40;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .multilineText {
        width: 200px;
        height: 120px;
        line-height: 30px;
        border: 1px solid #f40;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 4;/* Firefox当前不支持-webkit-line-clamp */
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <div class="singleText">
      单行文本内容过长,此时将溢出内容隐藏,并用省略号展示
    </div>
    <div class="multilineText">
      多行文本内容过长,先创建一个多行文本的容器,再指定 Webkit-box 布局方向为
      垂直,然后限制显示文本行数,最后超出部分隐藏
    </div>
  </body>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值