整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML 实例

TML 基础

非常简单的HTML文档

HTML 标题

HTML 段落

HTML 链接

HTML 图片

实例解析

HTML 标题

HTML 标题

在html源码中插入注释

插入水平线

实例解析

HTML 段落

HTML 段落

更多段落

本例演示在 HTML 文档中折行的使用。

HTML 格式化的某些问题。

实例解析

HTML 文本格式化

文本格式化

此例演示如何使用 pre 标签对空行和空格进行控制。

此例演示不同的"计算机输出"标签的显示效果。

此例演示如何在 HTML 文件中写地址。

此例演示如何实现缩写或首字母缩写。

此例演示如何改变文字的方向。

此例演示如何实现长短不一的引用语。

文本下划线与删除线

实例解析

HTML 样式

HTML Style 元素

背景色样式

字体样式,颜色,大小

文本对齐样式

设置文本字体

设置文本字体大小

设置文本字体颜色

设置文本字体,字体大小,字体颜色

HTML使用不同样式

没有下划线的链接

链接到一个外部样式表

实例解析

HTML 链接

创建超级链接

将图像作为链接

在新的浏览器窗口打开链接

链接到同一个页面的不同位置

跳出框架

创建电子邮件链接

创建电子邮件链接 2

实例解析

HTML 图像

插入图像

从不同的位置插入图片

排列图片

本例演示如何使图片浮动至段落的左边或右边。

制作图像链接

创建图像映射

实例解析

HTML 表格

简单的表格

没有边框的表格

表格中的表头

带有标题的表格

跨行或跨列的表格单元格

表格内的标签

单元格边距(Cell padding)

单元格间距(Cell spacing)

实例解析

HTML 列表

无序列表

有序列表

不同类型的有序列表

不同类型的无序列表

嵌套列表

嵌套列表 2

定义列表

实例解析

HTML Forms 和 Input

创建文本域(Text fields)

创建密码域

复选框

单选按钮

简单的下拉列表

预选下拉列表

本例演示如何创建一个文本域(多行文本输入控件)。

创建一个按钮

本例演示如何在数据周围绘制一个带标题的框。

带有文本域与输入域的表单

带有复选框与提交按钮的form表单

带有单选框与提交按钮的表单

发送邮件表单

实例解析

HTML iframe

内联框架 (HTML页面中插入框架)

实例解析

HTML 头部元素

描述了文档标题

HTML页面中默认的URL链接

提供文档元数据

实例解析

HTML 脚本

插入一个脚本

使用 <noscript> 标签

实例解析

如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!

章作者分享了一种基于设备模板的移动端原型设计方法,相信能够对你的原型设计工作带来帮助,值得马克。

在使用Axure设计移动端原型的应用方面,我总结出了两种常用的方法。第一种是更适合在移动端进行演示的设计方法,大家可以参考我之前已经分享过的一篇教程:使用Axure打造最佳的移动端交互原型教程,使用这种方法输出的原型在手机设备上进行演示时可以达到跟真实APP几乎一致的展示效果及交互体验。在今天我将分享另外一种基于设备模板的移动端原型设计方法。

什么是基于设备模板的移动端原型设计方法?简而言之就是在Axure的编辑界面中放置对应的机型模板,使输出的原型达到更规范和真实的演示效果。其实这是一种很常见的移动端原型的设计方法,很多同行在设计原型的时候也都用过。这篇分享教程将对个设计方法进行了总结和梳理,并基于这个方法制作了一套可快速复用的模板。这套模板具有几个方面的特点:

● 结构化,根据APP界面结构进行搭建;

● 标准化,非常方便进行编辑和维护;

● 高保真,可高度还原移动端交互效果;

在本篇分享的结尾我会提供模板的Axure源文件下载,其中包含了最新的IPhoneX和IPhone8等多套IOS设备机型,以及一些常见的界面元素和交互效果。在开始正式的介绍之前,大家可以查看使用这套模板还原IOS中两款官方应用的设计演示。

