服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - node.js - Node.js 控制台动画,绘制跨年祝福

Node.js 控制台动画,绘制跨年祝福

2022-01-04 22:26神光的编程秘籍神说要有光zxg node.js

Node.js 里面可以通过 process.stdout.isTTY 来查看是否是 TTY 类型的标准输出流,然后提供了 readline 这个包来操作它。

Node.js 控制台动画,绘制跨年祝福

今天是 2021 年的最后一天了,明天就是 2022 年。回顾过去一年,要特别感谢大家对我的支持。

人生不过几十年,每一年都值得纪念和祝福,所以我想用 Node.js 控制台动画送上一份我的新年祝福:

Node.js 控制台动画,绘制跨年祝福

视频

2021 年的最后一天,我们来学点 cli 的技术吧。

实现原理

动画都需要一帧帧的刷新,控制台动画也不例外。

那控制台是怎么刷新的呢?

控制台中有一种叫做 TTY,特点是可以设置颜色,可以清除或修改某个位置的内容。平时我们用的 Terminal 大多都是这种。

Node.js 里面可以通过 process.stdout.isTTY 来查看是否是 TTY 类型的标准输出流,然后提供了 readline 这个包来操作它。

比如用 readline.cursorTo(stream, x, y) 来移动光标位置, readline.clearLine(stream) 来清除某行的内容,用 readline.clearScreenDown(stream)来清除某个位置之后的所有内容。

能够移动光标位置,能够清除内容,也就能够刷新、能够做任意的绘制,这是控制台动画的基础。

绘制用 readline.wrtie(data) 来输出字符,可以指定字符的颜色(用 chalk 这个包)。

只是输出带颜色的字符么?那张图片和那个艺术字呢?

其实那也是字符来做的,只不过给上了不同的颜色而已,控制台只能显示字符。

Node.js 控制台动画,绘制跨年祝福

左边的这张图片的显示原理是拿到图片的像素信息,然后转成不同颜色的字符。可以用 console-png 这个包。

Node.js 控制台动画,绘制跨年祝福

右边的艺术字的显示原理是固定的一些字符信息,设置上颜色。用的是 cfonts 这个包。

Node.js 控制台动画,绘制跨年祝福

小结一下:

TTY 类型的控制台可以设置颜色、可以在任意位置清除和修改内容,这是控制台动画能一帧帧刷新的基础,Node.js 提供了 readline 模块来做这些。

控制台只能显示字符,图片可以拿到像素信息然后用带颜色的字符来显示,艺术字是提前准备好字符数组来绘制,综合把这些内容绘制在不同的位置,然后定时一帧帧刷新就构成了控制台动画。

思路通了之后,我们来写代码实现一下。

代码实现

首先,我们会用到 readline 这个内置模块,用它来做一帧帧的刷新。

调用 readline.createInterface 来创建一个实例,指定输入输出流为 stdin、stdout。

stdin 是标准输入流,是指键盘。

stdout 是标准输出流,是指显示器。

  1. const readline = require('readline'); 
  2.  
  3. const outStream = process.stdout; 
  4.  
  5. const rl = readline.createInterface({ 
  6.     input: process.stdin, 
  7.     output: outStream 
  8. }); 

然后清除整个控制台的内容,把光标移动到开始,然后 clear:

  1. readline.cursorTo(outStream, 0, 0); 
  2. readline.clearScreenDown(outStream); 

然后开始绘制文字:

