Js 如何实现一个类似 chatGPT 打字机效果

news2025/1/10 15:36:08

d496f5a0a512e99f73d27148ad7811c6.png

在使用chatGPT的时候,会有一个打字机的效果,以下是分别使用原生JsVue实现

96bba45857c70954491aafeb686b61b4.gif

原生 JS 实现

如下是示例代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Printer 打字机效果</title>
    <style>
        * {
            margin: 0;
            border: 0;
            padding: 0;
            font-family: "Courier New", Courier, monospace;
        }
        
        #window {
            width: 600px;
            height: 400px;
            background-color: black;
            margin: 100px auto;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
        }
        
        #title-bar {
            width: 595px;
            height: 20px;
            line-height: 20px;
            padding-left: 5px;
            font-size: 14px;
            background-color: #eee;
            font-family: Consolas, serif;
        }
        
        #title-bar span:before {
            content: "\25cf";
        }
        
        #title-bar span {
            font-size: 24px;
        }
        
        #close {
            color: red;
        }
        
        #min {
            color: yellow;
        }
        
        #max {
            color: #00FF00;
        }
        
        tilte-title {
            font-family: 'Arial Black', SimHei;
            font-weight: bold;
        }
        
        #show-board {
            width: 580px;
            height: 360px;
            background-color: #333;
            color: #eee;
            padding: 10px;
            font-family: "Courier New", Courier, monospace, Consolas, serif;
        }
    </style>
</head>

<body>

    <div id="window">
        <div id="title-bar"><span id="close"></span><span id="min"></span><span id="max"></span><strong id="tilte-title">&nbsp;Console</strong></div>
        <div id="show-board"></div>
    </div>

    <script>
      (function(root, factory){
 if(typeof define === 'function' && define.amd){
  define([], factory);
 }else{
  root.Printer = factory(root);
 }
}(this, function(root){
 var Printer = {};
 Printer.printer = {"version": "0.0.1"};
 var init_options = {
  "speed" : 50,  //文字的速度
  "selector" : 'canvas',  //要打印到的标签的ID   
  "startIndex" : 0,  //从第几个字符开始打印
  "endIndex" : 0,  //打印到第几个字符结束
  "hasCur" : true,  //是否有光标
  "curId" : 'cur',  //光标的ID
  "curStr" : '_',  //光标字符
  "curStyle" : 'font-weight: bold;', //光标的样式(CSS样式)
  "curSpeed" : 100,  //光标的速度(ms)
  "lnStr": ""
 };



 var str = "", options = init_options;
 var flwCurTimer, dom, curObj, reStr='', curSwitch,index=0;

 Printer.init = function(arg_str, arg_options){
  str = arg_str;
  for( var option in arg_options ){
   options[option] = arg_options[option];
  }
  dom = document.getElementById(options.selector);
  index = options.startIndex;
  options.endIndex = options.endIndex == 0 ? str.length : options.endIndex
  options.hasCur && flwCur();
  return this;
 }


 Printer.print = function(){ //打印函数
  for(var i=0; i<str.length; i++) {
   (function(index){
    setTimeout(function(){ 
     if (str.charAt(index) === '\n'){
      reStr += '<br>' + options.lnStr;
     } else {
      reStr += str.charAt(index);
     }
     dom.innerHTML= options.lnStr + reStr
    }, options.speed * (index + 1))
   })(i);
  }

  setTimeout(function(){
   if(options.hasCur){
    var element = document.createElement("span");
    element.id = options.curId
    dom.appendChild(element);

    curObj = document.getElementById(options.curId);
    clearTimeout(flwCurTimer);
    setInterval(chCur, options.curSpeed);
   }
  }, options.speed * str.length)
 }

 function flwCur(){ //跟随光标
  dom.innerHTML += '<span id="'+options.curId+'" style="'+options.curStyle+'">'+options.curStr+'</span>';
  flwCurTimer = setTimeout(flwCur, 1.5 * options.speed);
 }

 function chCur(){ //闪烁光标
  curObj.innerHTML = curSwitch ? options.curStr : "";
  curSwitch = !curSwitch
 }

 return Printer;
}));
    </script>
    <script>
        var str = 'itclanCoder\n';
        str += 'https://coder.itclan.net\n';
        str += '书以启智,技于谋生,活出斜杠\n';
        str += '微信公众号:itclanCoder\n';
        str += 'exit\n';
        Printer.init(str, {
            selector: 'show-board',
            lnStr: 'root@itclanCoder ~/ # '
        }).print();
    </script>
</body>

</html>

#Vue版本实现

如下是使用vue方式实现

