构建场景布局
Scenes 支持两种布局类型:flex 布局和 grid 布局。在本指南中,您将学习如何使用和配置 SceneFlexLayout
和 SceneGridLayout
。
Flexbox 布局
SceneFlexLayout
允许您使用浏览器 CSS flexbox 布局构建灵活的场景。这使您可以定义非常动态的布局,其中面板的宽度和高度可以适应可用空间。
步骤 1. 创建场景
通过创建一个 body 配置为 SceneFlexLayout
的场景,开始使用 flexbox 布局
const scene = new EmbeddedScene({
body: new SceneFlexLayout({}),
});
步骤 2. 配置 flexbox 布局
SceneFlexLayout
允许 flexbox 行为配置。您可以配置以下属性
direction
- 配置 flexbox 布局的主轴。布局中放置的子元素将遵循其方向。wrap
- 配置布局子元素的行为。默认情况下,子元素尝试适应一行。
默认情况下,SceneFlexLayout
使用 row
方向。要创建列布局,请使用以下代码
const scene = new EmbeddedScene({
body: new SceneFlexLayout({
direction: 'column',
}),
});
步骤 3. 添加布局子元素
SceneFlexLayout
具有 children
属性。它接受 SceneFlexItem
或 SceneFlexLayout
对象的数组。创建一个场景,其中包含两个大小相等的列式布局项
const scene = new EmbeddedScene({
body: new SceneFlexLayout({
direction: 'column',
children: [new SceneFlexItem({ minHeight: 200 }), new SceneFlexItem({ minHeight: 300 })],
}),
});
SceneFlexLayout
和 SceneFlexItem
对象类型都接受以下配置选项,这些选项允许大小约束和行为
flexGrow?: CSSProperties['flexGrow'];
alignSelf?: CSSProperties['alignSelf'];
width?: CSSProperties['width'];
height?: CSSProperties['height'];
minWidth?: CSSProperties['minWidth'];
minHeight?: CSSProperties['minHeight'];
maxWidth?: CSSProperties['maxWidth'];
maxHeight?: CSSProperties['maxHeight'];
xSizing?: 'fill' | 'content';
ySizing?: 'fill' | 'content';
// For sizing constaints on smaller screens
md?: SceneFlexItemPlacement;
我们强烈建议在所有使用 column
方向的布局子元素上设置 minHeight
。这确保它们在较小的屏幕上不会过度压缩。如果在 SceneFlexLayout
对象上设置了 minHeight
或 height
,则无需在每个子元素上设置,因为它们将继承这些约束。
步骤 4. 将面板添加到 flex 布局项
前面的示例为您的场景设置了一个布局。要可视化数据,请配置 SceneQueryRunner
并将其添加到您的场景中
const queryRunner = new SceneQueryRunner({
$timeRange: new SceneTimeRange()
datasource: {
type: 'prometheus',
uid: '<PROVIDE_GRAFANA_DS_UID>',
},
queries: [
{
refId: 'A',
expr: 'rate(prometheus_http_requests_total{}[5m])',
},
],
});
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneFlexLayout({
direction: 'column',
children: [new SceneFlexItem({}), new SceneFlexItem({})],
}),
});
接下来,将 VizPanel
对象添加为布局项的 body
const queryRunner = new SceneQueryRunner({
datasource: {
type: 'prometheus',
uid: '<PROVIDE_GRAFANA_DS_UID>',
},
queries: [
{
refId: 'A',
expr: 'rate(prometheus_http_requests_total{}[5m])',
},
],
});
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneFlexLayout({
direction: 'column',
children: [
new SceneFlexItem({
body: PanelBuilders.timeseries().setTitle('Time series').build(),
}),
new SceneFlexItem({
body: PanelBuilders.table().setTitle('Table').build(),
}),
],
}),
});
这将渲染两个面板,一个时间序列面板和一个表格面板。
对于包含 VizPanel
对象的 SceneFlexItems
,建议您设置 minHeight
或 minWidth
约束,以使面板不会因屏幕空间有限而过度压缩。
响应式 flex 布局
默认情况下,SceneFlexLayout
对较小的屏幕具有一些响应式行为
SceneFlexLayout
方向从row
更改为column
。SceneFlexLayout
maxWidth
、maxHeight
、height
或width
约束被移除。SceneFlexLayout
和SceneFlexItem
使用父布局上设置的minHeight
或height
(除非直接在其上指定)。这是为了强制在方向为row
的SceneFlexLayout
上设置的height
或minHeight
约束也应用于其子元素,以便在触发将方向更改为column
的响应式媒体查询时,这些约束继续作用于子元素。
这些行为针对与 Grafana 主题的 breakpoints.down('md')
媒体查询匹配的屏幕触发。
您可以使用 SceneFlexLayout
和 SceneFlexItem
上都存在的 md
属性来覆盖这些行为并设置自定义方向和大小约束。例如
new SceneFlexLayout({
direction: 'row',
minHeight: 200,
md: {
minHeight: 100,
direction: 'row',
},
children: [getStatPanel({}), getStatPanel({})],
}),
在前面的示例中,我们使用 md
属性来覆盖将行布局更改为列布局的默认响应式行为。我们还应用了更严格的 minHeight
约束。
CSS grid 布局
作为 SceneFlexLayout
的替代方案,SceneCSSGridLayout
可用于将场景项包裹在 CSS Grid 中。
const scene = new EmbeddedScene({
body: new SceneCSSGridLayout({
templateColumns: `repeat(auto-fit, minmax(400px, 1fr))`,
children: [
PanelBuilders.timeseries().setTitle('Graph 1').build(),
PanelBuilders.timeseries().setTitle('Graph 2').build(),
],
}),
});
SceneCSSGridLayout
接受与 SceneFlexLayout
相同的 children
,并具有以下属性用于应用 CSS grid 样式
autoRows?: CSSProperties['gridAutoRows'];
templateRows?: CSSProperties['gridTemplateRows'];
templateColumns: CSSProperties['gridTemplateColumns'];
/** In Grafana design system grid units (8px) */
rowGap: number;
/** In Grafana design system grid units (8px) */
columnGap: number;
justifyItems?: CSSProperties['justifyItems'];
alignItems?: CSSProperties['alignItems'];
justifyContent?: CSSProperties['justifyContent'];
// For sizing constaints on smaller screens
md?: SceneCSSGridLayoutState;
使用 CSS Grid,可以轻松构建动态的面板网格,其中面板大小约束可以在网格本身上指定,而不是在每个面板上指定。对于构建大小相等的面板网格非常有用。
下面的网格布局配置为使子元素具有 400px 的最小尺寸,如果还有更多可用空间,则将其均分。高度使用 autoRows 设置。此配置将启用大小相等的面板的非常响应式的布局。
const scene = new EmbeddedScene({
body: new SceneCSSGridLayout({
templateColumns: `repeat(auto-fit, minmax(400px, 1fr))`,
autoRows: '150px',
rowGap: 2,
columnGap: 2,
children: [
new SceneCSSGridItem({
body: PanelBuilders.timeseries().setTitle('Time series').build(),
}),
new SceneCSSGridItem({
body: PanelBuilders.table().setTitle('Table').build(),
}),
new SceneCSSGridItem({
body: PanelBuilders.timeseries().setTitle('Time series').build(),
}),
new SceneCSSGridItem({
body: PanelBuilders.table().setTitle('Table').build(),
}),
],
}),
});
每个子元素周围的 SceneCSSGridItem 包装器是可选的。
Grid 布局
SceneGridLayout
允许您将场景构建为可以拖动和移动的元素网格。这是 Grafana 核心仪表板体验使用的默认布局。除非您需要用户能够移动面板,否则不建议将其用于场景应用插件。
步骤 1. 创建场景
通过创建一个 body 配置为 SceneGridLayout
的场景,开始使用 grid 布局
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneGridLayout({}),
});
步骤 2. 配置 grid 布局
SceneGridLayout
允许 grid 行为配置。提供的网格有 24 列。
您可以配置以下属性
isDraggable
- 配置是否可以移动网格项。isLazy
- 配置是否应在网格项位于视口之外时对其进行初始化。
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneGridLayout({
isDraggable: false,
isLazy: true,
}),
});
步骤 3. 添加布局子元素
SceneGridLayout
具有 children
属性。它接受 SceneGridItem
或 SceneGridRow
对象的数组。创建一个场景,其中包含两个行式网格项
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneGridLayout({
children: [
new SceneGridItem({
x: 0,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
}),
new SceneGridItem({
x: 12,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
}),
],
}),
});
SceneGridItem
接受以下配置选项,这些选项以 24 列网格单位表示
x?: number;
y?: number;
width?: number;
height?: number;
步骤 4. 将面板添加到 grid 布局项
将 VizPanel
添加到 SceneGridItem
以显示可视化数据
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneGridLayout({
children: [
new SceneGridItem({
x: 0,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
body: PanelBuilders.timeseries().setTitle('Time series').build(),
}),
new SceneGridItem({
x: 12,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
body: PanelBuilders.table().setTitle('Table').build(),
}),
],
}),
});
步骤 5. 添加网格行
网格行是一种布局项,它将其他 SceneGridItems
分组到一个可折叠的行中。使用 SceneGridRow
向场景添加行
在 SceneGridRow
中,x 和 y 坐标相对于行。
const row = new SceneGridRow({
x: 0,
y: 0,
children: [
new SceneGridItem({
x: 0,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
body: PanelBuilders.timeseries().setTitle('Time series').build(),
}),
new SceneGridItem({
x: 12,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: false,
body: PanelBuilders.table().setTitle('Table').build(),
}),
],
});
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneGridLayout({
children: [row],
}),
});
拆分布局
SplitLayout
允许您将场景构建为独立的、可调整大小的窗格的组合,这些窗格可以是垂直或水平方向的。
步骤 1. 创建场景
通过创建一个 body 配置为 SplitLayout
的场景,开始使用 split 布局
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SplitLayout({}),
});
步骤 2. 配置 split 布局
SplitLayout
允许几个配置选项
direction
- 配置窗格是按行还是按列方向排列。primary
- 第一个窗格。secondary
- 第二个窗格
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SplitLayout({
direction: 'column',
}),
});
步骤 3. 提供 primary 和 secondary 对象
primary
和 secondary
都接受 SceneFlexItemLike
对象。
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SplitLayout({
direction: 'column',
primary: PanelBuilders.timeseries().setTitle('Primary panel').build(),
secondary: PanelBuilders.table().setTitle('Secondary panel').build(),
}),
});