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

# 快速导航

# 前言

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

# 示例效果

打字机效果

# 原生 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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

# 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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

# 分析

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

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

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

白色

关注公众号

一个走心,有温度的号,同千万同行一起交流学习

加作者微信

扫二维码 备注 【加群】

扫码易购

福利推荐