IOS11 AppStroe For iPhoneX 原型演示

IOS11 Contacts For iPhone8 原型演示

1.界面元素和结构介绍

由于这套模板是基于IOS系统进行设计的,所以相关界面元素和交互方式均以IOS为标准。目前主流的移动端系统除了IOS还有Android,这两种系统设计标准和交互方式其实是存在一些差异的,不过目前市面上大部分APP在设计时并没有争对两种系统做单独的处理。

所以如果没有特珠需求的话,我们一般也只需要输出一套原型方案就可以了,不过设计过程中需要尽量兼顾这两个主流的系统。当然,如果你的产品明确需要按照Android的系统规范来设计,你也可以参照本教程设计一套Android的原型模板,相关交互方式可以参照Android版的交互指南规范。

在开始介绍模板的搭建和使用方法之前,需要先对APP的界面结构做一个简单的介绍,熟悉了界面结构可以方便我们后续的设计。常见APP的界面主要由以下元素或组件组成:

StatusBar / 状态栏

状态栏显示设备的关键信息,包含设备模型或网络提供商、网络信号强度、电池使用量、时间等。在特殊界面中可以对状态栏做隐藏处理,或根据需要自定义状态栏背景。

NavBar / 导航栏

导航栏位于app内容区的上方,系统状态栏的下方,并且提供在一系列页面中的导航能力。可在导航栏中显示当前视图的标题,如果标题非常冗长且无法精简,可以空缺,避免用过多的元素填满导航栏。导航栏中可以添加文字和图标控件,相关控件的可点击区域需要大于控件的可视大小。

Body / 内容区

内容区域根据需要进行自定义设计,常见的设计形式有菜单列表、图标列表、卡片列表、图文组合等。

TabBar / 标签栏

标签栏位于APP底部,方便用户在不同功能模块之间进行快速切换。标签栏一般用作APP的一级分类,数量控制在3-5个之间。建议使用Badge进行提示,让用户知道有内容更新。

Toolbar / 工具栏

工具栏一般会出现在视图的的底部,提供给用户相关可操作的功能按纽。如,邮件应用程序里的收件箱栏中有删除、分享、答复等等。

Modal / 弹出层

移动端的弹出层根据弹出方式不同,共分为模态窗口、动作面板、弹出面板等几种不同的类型。在实际使用中,可根据界面的交互方式选择对应的类型。

Toast / 轻提示

一种轻量级反馈提示,可以用来显示不会打断用户操作的内容,适合用于页面转场、数据交互的等场景中。一次只显示一个轻提示,有图标的提示字数为4-6个,没有图标的轻提示字数不宜超过14个。

TableView / 列表视图

列表视图是移动端APP中一种通用的界面元素。很多应用程序在一定程度上,都有使用表视图来显示数据列表。常见的例如IOS的联系人应用中联系人信息列表,另外还有Mail中使用列表视图显示邮箱和邮件。列表视图不仅可以用来显示文本数据,也可以用来呈现图像数据。

以上是豆瓣APP的一个界面截图示例,界面的结构用颜色进行了区分,从上至下分别为:状态栏、导航栏、内容区、标签栏。

2.结构化的模板搭建

在介绍完APP的界面结构之后,接下来说明一下模板的搭建方法。在本篇教程的结尾会提供了已经制作好的模板的文件,大家可以下载并参考本部分介绍进行使用,也可以参照介绍制作自己的原型模板。

在制作模板时需要用到对应的机型设备的图片素材,可以通过Dribbble等设计分享平台找到对应的素材文件,然后对素材做一些简单的处理。处理的过程首先是去掉多余的元素,只保留机型设备的框架图片。另外还需要对图片的尺寸进行调整,例如在制作手机等移动端模板时我们将内容区域定为375px,需要根据所定的内容区域对图片的尺寸进行相应的调整。

