matplotlib 第2部分 艺术画笔见乾坤

第二部分 matplotlib 再认识

1. matplotlib 的三层 api

matplotlib 画图原理跟人画画很类似,如下:
1. 准备一块画布或画纸
2. 准备好颜料、画笔等制图工具
3. 作画
matplotlib.backend_bases.FigureCanvas 代表了绘图区,所有的图像都是在绘图区完成的.
matplotlib.backend_bases.Renderer 代表了渲染器,可以近似理解为画笔,控制如何在 FigureCanvas 上画图.
matplotlib.artist.Artist 代表了具体的图表组件,即调用了 Renderer 的接口在Canvas 上作图.

2. Artist 的分类

Artist 有两种类型:primitives 和 containers.
primitive 是基本要素,包含一些在绘图区作图用到的标准图形对象,如曲线 Line2D,文字 text,矩形 Rectangle,图像 image 等.
container 是容器,即用来装基本要素的地方,包括图形 figure、坐标系 Axes和坐标轴 Axis. 关系如下所示:
在这里插入图片描述

3. 基本元素

3.1 2D Lines

在 matplotlib 中曲线的绘制,主要是通过类 matplotlib.lines.Line2D 来完成的. 其中常用的的参数有:

  • xdata: 需要绘制 line 中的点在 x 轴上的取值,若忽略,则默认为range(1,len(ydata)+1)
  • ydata: 需要绘制 line 中的点在 y 轴上的取值
  • linewidth: 线条的宽度
  • linestyle: 线型
  • color: 线条的颜色
  • marker: 点的标记
  • markersize: 标记的 size

3.1.1 设置 Lin2D 的属性

  • 直接在plot()函数中设置
  • 通过获得线对象,对线对象进行设置
  • 获得线属性,使用setp()函数设置
# 1. 直接在plot()函数中设置
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=range(0,5)
y=[2,5,7,8,10]
plt.plot(x,y,linewidth=5,linestyle=':',color='m')#设置线的粗细为5、线型为虚线、颜色为品红色
plt.show()

在这里插入图片描述

# 2. 通过获得线对象,对线对象进行设置
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=range(0,5)
y=[2,5,7,8,10]
line,=plt.plot(x,y,linewidth=8,linestyle='-.',color='g')#这里等号坐标的line,是一个列表解包的操作,目的是获取plt.plot返回列表中的Line2D对象
line.set_antialiased(False)#关闭抗锯齿功能
plt.show()

在这里插入图片描述

# 3. 获得线属性,使用 step() 函数设置
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=range(0,5)
y=[2,5,7,8,10]
lines=plt.plot(x,y)
plt.setp(lines,color='k',linewidth=10,linestyle='--');

在这里插入图片描述

3.1.2 绘制 lines

  • 绘制直线 line
  • errorbar 绘制误差折线图
#1.1 plot方法绘制
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=range(0,5)
y1=[2,5,7,8,10]
y2=[3,6,8,9,11]
fig,ax=plt.subplots()
ax.plot(x,y1,linewidth=2,linestyle='-',color='r',marker='o',markersize=10)
ax.plot(x,y2,linewidth=2,linestyle='--',color='c',marker='x',markersize=10)
print(ax.lines); # 通过直接使用辅助方法画线,打印ax.lines后可以看到在matplotlib在底层创建了两个Line2D对象

在这里插入图片描述

# 1.2 Line2D 对象绘制
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=range(0,5)
y1=[2,5,7,8,10]
y2=[3,6,8,9,11]
fig,ax=plt.subplots()
lines=[Line2D(x,y1,color='k',linestyle='--'),Line2D(x,y2,color='orange')]  # 显式创建Line2D对象
for line in lines:
    ax.add_line(line) # 使用add_line方法将创建的Line2D添加到子图中
ax.set_xlim(0,4)
ax.set_ylim(2,11);

