码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【动画进阶】类 ChatGpt 多行文本打字效果


    今天我们来学习一个有意思的多行文本输入打字效果,像是这样:

    这个效果其实本身并非特别困难,实现的方式也很多,在本文中,我们更多的会聚焦于整个多行打字效果最后的动态光标的实现。

    也就是如何在文本不断变长,在不确定行数的情况下,让文字的最末行右侧处,一直有一个不断闪烁的光标效果:

    单行文本打字效果

    在此之前,我们快速看一个之前在 【Web动画】科技感十足的暗黑字符雨动画 分享过的,非常简单的单行打字效果动画。

    在这里的单行打字效果,其核心就是就是让字符一个一个的出现,像是这样:

    这里借助了 animation 的 steps 的特性实现,也就是逐帧动画。

    从左向右和从上向下原理是一样的,以从左向右为例,假设我们有 26 个英文字符,我们已知 26 个英文字符组成的字符串的长度,那么我们只需要设定一个动画,让它的宽度变化从 0 - 100% 经历 26 帧即可,配合 overflow: hidden,steps 的每一帧即可展出一个字符。

    当然,这里需要利用一些小技巧,我们如何通过字符的数量知道字符串的长度呢?

    划重点:通过等宽字体的特性,配合 CSS 中的 ch 单位。

    如果不了解什么是等宽字体族,可以看看我的这篇文章 -- 《你该知道的字体 font-family》。

    CSS 中,ch 单位表示数字 “0” 的宽度。如果字体恰巧又是等宽字体,即每个字符的宽度是一样的,此时 ch 就能变成每个英文字符的宽度,那么 26ch 其实也就是整个字符串的长度。

    利用这个特性,配合 animation 的 steps,我们可以轻松的利用 CSS 实现打字动画效果:

    <h1>Pure CSS Typing animation.h1>
    
    h1 {
        font-family: monospace;
        width: 26ch;
        white-space: nowrap;
        overflow: hidden;
        animation: typing 3s steps(26, end);
    }
    
    @keyframes typing {
        0{
            width: 0;
        }
        100% {
            width: 26ch;
         }
    }
    

    就可以得到如下结果啦:

    完整的代码你可以戳这里:

    CodePen Demo -- 纯 CSS 实现文字输入效果

    上述单行文本打字效果局限

    当然,上述效果一开始已经写死了最终的文本。这一块,我们实际中可能是通过 Javascript 不断的赋值新内容。

    不过,即便去除掉文本内容生成的方式这个因素,上述看似美好的动画效果,还有几个弊端。

    1. 限制了等宽字体,这其实就是非常大的一个问题,正常的页面,其实用的肯定都不是等宽字体,常见的衬线与非衬线字体,都不是等宽字体。
    2. 限制了单行文本,实际效果,类似于 GPT 吐答案这种,单行内容肯定是无法满足的,我们需要有一种光标效果能适配多行文本的方式。

    巧用 background 实现多行光标效果

    好,那接下来,我们尝试换一种思路实现一个适配单行和多行的文本打字效果。

    首先,我们将文本内容的生成,替换成使用 Javascript 生成:

    <p id="content">p>
    
    const text = 'Lorem ipsum dolor sit amet consectetur adipisicing elit......';
    const contentElement = document.getElementById('content');
    let index = 0;
    
    function addNextCharacter() {
      if (index < text.length) {
        contentElement.textContent += text[index];
        index++;
        setTimeout(addNextCharacter, Math.random() * 150 + 30);
      }
    }
    
    addNextCharacter();
    

    效果如下:

    接下来,我们核心需要实现的就是任意行数下动态光标的效果。

    也就是最开始的这个效果,文字最后的光标效果:

    读到这里,暂停 10 秒,思考一下如果让你来实现,会用什么方式实现?能用什么方式实现?有没有低成本快速能实现的奇技淫巧?

    这里,我们可以使用行内元素的 background 渐变实现。

    复习一下,之前我们讲过很多次是 background 在display: inline 和 display: block 下的不同表现。

    其核心现象就是 display: inline 内联元素的 background 展现形式与 display: block 块级元素(或者 inline-block、flex、grid)不一致。

    简单看个例子:

    <p>Lorem .....p>
    <a>Lorem .....a>
    

    这里需要注意,

    元素是块级元素,而 是内联元素。

    我们给它们统一添加上一个从绿色到蓝色的渐变背景色:

    p, a {
      background: linear-gradient(90deg, blue, green);
    }
    

    看看效果:

    什么意思呢?区别很明显,块级元素的背景整体是一个渐变整体,而内联元素的每一行都是会有不一样的效果,整体连起来串联成一个整体。

    基于上述的 Demo,我们可以给它们添加一个 background-size 的动画。像是这样:

    <p>Lorem .....p>
    <a>Lorem .....a>
    
    p, a {
        color: #000;
        background: linear-gradient(90deg, blue, green);
        background-size: 100% 100%;
        background-repeat: no-repeat;
        transition: all 1s linear;
    }
    
    p:hover ,
    a:hover {
        background-size: 0 100%;
    }
    

    效果如下:

    完整代码戳这里:CodePen Demo -- background & display Animation DEMO

    就可以得到这样不同的动画,可以看到,在 display: inline 的 标签下,动画效果是以行为单位进行变换的。

    针对这个特性,我们将我们的文本容器,改为 display: inline,然后给他设置一个特殊的背景,前 100% - 2px 宽度为一个颜色,最后 2px 为一个颜色。

    我们继续改造一下我们上述的 DEMO:

    <p id="content">p>
    
    p {
        display: inline;
        background: linear-gradient(90deg, #fc0, #fc0 calc(100% - 2px), #f00 calc(100% - 2px), #f00);
    }
    

    其中核心的背景代码 background: linear-gradient(90deg, #fc0, #fc0 calc(100% - 2px), #f00 calc(100% - 2px), #f00) 表达的含义就是前 100% - 2px 宽度为橙色,最后 2px 为红色。

    看看,此时整个的效果:

    好好理解一下:

    基于上述这个效果:

    1. 我们只需要把前 100% - 2px 宽度的橙色,设置为透明
    2. 最后 2px 的红色,设置成 #000 黑色到 transparent 透明的动态变化

    完整的 CSS 代码如下:

    :root {
        --pointerColor: #000;
    }
    p {
        display: inline;
        background: linear-gradient(90deg, transparent, transparent calc(100% - 2px), var(--pointerColor) calc(100% - 2px), var(--pointerColor));
        animation: colorChange .8s linear infinite;
        padding-right: 4px;
    }
    @keyframes colorChange {
        0%, 50% {
            --pointerColor: #000;
        }
        50%, 100% {
            --pointerColor: transparent;
        }
    }
    

    如此一来,我们就成功的实现了任意行数下动态光标的效果。得到了最初的完整效果:

    整个 DEMO 的完整代码,你可以戳这里了解:CodePen Demo -- 多行打字效果

    整个方案的核心,在于理解如何利用内联元素的 background,巧妙的实现动态光标效果,需要好好理解其中的奥妙。

    当然,实现这个动态光标的方式还有很多,譬如,我们只需要用一个宽度为 2px 的 元素,插入到元素的最尾部,实现 #000 黑色到 transparent 透明的动态变化。

    只是文中这种方式,我认为是元素最少,且最为巧妙的方式。

    最后

    好了,本文到此结束,希望本文对你有所帮助 😃

    想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄

    更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

    如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

    想 Get 到最有意思的 CSS 资讯,千万不要错过我的 iCSS 公众号 😄 :

    image

    如果觉得文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
    打赏支持
    +

    (^_^)打个赏喝个咖啡(^_^)

    微信支付
    支付宝支付
  • 相关阅读:
    Linux底层基础知识
    js中运算规则
    统计遗传学:第二章,统计分析概念
    Patroni的pause和resume功能
    ONNX模型修改为自定义节点
    我的单片机入门之旅
    【SQL】数据库事务
    linux 安装docker
    LeetCode 53.最大子数组和17.电话号码的字母组合
    Python 中-m 模块的妙用
  • 原文地址:https://www.cnblogs.com/coco1s/p/18277457
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号