为什么模板的内容区域是375px?这个问题我在上篇教程中进行过介绍,所以不再进行展开说明。但是需要记住的这个尺寸是一个重要的标准,后续在设计过程中相关元件的宽度尺寸都需要参照这个标准。机型设备的图片素材准备好之后,我们在Axure中创建一个对应的母版,然后将机型设备图片拖入到母版中。母版的名称可以按该机型设备的名称命名,后面在使用时在新建的页面中拖入该母版即可。

下一步需要创建前面介绍过的APP界面中常见元素或组件,首先大家可以看一下这张图片中已经创建好的模板,其中包含了机型母版、轻提示、弹层、导航栏、标签栏、内容框架等元素。

在这个模板页面的概要视图中可以看到相关的对象,所有对象我都创建了一个对应的动态面板。这样的处理主要出于两个方面的考虑,一是方便对相关元素进行编辑维护,二是相关对象的显示是有顺序的,这样可以方便在概要视图中进行排序处理。

3.模板使用细节说明;

在内容框架中编辑界面内容;

界面的主要内容在内容框架动态面板中进行编辑和维护,由于该动态面板设置了自动显示滚动条,如果你的界面内容超出了一屏,在演示时可以通过在内容框架区域滚动鼠标滚轮查看更多内容。

关于模板界面元素的尺寸说明:

模板中的界面元素的尺寸并没有非常严格的标准,以下尺寸是我根据比例进行设置的,仅供参考。IphoneX状态栏:44px、IphoneX标签栏:80px、Iphone8状态栏:28px、IphoneX标签栏:60px、导航栏:40px。另外,内容区域的高度因为机型设备的素材图片不统一可能略有差异,基本上可以忽略。

每个界面对应一个页面;

在设计原型时建议每一个界面创建一个对应的页面,通过添加页面链接进行界面跳转,这样方便对原型进行编辑和维护。不建议将多个界面用动态面板堆砌在一起页面内,这样会使输出的原型在演示时出现卡顿现象。

关于元素的层级顺序;

在概要视图中可以看到相关元素对应动态面板的层级顺序,在使用该模板的时候请尽量参照此顺序,否则可能在演示时出现显示错误的情况。

关于底部标签栏的设置;

为了方便维护可以将标签栏创建为母版,然后添加到需要显示标签栏的页面中。另外,在对应的页面中需要显示对应的标签选中效果,只需要在该页面中的标签栏动态面板中添加一个选中效果的标签元件。

热区占位符的使用;

如果页面中添加了标签栏或工具栏,由于标签页的动态面板在内容框架的动态面板之上,在演示时会出现内容有一部分被挡住的情况。可以创建一个高度为100px的热区元件为母版,将母版拖入对应的页面底部,用来解决内容区域被挡住的问题。

4.常用设计元素及规范

经常有朋友向我咨询如何设计出更漂亮美观的原型,虽然原则上原型能完整的体现出需求细节即可,好看并不是我们在原型输出时应该关注的重点,但是如果能满足说明需求的同时能把原型做得更漂亮一些更好,这也算是体现专业程度和工作态度的一个方面,而且很多人对自己的输出物也是有强烈的美感追求的。

其实原型设计不需要了解太复杂的设计方法,只要掌握一点简单的技巧就能达到美观的效果,同时能让整体更统一和标准。在分享的这套模板中包含了一些基本的设计元素,我下面对其中的一些规范细节进行说明,供大家进行参考。

配色方案

  • ◆ 一般采用黑白灰的配色方案就能够满足基本设计要求了,但是如果能稍微得加上一些亮色的配色效果,可以使原型更好的体现出视觉层级,这对UI是有一定的参考价值的。不要感觉得配色效果能够影响UI的设计,如果UI会被原型中的配色影响,只能说明UI的设计能力有待提升;
  • 整套原型中亮色主色调不要超过两个,对于主要按纽和重点提示可以加上主色调色值,次要元素统一使用#000000、#333333、#999999等灰色辅助色;
  • ◆ 模板中的这套模板方案中的主色调是从IOS11的UI设计规范中提取的,你可以根据自己的需要整理一套自己的配色方案,建议尽量使用扁平化设计色值;