在这里插入图片描述
errorbar 绘制误差折线图
pyplot 里有个专门绘制误差线的功能,通过 errorbar 类实现,其中最主要的参数是前几个:

  • x:需要绘制 line 中的点在 x 轴上的取值
  • y:需要绘制 line 中的点在 y 轴上的取值
  • yerr:指定 y 轴水平的误差
  • xerr:指定 x 轴水平的误差
  • fmt:指定折线图中某个点的颜色,形状,线条风格,例如 ‘co–’
  • ecolor:指定 error bar 的颜色
  • elinewidth:指定 error bar 的线条宽度
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import numpy as np
fig=plt.figure()
x=np.arange(10)
y=2.5*np.sin(x/20 * np.pi)
yerr=np.linspace(0.05,0.2,10)
plt.errorbar(x,y+3,yerr=yerr,fmt='co--',ecolor='r',elinewidth=3)
plt.show()

在这里插入图片描述

3.2 patches

matplotlib.patches.Patch 类是二维图形类,并且它是众多二维图形的父类,它的所有子类见 matplotlib.patches API .

3.2.1 Rectangle-矩形

Rectangle 矩形类在官网中的定义是:通过锚点 xy 及其宽度和高度生成. 在实际中最常见的矩形图是 hist 直方图和 bar 条形图.
1) 直方图
下面是一些常用的参数:

  • x: 数据集,最终的直方图将对数据集进行统计
  • bins: 统计的区间分布
  • range: tuple, 显示的区间,range 在没有给出 bins 时生效
  • density: bool,默认为 false,显示的是频数统计结果,为 True 则显示频率统计结果,这里需要注意,频率统计结果=区间数目/(总数*区间宽度),和 normed 效果一致,官方推荐使用 density
  • histtype: 可选 {‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’} 之一,默认为bar,推荐使用默认配置,step 使用的是梯状,stepfilled 则会对梯状内部进行填充,效果与 bar 类似
  • align: 可选 {‘left’, ‘mid’, ‘right’} 之一,默认为 ‘mid’,控制柱状图的水平分布,left 或者 right,会有部分空白区域,推荐使用默认
  • log: bool,默认 False, 即 y 坐标轴是否选择指数刻度
  • stacked: bool,默认为 False,是否为堆积状图
# hist 绘制直方图
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import numpy as np
x=np.random.randint(0,100,100) #生成[0-100)之间的100个数据,即 数据集
bins=np.arange(0,101,10) #设置连续的边界值,即直方图的分布区间[0,10),[10,20)...
plt.hist(x,bins,color='y',alpha=0.5,) #alpha设置透明度,0为完全透明
plt.xlabel('scores')
plt.ylabel('count')
plt.xlim(0,100) # 设置x轴分布范围 
plt.show()

在这里插入图片描述

# Rectangle 矩形类绘制直方图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
df=pd.DataFrame(columns=['data'])
df.loc[:,'data']=x
df['fenzu']=pd.cut(df['data'],bins=bins,right=False,include_lowest=True)
df_cnt=df['fenzu'].value_counts().reset_index()
df_cnt.loc[:,'mini']=df_cnt['index'].astype(str).map(lambda x:re.findall('\[(.*)\,',x)[0]).astype(int)
df_cnt.loc[:,'maxi']=df_cnt['index'].astype(str).map(lambda x:re.findall('\,(.*)\)',x)[0]).astype(int)
df_cnt.loc[:,'width']=df_cnt['maxi']-df_cnt['mini']
df_cnt.sort_values('mini',ascending=True,inplace=True)
df_cnt.reset_index(inplace=True,drop=True)
# 用Rectangle把hist绘制出来
fig=plt.figure()
ax1=fig.add_subplot(111)
for i in df_cnt.index:
    rect=plt.Rectangle((df_cnt.loc[i,'mini'],0),df_cnt.loc[i,'width'],df_cnt.loc[i,'fenzu'])
    ax1.add_patch(rect)
ax1.set_xlim(0,100)
ax1.set_ylim(0,16);

