说在前面
echarts图表我们见多了,有没有想过在控制台实现一个图标呢?本文将带您领略 Node.js 的魅力,教您如何使用 JavaScript 代码在控制台中一键绘制出令人惊叹的柱状图。我们将一起揭示背后的技巧,包括数据处理、格式化输出和绘图算法,让您轻松将数据转化为视觉艺术,并且为您的控制台应用增添一份独特的魅力。
效果展示
实现步骤
1、获取最大公约数
获取数据集合的最大公约数,并将数据集合中的每个元素都除以这个最大公约数,使得所有数据可以被放缩到一个较小的范围内。
function gcd(a, b) { if (b === 0) { return a; } return gcd(b, a % b); } function findGCD(numbers) { if (numbers.length === 0) { return null; } let result = numbers[0]; for (let i = 1; i < numbers.length; i++) { result = gcd(result, numbers[i]); if (result === 1) { return 1; } } return result; }
2、格式化数值
将每个数字格式化为固定位数的字符串,并居中对齐
function getShowNum(num, barWidth) { const numLen = (num + "").length; const dif = barWidth - numLen; const left = Math.floor(dif / 2); return " ".repeat(left) + num + " ".repeat(dif - left); }
3、数据化简
将柱形图数据化简,所有数据除以他们的最大公约数,通过设置的maxHeight计算柱状图条形的高度缩放比例 scaleFactor。
let data = options.data; const { maxHeight, barSpacing = 2 } = options; const result = findGCD(data); data = data.map((item) => { return item / result; }); const max = Math.max(...data); const barWidth = (max * result + "").length; const min = Math.min(...data); const scaleFactor = maxHeight / (max - min);
4、绘制柱状图
从 maxHeight 开始循环,逐行输出柱状图。对于每一行,先初始化 row 为一个竖线符号“|”和一个绿色 ANSI 转义码,用于表示柱状图条形的颜色。然后遍历数据集合中的每个元素,根据其大小和 scaleFactor 的结果,输出相应数量的空格或实心方块字符。
开头输出一个 | 作为y轴,最下方输出一行  ̄ 作为x轴。
let maxLen = 0; for (let i = maxHeight + 3; i > 0; i--) { let row = "| \x1B[32m"; data.forEach((value) => { const scaledValue = Math.floor(value * scaleFactor); if (scaledValue === i) row += getShowNum(value * result, barWidth); else if (scaledValue >= i) { for (let j = 0; j < barWidth; j++) { row += "█"; } } else { for (let j = 0; j < barWidth; j++) { row += " "; } } for (let j = 0; j < barSpacing; j++) { row += " "; } }); maxLen = Math.max(maxLen, row.length); console.log(row + "\x1B[39m"); } console.log(" ̄".repeat((maxLen / 3) * 2));
5、完整代码
const { findGCD } = require("../utils"); function getShowNum(num, barWidth) { const numLen = (num + "").length; const dif = barWidth - numLen; const left = Math.floor(dif / 2); return " ".repeat(left) + num + " ".repeat(dif - left); } function printBarChart(options) { let data = options.data; const { maxHeight, barSpacing = 2 } = options; const result = findGCD(data); data = data.map((item) => { return item / result; }); const max = Math.max(...data); const barWidth = (max * result + "").length; const min = Math.min(...data); const scaleFactor = maxHeight / (max - min); let maxLen = 0; for (let i = maxHeight + 3; i > 0; i--) { let row = "| \x1B[32m"; data.forEach((value) => { const scaledValue = Math.floor(value * scaleFactor); if (scaledValue === i) row += getShowNum(value * result, barWidth); else if (scaledValue >= i) { for (let j = 0; j < barWidth; j++) { row += "█"; } } else { for (let j = 0; j < barWidth; j++) { row += " "; } } for (let j = 0; j < barSpacing; j++) { row += " "; } }); maxLen = Math.max(maxLen, row.length); console.log(row + "\x1B[39m"); } console.log(" ̄".repeat((maxLen / 3) * 2)); } // 使用示例 const options = { data: [3, 7, 2, 5, 8, 12], maxHeight: 10, barWidth: 2, barSpacing: 1, }; printBarChart(options);
后续
目前只实现了一个简单的雏形样板,后续会考虑完善更多的功能和样式,并封装成一个插件,有兴趣的同学们可以提点建议和想法。
公众号
关注公众号『前端也能这么有趣
』,获取更多有趣内容。
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。