配色板使用

Axure中的配色板提供了一些常用的颜色色值,可用作一些常用元素的颜色配色。例如截图中标注1中的纵向的灰色色值可用于相关字体元素的颜色,标注2中横向的灰色色值可用于相关元素的背景和线条的颜色。另外,点击标注3中的更多按纽,可以将其它的常用色值加入到自定义颜色中,方便快速的使用。

字体元素

  • ◆ 原型设计时的字体字号建议统一使用偶数,常用的标题字号为16px、18px、20px,常用的正文字号为12px、14px;
  • 针对不同字体大小的多行文本单独设置对应的行间距,例如12px的多行文本行间距建议设置为20,14px的多行文本行间距建议设置为28;
  • 推荐中文字体统一使用微软雅黑,由于Axure的默认字体为Arial,可以通过生成HTML设置中的字体映射,将Arial映射为微软雅黑,这样就不需要在设计时去单独设置每个元件的字体了。

其它元素

  • ◆ 原型设计时元件的宽度建议统一保持为5和10的倍数,元件的间距建议为10px或20px;
  • ◆ 使用键盘方向键移动选中的元件时每次移动距离为1px ,使用ctrl+键盘方向键每次移动距离为10px;
  • ◆ 按住Ctrl+鼠标拖动可以快速的复制元件,按住Shift+鼠标拖动可以垂直或水平的移动元件;

对齐及分布工具使用

  • 有对齐强迫症的朋友可以使用顶部工具栏中的对齐及分布工具对元件进行处理,右击顶部的工具栏区◆ 域可以自定义显示或隐藏相关的工具图标;
  • 选中多个元件时可以使用对齐工具快速的对多个元件进行各种对齐处理,还可以使用分布工具快速的对多个元件进行垂直或水平分布处理;

5.使用辅助线进行排版;

在以前的教程中已经介绍过辅助线的使用方法,合理的使用辅助线可以帮助我们提升设计效率,同时能让输出的原型效果更标准,所以强烈建议大家在设计过程中使用。以下是模板中内容框架编辑区域的截图,是我常用使用辅助线用来排版的方式。截图中的辅助线均为横向x轴辅助线,可以看到其中共有4条,分别介绍一下它们的作用和位置:

  • 第1条辅助线是用来划分左边的内容留白区域,例如我一般习惯将左边留白为20px,这条辅助线位于x轴的20px位置。
  • 第2条辅助线是内容居中辅助线,之前已经介绍过模板的设计宽度标准为375px,这条辅助线位于x轴的188px位置;(375px/2=187.5px)
  • 第3条辅助线用来划分右边的内容留白区域,例如右边跟左边留白一样为20px,这条辅助线位于x轴的355px位置;(375px-20px=355px)
  • 第4条辅助线是用来划分内容设计区域,例如模板的设计宽度标准为375px,这条辅助线位于位于x轴的375px位置;

这些辅助线的用法只是作为参考,可以根据自己的需要新建对应的辅助线。鼠标光标移动到编辑区域的左侧和顶部的标尺区域,按住鼠标左键并往编辑区域拖动时,就可以生成横向x轴或纵向y轴的辅助线,然后将辅助线拖动到对应的位置即可。辅助线还有一个特性就是当拖动元件靠近它时,元件会自动吸附到辅助线的边缘达到快速对齐的效果。

几点辅助线的使用小技巧:

  • 右击辅助线可以将其锁定,以防止拖动元件时会将辅助线会跟着一起移动;
  • 可以通过按住Ctrl拖动创建全局辅助线,全局辅助线就是在所有页面中产生一条相同的辅助线;
  • 在“布局—栅格和辅助线—锁定辅助线”中选中可以将所有的辅助线保持锁定状态且无法删除;
  • 在“布局—栅格和辅助线—删除辅助线”中可以清除所有页面中的辅助线;
  • 在“布局—栅格和辅助线—辅助线设置”中可以修改辅助线的颜色或进行更多设置;