在这里插入图片描述
2) bar-柱状图
下面是一些常用的参数:

  • left:x 轴的位置序列,一般采用 range 函数产生一个序列,但是有时候可以是字符串
  • height: y 轴的数值序列,也就是柱形图的高度,一般就是我们需要展示的数据
  • alpha:透明度,值越小越透明
  • width:为柱形图的宽度,一般这是为 0.8 即可
  • color 或 facecolor:柱形图填充的颜色
  • edgecolor:图形边缘颜色
  • label:解释每个图像代表的含义,这个参数是为 legend() 函数做铺垫的,表示该次 bar 的标签
    有两种方式绘制柱状图
  • bar 绘制柱状图
  • Rectangle 矩形类绘制柱状图
# bar 绘制柱状图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
y=range(1,17)
plt.bar(np.arange(16),y,alpha=0.5,width=0.5,color='c',edgecolor='g',label='The First Bar',lw=3)
plt.show()

在这里插入图片描述

# Rectangle 矩阵类绘制柱状图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
fig=plt.figure()
ax1=fig.add_subplot(111)
for i in range(1,17):
   rect=plt.Rectangle((i+0.25,0),0.5,i,edgecolor='r')
   ax1.add_patch(rect)
ax1.set_xlim(0,16)
ax1.set_ylim(0,16);

在这里插入图片描述

3.2.2 Polygon-多边形

matplotlib.patches.Polygon 类是多边形类. 构造函数如下:
class matplotlib.patches.Polygon(xy, closed=True, **kwargs)
xy 是一个 N×2 的 numpy array,为多边形的顶点.
closed 为 True 则指定多边形将起点和终点重合从而显式关闭多边形.
matplotlib.patches.Polygon 类中常用的是 fill 类,它是基于 xy 绘制一个填充的多边形,定义如下:
matplotlib.pyplot.fill(*args, data=None, **kwargs)
参数说明 : 关于 x、y 和 color 的序列,其中 color 是可选的参数,每个多边形都是由其节点的 x 和 y 位置列表定义的,后面可以选择一个颜色说明符. 您可以通过提供多个 x、y、[颜色]组来绘制多个多边形.

# 用fill来绘制图形
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
x=np.linspace(0,5*np.pi,1000)
y1=np.sin(x)
y2=np.sin(2*x)
plt.fill(x,y1,color='r',alpha=0.3);

在这里插入图片描述

3.2.3 Wedge-契形

matplotlib.patches.Polygon 类是多边形类. 其基类是 matplotlib.patches.Patch. 一个 Wedge-契形 是以坐标 x,y 为中心,半径为r,从θ1扫到θ2(单位是度). 如果宽度给定,则从内半径 r-宽度到外半径 r 画出部分楔形. wedge 中比较常见的是绘制饼状图.
制作数据 x 的饼图,每个楔子的面积用 x/sum(x) 表示.
其中最主要的参数是前 4 个:

  • x:契型的形状,一维数组
  • explode:如果不是等于 None,则是一个 len(x) 数组,它指定用于偏移每个楔形块的半径的分数
  • labels:用于指定每个契型块的标记,取值是列表或为 None
  • colors:饼图循环使用的颜色序列. 如果取值为 None,将使用当前活动循环中的颜色
  • startangle:饼状图开始的绘制的角度
# pie 绘制饼状图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Circle,Wedge
labels=['Frogs','Hogs','Dogs','Logs']
sizes=[15,30,45,10]
explode=(0,0.1,0,0)
fig1,ax1=plt.subplots()
ax1.pie(sizes,explode=explode,labels=labels,autopct='%1.1f%%',shadow=True,startangle=90)
ax1.axis('equal'); # Equal aspect ratio ensures that pie is drawn as a circle.

在这里插入图片描述