<template>
  <div class="daziji-box">
    <div class="content"></div>
    <div class="textarea">
     <textarea v-model="message" placeholder="请输入文字后回车看看效果" @keydown.enter="handleEnter"></textarea>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg:'你好,我是模仿ChatGPT的打字机效果',
      message:'',
    }
  },
  mounted() {
    this.autoWriting(0)
  },
  methods:{
    handleEnter() {
      event.preventDefault();//阻止enter键回车换行
      this.msg=this.message
      const dom = document.querySelector('.content')
      dom.innerHTML = ''
      this.writing(0)
      this.message=''
    },
    autoWriting(index){
        const dom = document.querySelector('.content')
        const data = this.msg.split('')
        if (index < data.length) {
            dom.innerHTML += data[index]
            setTimeout(this.autoWriting, 200, ++index)
        }
    }
  }
}
</script>

<style>
   
.daziji-box .content {
    margin: 20px 0;
}    
.daziji-box .content::after{
    content: '_';
    animation: blink 1s infinite
}
@keyframes blink{
    from{
        opacity: 0;
    }
    to{
        opacity: 1;
    }
}

</style>

分析

实现这个打字机的效果,核心逻辑,主要是在autoWriting这个方法的实现,页面初始化加载自动打印

通过setTimeout设置200毫秒的时间间隔, 每隔200毫秒向dom中插入对应的数据,先将输入的字符串进行打散(split),然后一个一个插入到DOM节点

至于那个光标闪烁,是通过一个伪类after将光标定在这个class的最后面, 并使用动画的关键帧,实现显示隐藏的循环动画,模拟光标的闪烁

来自爱客来智能助手答案

以下是爱客来智能助手的回答

实现类似 chatGPT 打字机效果的方法可以通过 JavaScript 的 setTimeout 方法和字符串截取来实现,步骤如下:

  1. 将要打印的文本内容存储到一个字符串变量中;

  2. 通过 DOM 操作,找到需要输出的文本区域;

  3. 设置一个变量用于记录当前输出的字符数,初始值为 0;

  4. 设置一个变量用于存储 setTimeout 方法的返回值,初始值为 null;

  5. 使用 setTimeout 方法,每隔一定时间截取文本字符串前面的 n 个字符并显示到文本区域中,同时更新当前输出的字符数;

  6. 当输出完整个文本字符串后,停 setTimeout 方法。以下是具体代码实现:

const text = "这是要输出的文本内容,类似PT 的打字效果"; 
const typing = () => { const output = document.getElementById("output");
let count = 0; 
let timer = null; const print = () => {
  const subText = text.substring(0, count + 1); 
  output.textContent = subText; 
  count++; if (count === text.length) {
  clearTimeout(timer); 
} else {
  timer = setTimeout(print, 50); // 每隔 50 毫秒输出一个字符 } 
}; 
 print(); 
}; 
typing();

这段代码会在页面载入时自动执行 typing 函数,实现类似 chatGPT打字机效果的效果。同时,可以通过更改 setTimeout 方法的第二个参数以调整打印速度

以下也是爱客来智能助手另外一个答案

要实现类似 chatGPT 打字机效果,我们需要用 ·JavaScript· 来模拟打字过程。下面是一个简单的实现方法:

  1. 定义一个字符串,表示要打出的完整文本。比如:const text = "Hello, world!"

  2. 将该字符串转化为一个字符数组。比如:const characters = text.split("")

  3. 定义一个计数器变量,表示已经显示出来的字符数。初始值为 0。

  4. 创建一个定时器,每隔一定时间(比如 100ms)将下一个字符显示出来。可以使用 setInterval 函数实现。

  5. 在每次定时器回调函数中,使用 slice 函数从字符数组中取出前 counter + 1 个字符拼接成一个新字符串,然后将该字符串设置为要在页面上显示的文本。例如:document.getElementById("text").innerText = characters.slice(0, counter + 1).join("")

  6. 在每个定时器回调函数中,将计数器加 1。

  7. 当计数器等于字符数组的长度时,停止定时器。例如:if (counter === characters.length) clearInterval(timer)

下面是一份示例代码:

const text = "Hello, world!";
const characters = text.split("");
let counter = 0;
const speed = 100; // 打字的速度,单位为毫秒

const timer = setInterval(() => {
  // 拼接出当前应该显示的文本
  const currentText = characters.slice(0, counter + 1).join("");
  // 将文本显示在页面上
  document.getElementById("text").innerText = currentText;

  // 增加计数器
  counter++;

  // 如果已经显示完全部字符,停止定时器
  if (counter === characters.length) {
    clearInterval(timer);
  }
}, speed);

需要注意的是,这只是一个简单的实现方法,还有很多细节需要考虑,比如打字结束后是否要添加一些额外的操作,比如将光标移动到另一个位置等等。

总结

总得来说,实现这个打字机效果,是将这个字符进行打散成数组,然后通过定时器,设置间隔时间,一个一个的插入到指定的DOM节点上,就可以了的

56275f365cb93dcd576f2a1c12c413a9.png

b4449c7043a9796eb0db8cd9e614deb8.png

50194c2b1ebc6786a6097f66b9012684.png

当在网页浏览器的地止栏中输入URL或关键词时,web页面是如何呈现的?

2023-05-22

7bbbc61680dc9bd7db52d98866c47908.jpeg

想转正?不存在的,你被证明不符合录用条件,解除通知书收好

2023-05-18

362324e4fb0aeb6624401255cab3954b.jpeg

关于左耳朵耗子的一些创业,工作,生活,技术,学习等思考

2023-05-17

ec81e320c72dff77700d6e10b2a7e02f.jpeg

47岁技术大佬陈皓(左耳朵耗子)去世,叛逆人生不断创业,网友们纷纷留言悼念

2023-05-15

59bb0a0b889b7c54b4d0681e51f31e36.jpeg

css几种高效方案如何适配首屏可视区区域

2023-05-15

70763673632705142abf65b3cff05f4b.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/561803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录--使用率比较低的10个Web API

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 avaScript中有些API可能使用率比较低&#xff0c;下面我们逐一介绍它们的用法和使用场景。 至于标题&#xff0c;主要是想让你进来看看&#xff0c;兄弟们别打我&#xff01; Blob API Blob API 用于处…

电脑技巧:CopyQ剪切板增强工具介绍(附下载)

目录 1、软件简介 2、主要功能介绍 3、使用说明 4、总结 今天给大家再分享一款剪切板增强工具——CopyQ&#xff0c;感兴趣的朋友可以下载试一试&#xff01; 1、软件简介 CopyQ 是一款开源的、跨平台剪贴板管理工具&#xff0c;支持 Windows、macOS、Linux&#xff0c;可…

项目中遇到的一些问题总结(十)

nacos保护阈值 Nacos 中的保护阈值&#xff08;Protection Threshold&#xff09;是用来保护服务实例的一种机制。当某个服务实例出现故障或异常时&#xff0c;服务注册中心 Nacos 会通过心跳检测等方式将其从服务列表中移除&#xff0c;以避免客户端继续向其发送请求。但是&a…

在Linux中为Simulink添加ROS自定义消息类型

在Linux中为Simulink添加ROS自定义消息类型 基于Matlab/Simulink的ROS自定义消息类型的添加方法 ROS与Simulink联合仿真(三):自定义Message 1、下载 ROS Toolbox Interface for ROS Custom Messages 将 roscustommsg.mlpkginstall 文件放入 MATLAB 工作空间 双击 roscustommsg…

Nature -- 人类首个 “泛基因组”旨在编目人类遗传多样性

在人类基因组项目发布第一个人类基因组草图的20多年后,研究人员发布了人类“泛基因组”草图——这预示着一种新的参考基因组的出现,它能捕获到更多的人类遗传多样性信息。 泛基因组变异图由两个元素组成:序列图&#xff0c;其ode表示定向DNA链&#xff0c;双向边表示连通性关系…

学系统集成项目管理工程师(中项)系列25_计算机网络知识

1. OSI七层协议 1.1. 物理层 1.1.1. RS232、V.35、RJ-45、FDDI 1.2. 数据链路层 1.2.1. 【21上选17】 1.2.2. IEEE802.3/.2、HDLC、PPP、ATM 1.3. 网络层 1.3.1. IP、ICMP、IGMP、IPX、ARP 1.3.2. 路由选择 1.3.2.1. 【20下选17】 1.4. 传输层 1.4.1. TCP、UDP、SPX…

越小越好: Q8-Chat,在英特尔至强 CPU 上体验高效的生成式 AI

大语言模型 (LLM) 正在席卷整个机器学习世界。得益于其 transformer 架构&#xff0c;LLM 拥有从大量非结构化数据 (如文本、图像、视频或音频) 中学习的不可思议的能力。它们在 多种任务类型 上表现非常出色&#xff0c;无论是文本分类之类的抽取任务 (extractive task) 还是文…

又一批令人惊艳的 AI 工具,诞生了!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 自 ChatGPT 发布以后&#xff0c;AIGC 行业的热度也一直在持续发酵。几个月过去了&#xff0c;对比之前&#xff0c;各类 AI 工具的热度不减反增&#xff0c;各行各业的人都早开始拥抱 AIG…

SAP工具箱 MR22自定义BAPI

点击蓝字 关注我们 一 前言 标准事务代码MR22 通过调整金额影响物料的成本价,前台界面中单个凭证中允许输入多行物料, 但是对应的BAPI函数仅支持输入单行物料 BAPI_MATVAL_DEBIT_CREDIT 正常库存BAPI_SALESORDSTCK_DEBIT_CREDIT 销售订单库存 这种情况 婶可忍叔不可忍 (感谢用户…

Python 闭包装饰器和多任务--闭包,装饰器,进程,线程

1.闭包案例 在函数嵌套的前提下&#xff0c;内部函数使用了外部函数的变量&#xff0c;并且外部函数返回了内部函数&#xff0c;我们把这个使用外部函数变量的内部函数称为闭包. 外层函数: config_name(),外层函数中的变量是 name 内层函数: inner(),inner()使用了外层函数的变…

34从零开始学Java之构造方法都有哪些特性?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在前面的几篇文章中&#xff0c;壹哥给大家介绍了不少关于方法的内容&#xff0c;这些内容是我们日常…

zabbix监控之javasnmp自定义监控

1、客户端开启 java jmxremote 远程监控功能 上传 tomcat 软件包到 /opt 目录中 cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mv apache-tomcat-9.0.16 /usr/local/tomcat #配置 java jmxremote 远程监控功能 vim /usr/local/tomcat/bin/catalina.sh ...... #位置在 cygw…

嵌入式音视频开发面试过程遇到的问题!

前言&#xff1a; 今天继续给大家分享音视频面试过程会被常问到的一些问题&#xff01; 面试的具体题目&#xff1a; 1、说一下播放器的设计过程&#xff1a; 这里的话主要分以下几步完成&#xff1a; 开启一个线程进行解封装操作 , 这包括&#xff1a;读取音频、视频的压缩数据…

chatgpt赋能Python-python_ps图片

Python PS图片的SEO指南 Python在数字图像处理中广泛应用。其中&#xff0c;Photoshop文件&#xff08;psd&#xff09;是一种常见的图像文件格式。但是&#xff0c;如何在搜索引擎上优化Python PS图片并提高其排名仍然是一个挑战。 什么是Python PS图片&#xff1f; Python…

数据结构和算法基础学习1

​​​​​​​ 网址第01周b--1.1数据结构研究_哔哩哔哩_bilibili

学C的第十九天【实用调试技巧:1. 调试;2. Windows环境调试介绍;3. 一些调试的实例;4. 一些调试的实例】

相关代码gitee自取&#xff1a;C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a;学C的第十八天【指针初阶&#xff1a;5. 指针和数组、6. 二级指针、7. 指针数组&#xff1b;初识结构体&#xff1a;1. 结构体的声明、2. 结构体成员的访问、3. 结构体传参&#xff1b…

java中的栈、堆、方法区

栈&#xff08;stack&#xff09; Java栈与堆不同每一个线程都有一个stack&#xff0c;栈的区域非常小&#xff0c;大概只有1M左右&#xff0c;但是存储速度非常快&#xff0c;所以我们把快速执行的任务存储在stack。 特点&#xff1a;自动分配&#xff0c;连续空间&#xff0…

如何从文档中提取结构化数据?parsio.io

parsio.io 产品名&#xff1a;Parsio电子邮件解析器 技术&#xff1a;采用人工智能技术的电子邮件解析器。 支持多种格式&#xff1a; 可以解析电子邮件和附件中的数据&#xff0c;包括PDF、HTML、XLSX&#xff08;Excel&#xff09;、CSV、DOCX、XML、TXT等格式。 提取模版&am…

FANUC机器人作为EtherCAT通信从站的相关配置方法

FANUC机器人作为EtherCAT通信从站的相关配置方法 基本介绍: 前提条件: 硬件部分: 机器人需要使用EtherCAT从站板卡 A20B-8101-0821。使用带屏蔽层的网线连接板卡和PLC的网口。 本例中使用的网络接口为EC-IN(CD38Y) 软件部分: 机器人需要安装软件:1A05B-2600-J743! Et…

NLog使用

Nlog 日志组件的使用 这个博文关注 .net framework下的NLog日志组件的使用. 在项目中需要将日志写到日志文件中, 另外一些重要信息要显示在界面上. 使用 NLog 可以轻松做到这点.NLog wiki 页面 nuget 安装两个主要组件 NLogNLog.Windows.Forms 使用总结 日志文件 layout 按照 j…