布局
#
简介Ave 只支持 grid 的布局方式(web 中 flex 布局也可以基于此封装,不过 grid 其实是更灵活、强大的布局方式),所有控件都需要放在 grid 之中,因此组件部分首先从 grid 开始介绍。
Ave 中 grid 的含义和 web 中的(A Complete Guide to Grid)差不多,但是更加底层,也就是说,web 里的 grid css 也可以基于此实现。
#
例子#
背景色export function App() { return ( <Window> <Grid style={{ backgroundColor: new Vec4(0, 146, 255, 255 * 0.75), }} ></Grid> </Window> );}
在 Ave 中我们使用Vec4
类来表示颜色,其中每个颜色的取值范围都是[0,255]
,然后使用 grid 的backgroundColor
设置背景颜色。
#
APIexport interface IGridComponentProps extends IComponentProps { style?: IGridStyle; ...}
export interface IGridStyle extends IComponentStyle { backgroundColor?: Vec4; ...}
#
添加组件const layout = { columns: '1 1 1', rows: '1 1 1', areas: { center: { row: 1, column: 1 }, },};
const backgroundColor = new Vec4(0, 146, 255, 255 * 0.75);
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor, area: layout.areas.center }} ></Grid> </Grid> </Window> );}
这里我们创建了一个 grid,并设置它为 3 行、3 列,也就是说,现在我们的界面相当于一个 3x3 的网格。然后我们在中间那格添加了另一个设置了背景色的格子,运行后界面如下:
rows
和columns
分别是为 grid 添加行和列,slice
表明这里添加的行、列是成比例的,也就是说,添加的行和列都是 1:1:1,这样可以适应窗口大小变化:
#
APIexport interface IGridStyle extends IComponentStyle { ... layout?: IGridLayout;}
export interface IGridLayout { /** * whitespace sperated sizes, eg. "1 50px 100dpx" * * 1: slice 1 * 50px: unit is px * 100dpx: unit is dpx */ columns?: string; rows?: string; areas?: Record<string, IGridArea>;}
export interface IComponentStyle { area?: IGridArea; ...}
#
练习: grid这个练习的目的是实现类似 web 中的 24 栅格系统,例如 Ant Design Grid 。在 Ave 中怎样实现如下效果呢?
#
练习: offset这个练习的目的是实现 grid 的偏移,例如 Ant Design Grid: Offset 。在 Ave 中怎样实现如下效果呢?
#
边距const layout = { columns: '1 1 1', rows: '1 1 1', areas: { control: { row: 0, column: 0 }, },};
const backgroundColor = new Vec4(0, 146, 255, 255 * 0.75);
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor, area: layout.areas.control, margin: '100dpx 50dpx 0 0', }} ></Grid> </Grid> </Window> );}
在这个例子中,我们设置了蓝色方块的边距,它本身位于窗口的左上角,在设置了左边距和上边距之后,可以发现它不再紧贴窗口边缘:
#
APIexport interface IComponentStyle { ... margin?: string;}
#
练习: gutter这个练习的目的是实现类似 web 中的 grid gutter,例如 Ant Design Grid: Gutter 。在 Ave 中怎样实现如下效果呢?
#
透明度要想实现半透明的效果,有两种方式,一种是调整背景颜色的 alpha 值,另一种是设置opacity
:
const layout = { columns: "1 1 1 1 1", rows: "1 1 1 1 1", areas: { left: { row: 1, column: 1 }, right: { row: 1, column: 3 }, },};
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor: new Vec4(0, 146, 255, 255 * 0.25), area: layout.areas.left }}></Grid> <Grid style={{ backgroundColor: new Vec4(0, 146, 255, 255), area: layout.areas.right, opacity: 0.25 }}></Grid> </Grid> </Window> );}
在这个例子中,我们采取了两种不同的方式,画出了相同效果的半透明蓝色方块。
两种方式的区别如下:
- opacity:设置整体透明度,包括放在里面的控件全部都会半透明
- backgroundColor:就只有 grid 本身的背景部分有影响
#
练习答案#
gridconst colors = { white: new Vec4(255, 255, 255, 255), darkBlue: new Vec4(0, 146, 255, 255), lightBlue: new Vec4(0, 146, 255, 255 * 0.75),};
const layout = { columns: Array.from<number>({ length: 24 }).fill(1).join(" "), rows: [50, 25, 50, 25, 50, 25, 50, 25].map((r) => `${r}dpx`).join(" "), areas: { _24: { row: 0, column: 0, rowSpan: 1, columnSpan: 24 }, _12_1: { row: 2, column: 0, rowSpan: 1, columnSpan: 12 }, _12_2: { row: 2, column: 12, rowSpan: 1, columnSpan: 12 }, _8_1: { row: 4, column: 0, rowSpan: 1, columnSpan: 8 }, _8_2: { row: 4, column: 8, rowSpan: 1, columnSpan: 8 }, _8_3: { row: 4, column: 16, rowSpan: 1, columnSpan: 8 }, _6_1: { row: 6, column: 0, rowSpan: 1, columnSpan: 6 }, _6_2: { row: 6, column: 6, rowSpan: 1, columnSpan: 6 }, _6_3: { row: 6, column: 12, rowSpan: 1, columnSpan: 6 }, _6_4: { row: 6, column: 18, rowSpan: 1, columnSpan: 6 }, },};
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._24 }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._12_1 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._12_2 }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._8_1 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._8_2 }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._8_3 }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._6_1 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._6_2 }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._6_3 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._6_4 }}></Grid> </Grid> </Window> );}
#
offsetconst colors = { darkBlue: new Vec4(0, 146, 255, 255),};
const span1 = 8;const offset_11 = 0;const offset_12 = offset_11 + span1 + 8;
const span2 = 6;const offset_21 = 6;const offset_22 = offset_21 + span2 + 6;
const span3 = 12;const offset_3 = 6;
const layout = { columns: Array.from<number>({ length: 24 }).fill(1).join(" "), rows: `1 50dpx 25dpx 50dpx 25dpx 50dpx 1`, areas: { _11: { row: 1, column: offset_11, rowSpan: 1, columnSpan: span1 }, _12: { row: 1, column: offset_12, rowSpan: 1, columnSpan: span1 }, _21: { row: 3, column: offset_21, rowSpan: 1, columnSpan: span2 }, _22: { row: 3, column: offset_22, rowSpan: 1, columnSpan: span2 }, _3: { row: 5, column: offset_3, rowSpan: 1, columnSpan: span3 }, },};
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._11 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._12 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._21 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._22 }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._3 }}></Grid> </Grid> </Window> );}
#
gutter我们使用边距来实现区块间隔的效果:
const colors = { lightBlue: new Vec4(0, 146, 255, 255 * 0.75), darkBlue: new Vec4(0, 146, 255, 255),};
const gutter = 50;const margin = `${gutter / 2}dpx 0 ${gutter / 2}dpx 0`;
const layout = { columns: Array.from<number>({ length: 24 }).fill(1).join(" "), rows: `1 50dpx 1`, areas: { _1: { row: 1, column: 0, rowSpan: 1, columnSpan: 6 }, _2: { row: 1, column: 6, rowSpan: 1, columnSpan: 6 }, _3: { row: 1, column: 12, rowSpan: 1, columnSpan: 6 }, _4: { row: 1, column: 18, rowSpan: 1, columnSpan: 6 }, },};
export function App() { return ( <Window> <Grid style={{ layout }}> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._1, margin }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._2, margin }}></Grid> <Grid style={{ backgroundColor: colors.lightBlue, area: layout.areas._3, margin }}></Grid> <Grid style={{ backgroundColor: colors.darkBlue, area: layout.areas._4, margin }}></Grid> </Grid> </Window> );}