# wedge 绘制饼图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Circle,Wedge
fig=plt.figure(figsize=(5,5))
ax1=fig.add_subplot(111)
thetal=0
sizes=[15,30,45,10]
patches=[]
patches+=[
   Wedge((0.5,0.5),.4,0,54),
   Wedge((0.5,0.5),.4,54,162),
   Wedge((0.5,0.5),.4,162,324),
   Wedge((0.5,0.5),.4,324,360),
]
colors=100*np.random.rand(len(patches))
p=PatchCollection(patches,alpha=0.8)
p.set_array(colors)
ax1.add_collection(p);

在这里插入图片描述

3.2.4 collections

collections 类是用来绘制一组对象的集合,collections 有许多不同的子类,如 RegularPolyCollection, CircleCollection, Pathcollection, 分别对应不同的集合子类型. 其中比较常用的就是散点图,它是属于 PathCollection 子类,scatter 方法提供了该类的封装,根据 x 与 y 绘制不同大小或颜色标记的散点图.
其中最主要的参数是前 5 个:

  • x:数据点 x 轴的位置
  • y:数据点 y 轴的位置
  • s:尺寸大小
  • c:可以是单个颜色格式的字符串,也可以是一系列颜色
  • marker: 标记的类型
# 用scatter绘制散点图
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Circle,Wedge
from matplotlib.collections import PatchCollection
x=[0,2,4,6,8,10]
y=[10]*len(x)
s=[20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s,c='r',marker='x');

在这里插入图片描述

3.2.5 images

images 是 matplotlib 中绘制 image 图像的类,其中最常用的 imshow 可以根据数组绘制成图像.
使用 imshow 画图时首先需要传入一个数组,数组对应的是空间内的像素位置和像素点的值,interpolation 参数可以设置不同的差值方法.

 # images
import numpy as np
import pandas as pd
import re
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Circle,Wedge
from matplotlib.collections import PatchCollection
methods=[None,'none','nearest','bilinear','bicubic','spline16',
      'spline36','hanning','hamming','hermite','kaiser','quadric',
      'catrom','gaussian','bessel','mitchell','sinc','lanczos']
grid=np.random.rand(4,4)
fig,axs=plt.subplots(nrows=3,ncols=6,figsize=(9,6),
                  subplot_kw={'xticks':[],'yticks':[]})
for ax,interp_method in zip(axs.flat,methods):
  ax.imshow(grid,interpolation=interp_method,cmap='viridis')
  ax.set_title(str(interp_method))
plt.tight_layout();

在这里插入图片描述

4. 对象容器-Object container

容器会包含一些 primitives,并且容器还有它自身的属性. 比如 Axes Artist,是一种容器,包含了很多 primitives,比如 Line2D,Text;同时,也有自身的属性,比如 xscal,用来控制 X 轴是 linear 还是 log 的.

4.1 Figure 容器

matplotlib.figure.Figure 是 Artist 最顶层的 container 对象容器,包含了图表中的所有元素. 一张图表的背景就是 Figure.patch 的一个矩形 Rectangle.
当向图表添加 Figure.add_subplot() 或者 Figure.add_axes() 元素时,这些都会被添加到 Figure.axes 列表中.

import matplotlib.pyplot as plt
fig=plt.figure()
ax1=fig.add_subplot(211)# 作一幅2*1的图,选择第1个子图
ax2=fig.add_axes([0.1,0.1,0.7,0.3]) #位置参数,四个数分别代表了(left,bottom,width,height)
print(ax1)
print(fig.axes) # fig.axes 中包含了subplot和axes两个实例,刚刚添加的

在这里插入图片描述
由于 Figure 维持了 current axes,因此你不应该手动的从 Figure.axes 列表中添加删除元素,而是要通过 Figure.add_subplot()、Figure.add_axes() 来添加元素,通过 Figure.delaxes() 来删除元素. 但是你可以迭代或者访问Figure.axes 中的 Axes,然后修改这个 Axes 的属性.
比如下面的遍历 axes 里的内容,并且添加网格线:

import matplotlib.pyplot as plt
fig=plt.figure()
ax1=fig.add_subplot(211)
for ax in fig.axes:
  ax.grid(True)