6.Toast提示交互设置;

移动端原型中最常用的交互效果就是弹出层和轻提示两种,模板中已经包含了这种两交互效果的相关元件和事件,这里再单独简单的介绍一下。

Toast提示显示效果

在模板页面的概要视图中可以看到名为“提示”的动态面板,需要显示的提示信息在这个动态面板中编辑就可以了。当前的动态面板中有一个“操作成功”的提示状态,如果在一个页面中显示多个提示,可以新增对应的状态然后修改相关的提示内容。

选中提示的动态面板的状态右击选择复制状态可以快速创建新的提示。建议对每个对应的提示状态进行命名,这样方便后续进行管理。关于轻提示的基本使用规范请参照前面的介绍内容。

Toast提示的显示方式设置很简单,只需要在对应的元件事件上加入以上的交互动作。首先设置提示动态面板中对应的状态,然后设置显示动态面板,显示时有一个逐渐的动画效果。

Toast提示显示以后会在3秒后自动逐渐隐藏,模板中的这个交互动作已经加在提示动态面板的显示时事件中了,不需要再单独的进行设置。

7.常用弹层交互设置

模态窗口交互效果

移动端的弹层共分为模态窗口、动作面板、弹出面板等几种不同的类型。在模板页面的概要视图中可以看到名为“弹层”的动态面板,可以根据需要创建更多其它的弹层状态,还能在对应的面板状态属性中设置透明背景的遮罩效果。

上面截图中的为比较常见的模态窗口弹层效果,设置方式是在对应的元件事件上加入以上的交互动作。另外,根据模态窗口、动作面板、弹出面板这几种弹层类型的弹出方式不同,需要设置显示时为向上滑动和逐步等动画效果。

8.导航栏切换交互设置

最后介绍一下如何实现内容区域滚动时,导航栏自动切换的交互效果。首先需要在导航栏的动态面板中创建对应的状态,然后选中内容框架动态面板,在它的滚动时事件中按照上面的格式加入对应的条件判断即可。

在这个设置用到了条件判断和函数,条件的详细设置见上方的截图。它的原理是当内容框架垂直滚动高度大于70时设置导航栏动态面板的显示状态为2,当内容框架垂直滚动高度大小于70设置导航栏动态面板的显示状态为1。其中用到的This.scrollY函数是获取当前元件的直滚动高度,70的值可以根据需要自己设置。

好了,到此这篇基于设备模板的移动端原型设计方法的分享基本介绍完了。最后提供的是iPhoneX And iPhone8 Mockup 原型模板的源文件下载,大家可以结合本文中的相关介绍进行使用。

最后再给大家分享一套本人整理设计的移动端元件库,这套元件库中的相关元件是可以在这个模板中复用的,后续也会不断的进行优化和完善,有需要的朋友可以关注一下。

在学习和工作中,我们经常需要使用日志来记录程序的运行状态和调试信息。而为了更好地区分不同的日志等级,我们可以使用不同的颜色来呈现,使其更加醒目和易于阅读。

在下图运行结果中,我们使用了 colorlog 库来实现彩色日志输出。通过定义不同日志等级对应的颜色,我们可以在控制台中以彩色的方式显示日志信息。例如,DEBUG 级别的日志使用白色,INFO 级别的日志使用绿色,WARNING 级别的日志使用黄色,ERROR 级别的日志使用红色,CRITICAL 级别的日志使用蓝色。

