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

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

猜你喜欢

转载自blog.csdn.net/wzc_coder/article/details/130838312