在这里插入图片描述

4.2 Axes 容器

和 Figure 容器类似,Axes 包含了一个 patch 属性,对于笛卡尔坐标系而言,它是一个 Rectangle;对于极坐标而言,它是一个 Circle. 这个 patch 属性决定了绘图区域的形状、背景和边框.

fig=plt.figure()
ax=fig.add_subplot(111)
rect=ax.patch # axes的patch是一个Rectangle实例
rect.set_facecolor('m')

在这里插入图片描述

4.3 Axis 容器

matplotlib.axis.Axis 实例处理 tick line、grid line、tick label以及 axis label 的绘制,它包括坐标轴上的刻度线、刻度 label、坐标网格、坐标轴标题. 通常你可以独立的配置 y 轴的左边刻度以及右边的刻度,也可以独立地配置 x 轴的上边刻度以及下边的刻度.

# 不用print,直接显示结果
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity="all"
fig,ax=plt.subplots()
x=range(0,5)
y=[2,5,7,8,10]
plt.plot(x,y,':',color='c')
axis=ax.xaxis # axis为X轴对象
axis.get_ticklocs() #获取刻度线位置
axis.get_ticklabels() #获取刻度label列表
axis.get_ticklines() #获取刻度线列表
axis.get_data_interval() #获取轴刻度间隔
axis.get_view_interval() #获取轴视角(位置)的间隔

在这里插入图片描述
下面的例子展示了如何调整一些轴和刻度的属性.

fig=plt.figure() #创建一个新图表
rect=fig.patch # 矩形实例并将其设为黄色
rect.set_facecolor('y')
ax1=fig.add_axes([0.1,0.3,0.4,0.4]) #创一个axes对象,从(0.1,0.3)的位置开始,宽和高都为0.4
rect=ax1.patch # ax1的矩形设为品红色
rect.set_facecolor('m')
for label in ax1.xaxis.get_ticklabels():
    # 调用x轴刻度标签实例,是一个text实例
    label.set_color('red')# 颜色
    label.set_rotation(45)#旋转角度
    label.set_fontsize(20) #字体大小
for line in ax1.yaxis.get_ticklines():
    #调用y轴刻度线条实例, 是一个Line2D实例
    line.set_markeredgecolor('green') #颜色
    line.set_markersize(25) #marker大小
    line.set_markeredgewidth(4) #marker粗细

在这里插入图片描述

4.4 Tick 容器

matplotlib.axis.Tick 是从 Figure 到 Axes 到 Axis 到 Tick 中最末端的容器对象. Tick包含了 tick、grid line 实例以及对应的 label. 所有的这些都可以通过Tick的属性获取,常见的tick属性有:

  • Tick.tick1line:Line2D 实例
  • Tick.tick2line:Line2D 实例
  • Tick.gridline:Line2D 实例
  • Tick.label1:Text 实例
  • Tick.label2:Text 实例
    y 轴分为左右两个,因此 tick1 对应左侧的轴;tick2 对应右侧的轴.
    x 轴分为上下两个,因此 tick1 对应下侧的轴;tick2 对应上侧的轴.
    下面的例子展示了,如何将 Y 轴右边轴设为主轴,并将标签设置为美元符号且为绿色:
fig,ax=plt.subplots()
ax.plot(100*np.random.rand(20))
# 设置ticker的显示格式
formatter=matplotlib.ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter)
# 设置ticker的参数,右侧为主轴,颜色为绿色
ax.yaxis.set_tick_params(which='major',labelcolor='green',labelleft=False,labelright=True);

在这里插入图片描述

5. 思考题

5.1 primitives 和 container 的区别和联系是什么,分别用于控制可视化图表中的哪些要素.

答:区别:primitives 是基本元素,代表图形的类型,如曲线-Line2D,矩形-Rectangle,多边形-Polygon,图像-image. container 是容器,会包含一些 primitives,并且容器还有它自身的属性.
联系:primitives 一定是存在 container 中的. 根据数据的类型,我们会选择不同的 primitives 绘图,根据数值的大小,我们也要调整 container, 使图形更美观.

