您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

如何实现可复用的控制台“艺术字”打印功能 {导航网站源码}

  • 时间:2022-08-10 01:09 编辑: 来源: 阅读:267
  • 扫一扫,手机访问
摘要:如何实现可复用的控制台“艺术字”打印功能 {导航网站源码}
在使用少量开源项目之前,经常会在控制台上看到项目输出的大LOGO。 例如,当hexo minos的主题启动时,控制台中会显示“minos”副本,而当fis3启动时,也会显示“fis”。加上这种大字号的“艺术字”,可以达到“品牌曝光”的效果,当然也是程序员特有的“趣味”的表达 但是,它们的实现无非是通过console.log输出排列好的Logo 这种方法的问题是几乎没有复用能力,少数需要转义的情况会导致字符串的可维护性差。 因此,我花了一个周末的时间来实现一个易于使用和可重用的控制台“艺术字”库。 这样,下次有新的需求,只要你想把正常的文字传给它,它就能自动为你排列打印。 1.图1。目标如前一节所述,目前一般项目的做法是自己写一串具体的文本,比如Minos:logger . info(`=======================================███╗███╗██╗███╗██╗██████╗███████╗████╗████║██║████╗██║██╔═══██╗██╔════╝██╔████╔██║██║██╔██╗██║██║██║███████╗██║╚██╔╝██║██║██║╚██╗██║██║██║╚════██║██║╚═╝██║██║██║╚████║╚██████╔╝███████║╚═╝╚═╝╚═╝╚═╝╚═══╝╚═════╝╚══════╝=============================================`);还有就是logo fis 3 =['/\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ n \ \ n \ \ n//////////\ \ n/////\ \ n////\ \ n///\ ',' \ \/\ \ n \n \n \n \n \n//n \n \n \n \n///\ \ n \n \n///\ ',' \ \ n \n \n \n \n \\\\\\\n\\\\\\\njoin(' \ n ');这些方法都是通过“硬编码”来实现的。如果有新的项目或需求变化,就要重新安排和调整。 所以准备实现一个可以根据输入的字符串自动排版显示的控制台“艺术字”打印库。例如,它将输出:/\ \ \/\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \/\ \ \ \ \ \ \ \ \ \ \ \/\ \ \ \ \/\ \ \ _ _/\ \ \ \\\\\\\\\\\\\\\\\\\\\\\/ \ \ \\\\\\\\/ \ \ \ \/\ \ \ \ \ \/\ \ \ \/\ \ \ \/\ \ \ \/\ \ \ \/\ \/\ \ \ \/\ \ \ \/\ \ \ \/\ \/\ \ \ \/\ \/\ \ \ \/\ \/\ \ \ \/\ \ \ \/\ \ \ \/\ \/\ \ \ \/\ \ \ \/\ \/\ \ \ \ \ \/\ \ \ \/\ \/\ \ \/\\\\\\\\\\\\/ \\\\\\\\\\\/ \\\\\\/ \\\/ \\\\\\\\\\\ \/\\\\/ \\\\\\\\\/ \\\\\\\\\\\\\\\\\\\/ \\\\\\\ \ \\ \\ \\ \\ \\ \\ \\\ \ \\_____/ \/\\\ \\\ \\\ /\\\_____/\\\ \/\\\ \\\ \/\\\ \/\\\_____/ \/\\\ /\\\ \/\\\ \/\\\ \/\\\ \\\ \\\ \/\\\ \ /\\\ \/\\\ /\\\ \/\\\ \/\\\ \/\\\ /\\\ /\\\ \/\\\\\\\\\\ \/\\\ \\\ \\\ /\\\\\\\\\ \/\\\ \/\\\ \/\\\ /\\\ /\\\ \/\\\\\\\\\\ \/\\\ \/\\\ /\\\ \/\\\_____/ \/\\\ \\\ \\\ \/_______/ \/\\\ \/\\\ \/\\\ \/\\\ /\\\ \/\\\_____/ \/\\\ \ /\\\ \\\ \/\\\ \/\\\ \\\\\ \\\ \/\ \\ \/\\\ \/\\\ \ /\\\ \\\ \/\\\ \/\\\ \/_\\\\\\ \/\\\\\\\\\\ \/\\\\\__/\\\\\ \/_/\\\\\\\\\ \/\\\ \/_\\\\\\ \/\\\\\\\\\\ \ /_/\/_ _ _ _/\/_ _ _ _ _ _ _/\/_/\/_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 基于这个目标,开发了库yoo-hoo。 下面大致说一下如何实现。 2.如何实现类似于其他字体的显示需求,我们一般可以把功能分为三个部分:字体库的生成,字体的排版和渲染。这里先说一下字体的渲染。 2.1.字体渲染之所以先说这部分,是因为它会影响排版信息的输出格式。 其实字体渲染也没什么特别的。在控制台环境中,我们受到API的限制。基本上,我们使用console.log将内容“呈现”到屏幕上。 但是,正是这里的“渲染”的局限性,会使我们的排版方式发生逆转。 我们知道,控制台基本上是单一顺序渲染的,大致是一个“Z”字型。 同时,由于我们的“艺术词”会占据多行,最终的渲染也不是按照单个词的顺序,所以需要先排好版本,然后再按照线条逐步渲染到屏幕上。 这有点像我们常见的打印机。 如果你要打印一个苹果,它会从上到下逐渐打印苹果,而不是像打印邮票一样直接打印苹果。 接下来我们先详细介绍字体库的生成,而不是接下来的字体布局。 由于排版是承上启下的环节,当我们确定了上下游环节,这一块的逻辑自然也就确定了。 2.2.字体库生成当我们要实现复用时,需要在系统中寻找或概括出逻辑最小复用单元——这里显然是一个字符。 简单来说,在输入字符串JS时,如果能找到J和S对应的字符表示,辅以排版,理论上就能达到目的。 有点像我们祖先的活字印刷术。 所以在字体库中,我们将有一个字义和字体之间的映射。 其实这个思路和我们前台常见的字体文件格式是一样的,需要这样的映射关系。 字体从何而来?嗯,我也用了一个笨办法——“手绘”自己。 比如,下面是我的“手绘”1:1/\ \ \/\ \ \ \/_/\ \ \ \ \/\ \ \ \ \ \ \ \ 1 当然,这只是一次性工作。一旦创建了一种类型的“字体”,以后就不需要重复这项工作了。 我把以上内容放在一个单独的文件里,带后缀。目前直接txt,这是我们原来的字体格式。 不放进去的原因。js就是\在JavaScript中是转义的,这样文字的视觉效果和最终的渲染效果不一致,不利于调试和维护。 原字体文件分为两部分:最上面第一行是字义,支持一个字义对应一个图形。 例如,和*我用了同样的图形。 多重含义用空格隔开,不用换行符。 除了第一行,剩下的就是字体了。 理论上我们可以把这个原始的字体文件作为字体库,通过NodeJS中的fs模块读取并解析文件内容就可以得到映射关系。 但是我希望它也可以用在非NodeJS的环境中(比如浏览器),所以我不能依赖fs模块。 这里,制作一个原始文件解析脚本来生成相应的JS模块。 因为我们不直接维护这些生成的JS模块,所以它的可读性并不重要。在设计数据格式时,可以完全面向后续的排版过程。 首先,实现一个简单的解析器来解析第一行的含义。 这也类似于一个词法解析器,但是因为语法规则极其弱智(简单),就不用说了。大致如下:const parse definition = function(line:string){ let token = ' ';const defs:string[]=[];for(第行的const char){ if(char = = = ' ' & amp;& amptoken){ defs . push(token);令牌=“”;} if (char!= = ' '){ token+= char;} } if(token){ defs . push(token);}返回defs}这里是字体解决方案部分。 需要解决字体是因为上面提到的转义问题。 因为我们用\以原来的格式显示字体,直接放到生成的JS文件中,所以这个\就变成了转义符,需要\ \才能正常显示。 一种方法是常规匹配,将所有源文本中的\ \替换为\ \并重新写入。 但我选择了另一条路。 字符被转换为字符代码存储。charCodeAt方法,然后在读取字体信息时通过String.fromCharCode传输回来。 原来的字符串变成了数值类型的数组,所以不存在特殊字符的问题。 最后通过对文本进行拼接,生成JS文件,将原来的有利于人们维护的字体文件转换成编译JS的模块。 const arrayToString = & ltT & gt(arr:T[])= & gt;['+arr . map(d = & gt;` ' ${d} ' `)。join(',')+']';const text = parsed fonts . reduce((t,f,idx)= & gt;{ return t+(' \ n/* * \ n '+f . content+' \ n */\ n '+` fonts[$ { idx }]= { \ n `+ ` defs:$ { arrayToString(f . defs)},\ n `+ ` codes:$ { arrayToString(f . codes)} \ n `+ ' };\ n’);}, '');const module text =(' const fonts =[];\ n '+text+' module . exports . fonts = fonts;\ n’);fs.writeFileSync(fontFilepath,moduleText,' utf-8 ');Defs是该字体对应的字义列表,codes是字体的char码数组。所有字体都放在一个JS文件中。 这里第3行的parsedFonts是遍历原字体文件的所有解析内容,所以还需要通过NodeJS的fs模块递归读取源文件目录下的字体文件才能得到这部分。 这是基本的,所以你不必执行它。 因为这部分可以提前解析编译,所以JS模块一旦生成,就不会依赖NodeJS运行时,仍然可以在浏览器中运行。 2.3.字体的排版我们的字体格式已经确定,目标的渲染方式也已经确定。 最后可以填充这部分的逻辑实现。 具体排版会遇到少量的细节,比如不等高字体的空行填充,最大线宽的断行判断(要求客户进行线宽),但这些都是小点,解决方法并不太复杂。 这里可能会有一点特殊的一块——字间距调整。 我们知道,少数艺术字可能有很大程度的倾斜,比如“1”这个字:/\ \ \/\ \ \/\ \ \ _/\ \ \/\ \ \/\ \ \ \ \ \ \ \ \\\\\ 比如上图,我的两个包围盒距离其实只有1,但是看起来很大。 我们实际想要的可能是这样的:当图像间距为1时,两个字符“1”被调整到最近的地方间距为1。 如果想要更宽的效果,可以设置更大的间距。 要解决这个问题,主要需要计算最大“挤压空间”(即两个盒子支撑的最大交叉空间)。 刚开始渲染的时候,说是我们根据控制台传来的台词存储打印的。比如这个“1”的高度是8,那么在渲染的时候就是8个元素的字符串数组:constlines = ['/\ \ \ ','/\ \ \ ',' \/_ _/. '\/\\\', ' \/\\\', ' /\\\\\\\', ' \/_____/',];直接lines . foreach(l = >;Console.log(l))就可以了。 注意,为了方便读者,我没有对上面lines数组中的字符串进行转义,这是非法的!只是为了更容易阅读和理解,实际中不可能这样写。 最大缩进量的计算(缩进这个词不准确,但希望你能理解那个意思)只需要知道前面每一行的末尾有多少个空格,同时需要在那之后添加新的字符,每行前面有多少个空格。综合两者,遍历所有线取最小值://calc前缀空间const前缀空间= function(str:string){ const matched =/\ s+/gu . exec(str);退货匹配?匹配了[0]。长度:0;};//calc the tail space const tail space = function(str:string){ const matched =/\ s+$/gu . exec(str);退货匹配?匹配了[0]。长度:0;};// calc布局需要缩进多少个空格// overwise两个字符之间的间距将是不同的const calc indent = function(lines:string[],charLines: string[]): number { //不破坏布局的最大缩进量let maxPossible = Infinityfor(设I = 1;我& ltlines.lengthi++){ const former tail num = tail space(lines[I]);const latterPrefixNum = prefix space(charLines[I]);max possible = math . min(max possible,former tail num+latterPrefixNum);}返回maxPossible};最后,calcIndent方法返回新字符需要向前缩进(或收紧)的值。 渲染结束时,根据该值调整连接每条线时添加的空格数。 顺带一提,之前的字体格式加载会转换成类似字典的格式——单词含义为key,字体等属性为value:const dictionary = { ' a ':{ lines:[...],宽度:...,高度:...,},' b': {...}, ...}这使得split在拆分客户传入的字符串后,更容易索引对应的字体和字体信息。 2.4.剩下的,当然会有少量的工作给剩下的,包括支持颜色支持,返回排版行,让客户自己渲染,支持客户自己设置调整字距。目前实现中遇到的这些问题都不大,篇幅原因就不说了。 具体代码可以在Github上看到。 3.总结并实现可复用的控制台“艺术字”功能。总的来说,没有太多复杂的点。整体流程模型是生成字体库->:排版->:渲染文本。这对于前台来说应该是非常容易理解的。 做这个项目真的是我希望在我的工作中把这个logo或者banner展示加入到少数的库中,但是每次重复枯燥的工作真的很恶心。 于是,在考虑了可行性之后,我做了一个类似yoo-hoo的小玩意。如果大家都遇到类似的问题,希望能有所帮助。 NPI哟呼4。最后,目前yoo-hoo@1.0.x内置了26个字母(A-Z),10个数字(0-9),*-|。 考虑到单一字体和有限数量的字体无法满足所有需求,代码结构在开发时留了支持外部扩展的模式。 随后,2.2节中的字体源文件解析工具可以独立出来,允许客户“手绘”自己的字体。工具生成相应的格式后,将字体的JS模块传入yo方法,作为扩展字体加载。 虽然源文件的“手绘”有成本,但所见即所得,写起来并不难。同时也算是一劳永逸。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)
【技术支持|常见问题】别告诉我你没看过邰方这两则有思想的创意广告! (2022-11-04 10:37)
【技术支持|常见问题】你正确使用https了吗? [php源码](2022-11-04 10:37)
【技术支持|常见问题】安全超文本传输协议 {源码分享}(2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部