准备一个数组放要绘制的文字,然后定时在不同的位置显示这些文字

  1. const textArr = ['2021''感谢''大家的''支持','2022''我们','一起','加油!']; 
  2.  
  3. (async function () { 
  4.     for(let i = 0; i< textArr.length; i++) { 
  5.         readline.cursorTo(outStream, ...randomPos()); 
  6.         rl.write(randomStyle(textArr[i])); 
  7.  
  8.         await delay(1000); 
  9.         readline.cursorTo(outStream, 0, 0); 
  10.         readline.clearScreenDown(outStream); 
  11.     } 
  12. })(); 
  13.  
  14. function delay(time) { 
  15.     return new Promise((resolve) => setTimeout(resolve, time)); 

我用了 async await 的方式来组织代码,基于封装了一个 delay 方法。

其中位置、样式都是随机的:

  1. const chalk = require('chalk'); 
  2.  
  3. function randomPos() { 
  4.     const x = Math.floor(30 * Math.random()); 
  5.     const y = Math.floor(10 * Math.random()); 
  6.     return [x, y]; 
  7.  
  8. function randomStyle(text) { 
  9.     const styles = ['redBright','yellowBright''blueBright''cyanBright','greenBright''magentaBright''whiteBright']; 
  10.     const color = styles[Math.floor(Math.random() * styles.length)]; 
  11.     return chalk[color](text); 

前面的文字动画就做完了:

Node.js 控制台动画,绘制跨年祝福

然后是图片和艺术字的显示:

图片需要用 console-png 来把图片像素信息取出来转成字符的形式:

  1. const consolePng = require('console-png'); 
  2. consolePng.attachTo(console); 
  3.  
  4. const image = fs.readFileSync(__dirname + '/headpic.png'); 
  5. console.png(image); 

艺术字用 cfonts 来绘制,拿到字符之后显示在右边的位置:

  1. const CFonts = require('cfonts'); 
  2.  
  3. const prettyFont = CFonts.render('|HAPPY|NEW YEAR', { 
  4.     font:'block',  
  5.     colors: ['blue''yellow'
  6. }); 
  7.  
  8. let startX = 60; 
  9. let startY = 0; 
  10. prettyFont.array.forEach((line, index) => { 
  11.     readline.cursorTo(outStream, startX + index, startY + index); 
  12.     rl.write(line); 
  13. }); 

cfont.render 的第一个参数里的竖线是指换行,第二个参数的 font 是指定样式,colors 指定颜色。

然后对返回的字符数组做光标的偏移之后再显示。

最后,在右下方显示公众号的标记:

  1. readline.cursorTo(outStream, 120, 25); 
  2. rl.write(chalk.yellowBright('---神光的编程秘籍')); 

这样,最后这一帧就绘制完了:

Node.js 控制台动画,绘制跨年祝福

大功告成!我们再来看下整体的效果:

Node.js 控制台动画,绘制跨年祝福

视频

代码上传到了 github:https://github.com/QuarkGluonPlasma/cli-exercise

也在这里贴一份:

  1. const readline = require('readline'); 
  2. const chalk = require('chalk'); 
  3. const CFonts = require('cfonts'); 
  4. const consolePng = require('console-png'); 
  5. const fs = require('fs'); 
  6.  
  7. consolePng.attachTo(console); 
  8.  
  9. const outStream = process.stdout; 
  10.  
  11. const rl = readline.createInterface({ 
  12.     input: process.stdin, 
  13.     output: outStream 
  14. }); 
  15.  
  16. function delay(time) { 
  17.     return new Promise((resolve) => setTimeout(resolve, time)); 
  18.  
  19. function randomStyle(text) { 
  20.     const styles = ['redBright','yellowBright''blueBright''cyanBright','greenBright''magentaBright''whiteBright']; 
  21.     const color = styles[Math.floor(Math.random() * styles.length)]; 
  22.     return chalk[color](text); 
  23.  
  24. function randomPos() { 
  25.     const x = Math.floor(30 * Math.random()); 
  26.     const y = Math.floor(10 * Math.random()); 
  27.     return [x, y]; 
  28.  
  29. readline.cursorTo(outStream, 0, 0); 
  30. readline.clearScreenDown(outStream); 
  31.   
  32. const image = fs.readFileSync(__dirname + '/headpic.png'); 
  33.  
  34. const textArr = ['2021''感谢''大家的''支持','2022''我们','一起','加油!']; 
  35.  
  36. (async function () { 
  37.     for(let i = 0; i< textArr.length; i++) { 
  38.         readline.cursorTo(outStream, ...randomPos()); 
  39.         rl.write(randomStyle(textArr[i])); 
  40.  
  41.         await delay(1000); 
  42.         readline.cursorTo(outStream, 0, 0); 
  43.         readline.clearScreenDown(outStream); 
  44.     } 
  45.  
  46.     console.png(image); 
  47.  
  48.     await delay(1000); 
  49.     const prettyFont = CFonts.render('|HAPPY|NEW YEAR', {font:'block', colors: ['blue''yellow']}); 
  50.  
  51.     let startX = 60; 
  52.     let startY = 0; 
  53.     prettyFont.array.forEach((line, index) => { 
  54.         readline.cursorTo(outStream, startX + index, startY + index); 
  55.         rl.write(line); 
  56.     }); 
  57.  
  58.     readline.cursorTo(outStream, 120, 25); 
  59.     rl.write(chalk.yellowBright('---神光的编程秘籍')); 
  60. })(); 

总结

TTY 类型的终端支持设置字符颜色和在任意位置清除和修改内容,这是控制台动画可以刷新的基础。

我们通过把图片的像素转为有颜色的字符来显示图片,通过预置的字符数组来显示艺术字,在不同的位置绘制这些内容就可以达到丰富的显示效果。

其中,控制台的光标位置修改和内容的清除使用 Node.js 的 readline 内置模块,其余的是第三方的包。艺术字使用 cfonts 的包,图片显示使用 console-png,字体颜色使用 chalk。

控制台是我们每天都用的,前端的大多数工具都是 cli 的形式。深入学习 cli 显示各种内容和做动画的知识,有助于更好的理解一些 cli 工具和写出更好的 cli 工具。

最后,再次感谢大家过去一年的支持,明年一起加油呀~

原文链接:https://mp.weixin.qq.com/s/pPBeTqbZqoKFpuLusYE7Vg

延伸 · 阅读

精彩推荐
  • node.jsNode.js 中如何收集和解析命令行参数

    Node.js 中如何收集和解析命令行参数

    这篇文章主要介绍了Node.js 中如何收集和解析命令行参数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    descire8212021-12-28
  • node.jsNest.js环境变量配置与序列化详解

    Nest.js环境变量配置与序列化详解

    这篇文章主要给大家介绍了关于Nest.js环境变量配置与序列化的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价...

    Jaxson Wang11172022-01-21
  • node.jsnode.js文件的复制、创建文件夹等相关操作

    node.js文件的复制、创建文件夹等相关操作

    这篇文章主要给大家介绍了node.js文件的复制、创建文件夹等相关操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值...

    阳阳_申6272022-01-17
  • node.js在nodejs中创建child process的方法

    在nodejs中创建child process的方法

    这篇文章主要介绍了在nodejs中创建child process的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    flydean程序那些事7262022-01-07
  • node.js在浏览器中,把 Vite 跑起来了!

    在浏览器中,把 Vite 跑起来了!

    大家好,我是 ssh,前几天在推上冲浪的时候,看到 Francois Valdy 宣布他制作了 browser-vite[1],成功把 Vite 成功在浏览器中运行起来了。这引起了我的兴趣,如...

    前端从进阶到入院6432022-01-11
  • node.jsnodejs中的异步编程知识点详解

    nodejs中的异步编程知识点详解

    在本篇内容里小编给大家整理的是一篇关于nodejs中的异步编程知识点详解内容,有兴趣的朋友们可以学习下。...

    flydean12262022-01-04
  • node.jsNest.js 授权验证的方法示例

    Nest.js 授权验证的方法示例

    这篇文章主要介绍了Nest.js 授权验证的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    Jaxson Wang4202022-01-21
  • node.jsexpress项目文件目录说明以及功能描述详解

    express项目文件目录说明以及功能描述详解

    这篇文章主要给大家介绍了关于express项目文件目录说明以及功能描述的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    Shimily10482022-02-27