5.2 使用提供的drug数据集,对第一列yyyy和第二列state分组求和,画出下面折线图。PA加粗标黄,其他为灰色。图标题和横纵坐标轴标题,以及线的文本暂不做要求。

import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
path='Drugs.csv'
data=pd.read_csv(path)
fig,ax=plt.subplots()
rect = fig.patch   # 矩形实例并将其设为黄色
rect.set_facecolor('lightgoldenrodyellow')
rect1 = ax.patch   # ax的矩形设为灰色
rect1.set_facecolor('gray')
ax.grid(True) # 添加网格
for i,group in data.groupby('State'):
    data_subgroup=group.groupby(['YYYY'])['DrugReports'].sum()
    df=pd.DataFrame(data_subgroup)
    df['year']=df.index
    if i=='PA':
        ax.plot(df['year'],df['DrugReports'],label=i,color='y',linewidth=5)
    elif i=='KY':
        ax.plot(df['year'],df['DrugReports'],label=i,color='b',linewidth=3)
    elif i=='OH':
        ax.plot(df['year'],df['DrugReports'],label=i,color='g',linewidth=3) 
    elif i=='VA':
         ax.plot(df['year'],df['DrugReports'],label=i,color='m',linewidth=3) 
    else:
        ax.plot(df['year'],df['DrugReports'],label=i,color='k',linewidth=3)
    plt.legend()
plt.xlim(2010,2017)
plt.xlabel('year')
plt.ylabel('DrugReports')
plt.title('Evolution of PA vs other states');

在这里插入图片描述

5.3 分别用一组长方形柱和填充面积的方式模仿画出下图,函数 y = -1 * (x - 2) * (x - 8) +10 在区间[2,9]的积分面积

x=np.linspace(2,9,42)
y=-1*(x-2)*(x-8)+10
x1=np.linspace(0,10,500)
y1=-1*(x1-2)*(x1-8)+10
fig,ax=plt.subplots()
ax.plot(x1,y1,color='m')
ax.bar(x,y,width=0.05)
ax.set_xlim(0)
ax.set_ylim(0);

在这里插入图片描述

x=np.linspace(2,9,100)
y=-1*(x-2)*(x-8)+10
x1=np.linspace(0,10,100)
y1=-1*(x1-2)*(x1-8)+10
fig,ax=plt.subplots()
ax.plot(x1,y1,color='m')
ax.fill_between(x,y)
ax.set_xlim(0)
ax.set_ylim(0);

在这里插入图片描述

6. 补充知识

6.1 legend() 绘制图例

axes 类的 legend() 方法负责绘制画布中的图例,它需要三个参数,如下所示:
在这里插入图片描述

  • labels 是一个字符串序列,用来指定标签的名称
  • loc 是指定图例位置的参数,其参数值可以用字符串或整数来表示
  • handles 参数,它也是一个序列,它包含了所有线型的实例
    下面是 loc 参数的表示方法,分为字符串和整数两种,如下所示:
    在这里插入图片描述

6.2 axes.plot()

这是 axes 类的基本方法,它将一个数组的值与另一个数组的值绘制成线或标记,plot() 方法具有可选格式的字符串参数,用来指定线型、标记颜色、样式以及大小.
颜色代码如下表:

字符颜色
‘b’蓝色
‘g’绿色
‘r’红色
‘c’青色
‘m’品红色
‘y’黄色
‘k’黑色
‘w’白色

标记符号如下表:

标记符号描述
‘.’点标记
‘o’圆圈标记
‘x’'X’标记
‘D’钻石标记
‘H’六角标记
‘s’正方形标记
‘+’加号标记

线型表示字符,如下表:

字符描述
‘-’实线
‘–’虚线
‘-.’点划线
‘:’虚线
‘H’六角标记
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值