但是在查看日志文件时,我们会发现日志信息是系统默认的字体颜色,并且前后多了一些特殊符号,例如 [32m 等。这是因为在控制台中使用的是 ANSI 转义序列来实现彩色文本效果,而这些特殊符号是 ANSI 转义序列的一部分。如下图所示:

现在有一个需求,在前端页面直接查看日志内容并还原彩色文本效果,因此,我们将进行以下内容讲解:

  1. 什么是 ANSI 转义序列?
  2. 如何在前端页面直接查看日志内容?
  3. 如何在前端页面还原彩色文本效果?

本文代码点击此处跳转,往期系列文章请访问博主的 项目实战专栏,博文中的所有代码全部收集在博主的 GitHub 仓库中;

ANSI 转义序列

ANSI 转义序列是美国国家标准化组织(American National Standards Institute,ANSI)制定的标准,是一种用于控制文本终端显示的特殊字符序列。它们以 3[ 开头,以字母和数字组合的形式表示不同的控制功能。

ANSI 转义序列可以用于控制文本的颜色、背景色、文本样式(如粗体、斜体等)、光标位置、清屏等操作。通过在输出文本中插入适当的 ANSI 转义序列,可以实现丰富的终端显示效果。

以下是一些常用的 ANSI 转义序列示例:

  • 3[0m:重置所有属性,恢复默认设置;
  • 3[31m:设置文本颜色为红色;
  • 3[42m:设置背景颜色为绿色;
  • 3[1m:设置文本为粗体;
  • 3[4m:设置文本为下划线;
  • 3[2J:清屏;

需要注意的是,ANSI 转义序列在不同的终端和操作系统上的支持程度可能会有所不同。在某些终端中,可能无法正确解释和显示 ANSI 转义序列。

我们以 3[31m 和 3[42m 为例,输出一个绿底红字的句子 Hello World! --sidiot.,代码如下所示:

log.debug("3[42m3[31mHello World! --sidiot.3[0m3[0m")

运行结果:

前端页面直接查看日志内容

这里的话,我们使用 Python 的 http.server 模块来启动一个简单的 HTTP 服务器。

比较快捷的方式就是在日志文件夹中打开终端,输入 python -m http.server 8888 即可,运行结果如下所示:

不过这种方式相对来说还是不太安全的,因此我们可以通过设置白名单的方式,来规避一些潜在的安全隐患,代码如下所示:

import http.server
import socketserver

class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def check_client_address(self):
        # 设置白名单,只允许特定的IP地址或主机访问
        whitelist = ['127.0.0.1', 'localhost']

        client_address = self.client_address[0]
        if client_address not in whitelist:
            self.send_response(403)
            self.end_headers()
            self.wfile.write(b'Forbidden. Please contact sidiot.')
            return False

        return True

    def do_GET(self):
        if not self.check_client_address():
            return
        
        super().do_GET()

with socketserver.TCPServer(('0.0.0.0', 8888), HTTPRequestHandler) as httpd:
    httpd.serve_forever()

目前本机的 IP 为 192.168.124.23,当我们以 127.0.0.1 来访问 8888 服务端口时,访问是成功的,但是当我们用 192.168.124.23 来访问服务端口时,访问是失败的。

运行结果:

现在我们点击文件,它会直接通过浏览器直接下载,但是我们需要的是在网页上能够直接阅览文件中的内容,因此我们可以从 do_GET() 下手。

我们可以设计一个根据传入的文件名参数,读取本地文件并作为响应结果进行返回的方法,然后根据一定的规则进行触发,代码如下所示:

def read_file(self):
    try:
        self.send_response(200)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.end_headers()
        self.wfile.write(open(self.path[6:], 'rb').read())

    except FileNotFoundError:
        self.send_response(404)
        self.end_headers()
        self.wfile.write(b'File not found!')

def do_GET(self):
    if self.check_client_address():
        if self.path.startswith("/?log="):
            self.read_file()
        else:
            super().do_GET()

上述代码通过检查请求的资源路径来处理 GET 请求。如果请求的资源路径前缀是 /?log=,且是当前目录下存在的日志文件,它会读取文件并将其内容作为响应发送。否则,它会使用基类的默认行为处理普通的 GET 请求。

运行结果:

至此,我们已经实现了前端页面直接查看日志内容的功能。

前端页面还原彩色文本效果

原理分析

当我们想要在前端页面展示 ANSI 字体的彩色效果时,我们只需要简单地将 ANSI 转义序列转换成相应的 HTML 代码就可以实现了。这个转换过程实际上可以通过编写一个 Python 函数来实现,该函数可以接受包含 ANSI 控制码的字符串作为输入,并将其转换为带有相应样式的 HTML 代码输出,代码如下所示:

def convert_ansi_to_html(ansi_text):
    ansi_to_html = {
        '\x1b[31m': '<span style="color: red;">',
        '\x1b[42m': '<span style="background-color: green;">',
        ...,
    }
    html_text = re.sub(r'\x1b[[0-9;]*m', lambda match: ansi_to_html.get(match.group(0), ''), ansi_text)

    return html_text


if __name__ == '__main__':
    ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
    print(ansi)
    html = convert_ansi_to_html(ansi)
    print(f"convert content: {html}")

需要注意的是,在 ANSI 转义序列中,\x1b 和 3 都代 表ASCII 码中的 Escape 字符,用于开始一个转义序列。

运行结果:

使用 ansiconv 转换

接下来,我们借助已有的库函数 ansiconv 进行 ANSI 的转换。

通过 pip 进行安装:

pip install ansiconv

根据 ansiconv 的官方文档使用其中的三个方法 to_plain(),to_html() 和 base_css() 来实现在前端页面展示 ANSI 字体的彩色效果,代码如下所示:

import ansiconv

ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(f"Ansi: {ansi}")
plain = ansiconv.to_plain(ansi)
html = ansiconv.to_html(ansi)
print(f"Convert Plain: {plain}")
print(f"Convert HTML: {html}")

在 base_css() 中会有相关的 CSS 映射表,如下所示:

css_rule('.ansi31', color="#FF0000"),
css_rule('.ansi42', background_color="#00FF00"),

运行结果:

研究 ansiconv 源码

我们将通过研究 ansiconv 的源码,以便深入了解它是如何将 ANSI 转换成纯文本或 HTML 代码的工作原理。

to_plain() 的源码如下所示:

上述代码使用正则表达式匹配字符串中的 ANSI 转义序列,并将其替换为空字符串,从而得到不包含转义序列的纯文本。

正则表达式的含义如下:

  • \x1B:匹配 ESCAPE 字符;
  • \[:匹配左方括号;
  • [0-9;]*:匹配零个或多个数字或分号;
  • [ABCDEFGHJKSTfmnsulh]:匹配 ANSI 转义序列中的控制字符;

我们通过 re.findall() 方法来获取所有匹配的结果,这样够清晰地捕获所有符合条件的匹配项,从而更好地理解 ansiconv 是如何进行 ANSI 到纯文本的转换,代码如下所示:

ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(re.findall(r'\x1B[[0-9;]*[ABCDEFGHJKSTfmnsulh]', ansi))

运行结果:


to_html() 的源码如下所示:

上述代码将 ANSI 字符串分割成块,并对每个块调用 _block_to_html() 函数进行解析和转换,同时还处理了 ANSI 命令 "A",模拟向上移动光标的行为。如果 replace_newline 为 True,则 HTML 字符串中的换行符 \n 将替换为 <br />\n 以保留 HTML 输出中的换行符。

其中 _block_to_html() 的源码如下所示:

上述代码使用正则表达式匹配 ANSI 代码,并根据匹配结果生成对应的 HTML 代码。

正则表达式的含义:

  • ^:表示匹配字符串的开头。
  • \[:匹配左方括号 [。
  • (?P<code>\d+(?:;\d+)*)?:这是一个命名捕获组,用于匹配 ANSI 代码中的数字部分。它由以下组成: \d+:匹配一个或多个数字。 (?:;\d+)*:这是一个非捕获组,用于匹配分号 ; 和一个或多个数字的重复出现。(?: ... ) 表示非捕获组,* 表示重复零次或多次。
  • (?P<command>[Am]):这是另一个命名捕获组,用于匹配 ANSI 代码中的命令部分。它由以下组成: [Am]:匹配字符 A 或 m。

我们可以通过运行源码里的部分代码来帮助理解,代码如下所示:

text = ("\x1B[0;32;45msidiot\n"
        "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m")
print(text)
blocks = text.split('\x1B')
print(blocks)
for block in blocks:
    match = re.match(r'^[(?P<code>\d+(?:;\d+)*)?(?P<command>[Am])', block)
    if match is not None:
        print("\nmatch:", match, ", code:", match.group('code'), ", command:", match.group('command'))

运行结果:

实际应用

通过深入理解 ANSI 转换思路和 ansiconv 源码,我们可以为之前的 http.server 服务带来全新的优化。

首先,将原先的 read_file() 方法进行优化,代码如下所示:

def read_file(self, content_type, file_io):
    try:
        self.send_response(200)
        self.send_header("Content-Type", f"{content_type}; charset=utf-8")
        self.end_headers()
        self.wfile.write(file_io)

    except FileNotFoundError:
        self.send_response(404)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.end_headers()
        self.wfile.write(b'File not found!')

上述代码通过接收 content_type 和 file_io 两个参数,实现将自定义内容作为响应返回给客户端。

然后修改请求路径,使其能够返回纯文本HTML 两种不同类型的内容,代码如下所示:

def do_GET(self):
    if self.check_client_address():
        if self.path.startswith("/?plain="):
            file = open(self.path[8:], 'rb').read()
            plain = ansiconv.to_plain(file.decode('UTF-8'))
            self.read_file("text/plain", plain.encode())
        elif self.path.startswith("/?html="):
            file = open(self.path[7:], 'rb').read()
            conv = ansiconv.to_html(file.decode('UTF-8'))
            css = ansiconv.base_css()
            html = """
            <html>
              <head><style>{0}</style></head>
              <body>
                <pre class="ansi_fore ansi_back">{1}</pre>
              </body>
            </html>
            """.format(css, conv)
            print(html)
            self.read_file("text/html", html.encode())
        else:
            super().do_GET()

这里要注意的是,需要设置 CSS 样式,不然 class 类是无法进行渲染的。

纯文本运行结果:

HTML 运行结果:

后记

在本文中,我们探讨了如何实现将 ANSI 字体在前端页面进行彩色展示的方法。在前端页面中直接显示 ANSI 转义序列是不起作用的,因为浏览器不会解析和处理这些转义序列。

为了在前端页面实现彩色展示,我们介绍了一种方法,即将 ANSI 转义序列转换为对应的 HTML 代码。通过解析 ANSI 转义序列并将其转换为适当的 HTML 标签和样式,我们可以在前端页面上还原彩色文本的效果。

在本文中,我们使用了 Python 中的 ansiconv 库来实现 ANSI 转换。该库提供了 to_plain 和 to_html 两个方法,分别用于将 ANSI 转义序列转换为纯文本和 HTML 代码。我们还展示了如何使用这些方法来转换 ANSI 字符串,并在前端页面上显示转换后的结果。

通过本文的介绍,读者可以了解到如何在前端页面实现彩色文本的展示,从而提升用户体验和可读性。无论是在日志查看器、终端模拟器还是其他需要展示彩色文本的应用中,这种技术都能发挥重要作用。

以上就是 从终端到浏览器:实现 ANSI 字体在前端页面的彩色展示 的所有内容了,希望本篇博文对大家有所帮助!欢迎大家持续关注我的博客,一起分享学习和成长的乐趣!✨

作者:sidiot
链接:https://juejin.cn/post/7381820436274184202