前端应知应会:flex布局详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端应知应会:flex布局详解相关的知识,希望对你有一定的参考价值。
参考技术A 前端应知应会:flex布局详解flex布局可以说是当下前端开发必须学会的一个基本技能,它在面试中的出场率也很高,有必要专门讲解一下。
flex布局全称flexible box布局模型,是一种比较高效的css3布局方案
通过设置元素的display属性,改成flex属性
来指定对应容器为flex布局。然后它的所有子元素自动成为了容器元素,不脱离文档流的情况下按照flex item的默认布局规则排列。
首先看下容器的属性:
1、flex-direction
决定主轴的方向,
默认值是row即横向从左往右的顺序进行排列。
其他选项值还有row-reverse、column、column-reverse
2、flex-wrap
它决定了如果轴线排列不下去的话,如何进行换行
默认是不进行换行,继续沿着主轴方向放置。
其它选项还有:wrap(换行)、wrap-reverse(换行、但是位置跟wrap相反)
3、flex-flow
它是flex-firection和flex-wrap的简写
4、justify-content
该属性定义了item在主轴上的对齐方式
默认值是:flex-start即顺着主轴方向排列对齐
其他还有flex-end:逆着主轴方向并从最远处往主轴起点排列
center:居中
space-between:两端对齐,项目之间间隔相等
space-around:每个项目两侧留白距离相等
5、align-items
该属性定义了项目在交叉轴上如何对齐
毕竟,每个item的高度不一定完全一样。
它的默认值是stretch:即如果item没有设置高度或者是auto,则会占据整个容器的高度
其他还有flex-start、flex-end、center、baseline
6、align-content
它跟align-items的区别就是,该属性定义的是多跟轴线的对齐方式
该参数有六个可选项:
flex-start、flex-end、center、space-between、space-around、stretch
这里面要记得的是处于不同轴线上的item不会遮挡,即如果某个轴线上有两个不同高度的item,那么下一个轴线的位置会按照上一条轴线上高度最高的item进行计算。
针对item,也有一些属性可以设置
1、order决定了项目的排列顺序,可以通过设置该属性将对应的item往前排列
2、flex-grow,决定了item的放大比例,默认为0不进行放大。
3、flex-shrink,定义了item的缩小比例,默认为1,如果空间不够的话所有轴线上的item将进行同比缩小,如果为0则该item不进行缩小
4、flex-basis,定义item在轴线上占据的宽度,如果没设置的话,就按item自身的宽度进行分配
5、align-self。定义item在轴线纵向的排列方式,可以替换掉对应flex容器的align-items属性,为该item设置专门的对齐方式
下面再举个例子
<!DOCTYPE html>
<html lang="en">
Tkinter编程应知应会(23)-活用Canvas的对象tag
我们继续以围棋小程序为例说明Tkinter中Canvas控件的用法。当控件的内容表示之后,一般也需要根据用户的需要进行更新。本文介绍借助Tkinter提供的对象Tag来实现管理和控制Canvas对象的方法。
首先还是动作的视频:
视频链接
为了方便管理程序中的数据,我们以Canvas为基类构建一个棋盘类:
class GoBoard(Canvas):
def __init__(self, master, size, span):
Canvas.__init__(self, master, height=size * span, width=size * span)
self.size = size
self.span = span
# create font
self.font1 = Font(family=Times, size=12)
self.__draw_board()
self.__create_cursor()
self.step = 0
这个类一个有4个数据成员,其中棋盘大小(路数)、线间距这两个成员由用户通过参数指定以确定棋盘的大小;另外两个font1和step用于管理数字的字体和当前棋子的步数。
除此之外,初始化函数还调用__draw_board方法描画棋盘:
def __draw_board(self):
# crate pan
self.create_rectangle(self.span / 2,
self.span / 2,
self.span * self.size - self.span / 2,
self.span * self.size - self.span / 2,
fill=#eeaa40)
# draw horizental lines
for r in range(0, self.size):
self.create_line(self.span / 2,
self.span / 2 + r * self.span,
self.span * self.size - self.span / 2,
self.span / 2 + r * self.span)
# draw vertical lines
for c in range(0, self.size):
self.create_line(self.span / 2 + c * self.span, self.span / 2,
self.span / 2 + c * self.span, self.span * self.size - self.span / 2)
这部分代码和前一篇文章中描画棋盘的代码相同。接着调用__create_cursor函数构建光标对象:
def __create_cursor(self):
# add go shape
side = 5
self.create_rectangle(self.__cursor_rect(int(self.size / 2), int(self.size / 2)),
tag=cursor,
fill=white)
__create_cursor方法主要是构建了一个tag为‘cursor’的矩形,接下来所有的光标操作都是通过这个‘cursor’来获得光标对象。
add_go用于在光标位置增加一个棋子,颜色由当前步数step决定。
def add_go(self):
row, col = self.get_cursor()
tag = self.__oval_tag(row, col)
if self.find_withtag(tag):
return
r = 11
if self.step % 2 == 0:
go_color = black
else:
go_color = white
# add go shape
self.create_oval(self.__oval_rect(row, col),
fill=go_color,
tags=[go,
go_oval,
tag,
step + str(self.step)])
# move cursor to upmost
self.tag_raise(cursor, go)
self.step += 1
需要注意的是:在构建椭圆对象的时候,tags参数一个指定了四个tag值,第三个tag包含位置信息,而第四个tag包含步数信息。指定其中任何一个tag都可以选中这个对象。构建椭圆对象之后,通过tag_raise将光标对象移动到所有tag中包含‘go’的对象(棋子和数字)之上。
设定数字函数set_number的功能和set_go类似:
def set_number(self, row, col, number):
if number > 0:
tag = self.__oval_tag(row, col)
if self.find_withtag(tag):
if self.itemcget(tag, fill) == white:
font_color = black
else:
font_color = white
self.create_text(self.span / 2 + col * self.span,
self.span / 2 + row * self.span,
font=self.font1, fill=font_color,
text=str(number),
tags=[go, go_number, self.__font_tag(row, col)])
# move cursor to upmost
self.tag_raise(cursor, go)
代码中同样包含移动光标的处理。
reset_numbers首先获得当前位置棋子椭圆对象的位置tag,然后通过gettags方法获得这个对象的所有tag。参照椭圆生成部分的代码可以知道,第四个tag就是步数tag。
def reset_numbers(self):
row, col = self.get_cursor()
self.delete(go_number)
tags = self.gettags(self.__oval_tag(row, col))
number = 1
if tags:
start_step = int(tags[3][4:])
for s in range(start_step, self.step):
tag = step.format(s)
if self.find_withtag(tag):
row, col = self.to_rc(self.coords(tag))
self.set_number(row, col, number)
number += 1
获得选中棋子的步数tag之后,循环生成后续的步数tag并通过find_withtag确认对应棋子存在之后再逐个生成数字对象就实现了为棋子标号的功能。
del_go首先使用光标的当前位置分别生成椭圆和数字的位置tag。如果这两个tag对应对象存在,则删除它们。
def del_go(self):
row, col = self.get_cursor()
tag = self.__oval_tag(row, col)
if self.find_withtag(tag):
self.delete(tag)
tag = self.__font_tag(row, col)
if self.find_withtag(tag):
self.delete(tag)
move_curosr方法获得光标的当前位置之后根据输入参数对这个对象的坐标进行调整:
def move_cursor(self, offset_r, offset_c):
row, col = self.get_cursor()
row += offset_r
col += offset_c
if 0 < col < self.size and 0 < row < self.size:
self.move(cursor, offset_c * self.span, offset_r * self.span)
而光标的当前位置又是通过光标对象的坐标计算而来的:
def get_cursor(self):
coords = self.coords(cursor)
x = (coords[0] + coords[2]) / 2
y = (coords[1] + coords[3]) / 2
return int((y - self.span / 2) / self.span), int((x - self.span / 2) / self.span)
棋盘类完成之后,用起来就简单了:
# create the main window
root = Tk()
go_board = GoBoard(root, 13, 40)
go_board.grid(row = 0, column = 0)
root.bind_all(<Key-Up>, lambda event:go_board.move_cursor(-1, 0))
root.bind_all(<Key-Down>, lambda event:go_board.move_cursor(1, 0))
root.bind_all(<Key-Left>, lambda event:go_board.move_cursor(0, -1))
root.bind_all(<Key-Right>, lambda event:go_board.move_cursor(0, 1))
root.bind_all(<Key-Insert>, lambda event:go_board.add_go())
root.bind_all(<Key-Delete>, lambda event:go_board.del_go())
root.bind_all(<Key-Home>, lambda event:go_board.reset_numbers())
root.mainloop()
需要强调的是:
- 棋盘类GoBoard中并没有准备管理Canvas对象的数据结构,而是通过规则生成对象tag并获取Canvas管理的对象。
- 巧妙设计对象的tag,就可以用非常小的代价实现很多功能。
完整代码可以从以下地址下载:
https://github.com/xueweiguo/TkinterPrimer/blob/master/Sample/23%20Go.py
觉得本文有帮助?请分享给更多人。
阅读更多更新文章,请关注微信公众号【面向对象思考】
以上是关于前端应知应会:flex布局详解的主要内容,如果未能解决你的问题,请参考以下文章