# 布局和视图
页面整体布局是一个产品最外层的框架结构,往往会包含导航、页脚、侧边栏、通知栏以及内容等。在页面之中,也有很多区块的布局结构。在真实项目中,页面布局通常统领整个应用的界面,有非常重要的作用。
# 基础布局和视图
# 基础布局
我们抽离了使用过程中一些常用的布局,都放在 layouts 目录中,分别为:
通用布局 CommonLayout:MapGIS-Pan-Spatial-Map/src/layouts/UserLayout.vue
仅包含内容区和页脚的简单布局,项目中常用于注册、登录或展示页面
![通用布局](/mapgis-pan-spatial-map-docs/images/common-layout.png)
# 基础视图
除了基本布局外,通常有很多页面的结构是相似的。因此,我们把这部分结构抽离为视图组件。
一个视图组件通常包含一个基本布局组件、视图公共区块、路由视图内容区、页脚等,常常结合路由配置使用。它们被放入了 views 目录中,即 MapGIS-Pan-Spatial-Map/src/views/。
# 如何使用
通常我们会把视图组件和路由配置结合一起使用,我们把配置信息抽离在路由配置文件中。
当然,如果这满足不了您的需求,您也可以自定义一些视图组件,或者直接在页面组件中使用布局。
# 专属布局
# 经典版主题布局
经典版主题布局 MpPanSpatialMapClassicTheme,包含了头部导航条,左侧导航条、左侧展示区域、工具条、底部展示区域和内容区。
<template>
<mapgis-ui-layout class="pan-spatial-map-wrapper">
<!-- 头部导航条 -->
<component
:is="headerContentComponent"
ref="headerContent"
v-bind="parseContentProps('header')"
/>
<mapgis-ui-layout ref="bodyContent">
<!-- 左侧导航条 -->
<component
:is="leftContentComponent"
ref="leftContent"
v-bind="parseContentProps('left')"
/>
<!-- 左侧展示区域 -->
<mp-pan-spatial-map-side-panel
v-if="maxSidePanelWidth && mapInitialized"
v-bind="left.panel"
:widgets="left.widgets"
:widgetStructure="left.widgetStructure"
:max-width="maxSidePanelWidth"
@update-widget-state="onUpdateWidgetState('left', $event)"
/>
<mapgis-ui-layout class="main-wrapper">
<mapgis-ui-layout-content class="content-wrapper">
<!-- 工具条 -->
<component
:is="toolbarContentComponent"
ref="toolbarContent"
v-bind="parseContentProps('toolbar')"
/>
<!-- 内容区 -->
<slot v-if="mapInitialized" name="map" />
</mapgis-ui-layout-content>
<!-- 底部展示区域 -->
<component
:is="footerContentComponent"
v-bind="parseContentProps('footer')"
:max-view-height="maxFooterHeight"
/>
</mapgis-ui-layout>
<mp-map-container
v-if="configInitialized"
class="map-wrapper"
:dataFlowList="dataFlowList"
:cesium-lib-path="publicPath + 'cesium/Cesium.js'"
:cesium-plugin-path="publicPath + 'cesium/webclient-cesium-plugin.js'"
:map-options="mapOptions"
:popupShowType="popupShowType"
:dataStoreIp="dataStoreIp"
:dataStorePort="dataStorePort"
:getProjectorStatus="getProjectorStatus"
:minimumLevel="minimumLevel"
:maximumLevel="maximumLevel"
@project-screen="handleProjectScreen"
/>
</mapgis-ui-layout>
</mapgis-ui-layout>
</template>
![经典版主题布局](/mapgis-pan-spatial-map-docs/images/classic-layout.png)
经典版主题布局由 MpApploader 根据 app.json 生成,指向的主题清单themes/pan-spatial-map-classic-theme/manifest.json
共包含了 4 个内容区域。
"contents": [
{
"name": "header",
"description": "头部导航条",
"component": "MpPanSpatialMapClassicHeader"
},
{
"name": "toolbar",
"description": "工具条",
"component": "MpPanSpatialMapClassicToolbar",
"maxWidgets": 6,
"subNodeMaxDepth": 2
},
{
"name": "left",
"description": "左侧导航条",
"component": "MpPanSpatialMapClassicLeft"
},
{
"name": "footer",
"description": "底部展示区域",
"component": "MpPanSpatialMapFooter"
}
]
其中有 3 个区域支持微件配置:
"contentWidgets": {
"groups": [
{
"content": "header",
"widgets": []
},
{
"content": "left",
"widgets": [],
"panel": {
"relativeTo": "content"
}
},
{
"content": "toolbar",
"widgets": []
}
]
}
- mapWidgets:地图 widgets,都是相对于 map 的,可以定义占位空间,对于 off-panel,设计器可以设置 visible,可以进行拖动(只要 dragble 不为 false)。
- contentWidgets:内容 widgets,用来供页面导航使用,加入的 widget 必须以 group 的形式存在,添加到布局的 content 中。
{
// 可选,应用logo,默认值为images/app-logo.svg
"logo": "images/logo.png",
// 可选,应用标题
"title": "MapGIS全空间一张图",
// 可选,应用副标题
"subtitle": "",
//可选. 应用包含的外链列表
"links": [
{
"url": "http://www.smaryun.com",
"label": "MapGIS Cloud"
}
],
// 必须,主题
"theme": {
// 主题名称,指向themes/name主题
"name": "pan-spatial-map-classic-theme",
// 可选,系统主题风格,如果不存在,则使用customStyle
"style": "night",
// 可选,自定义主题风格,必须跟style至少存在一个
"customStyle": {
"color": "#1890ff",
"theme": "night"
}
},
// 地图widgets
"mapWidgets": {
// widget
"widgets": [
{
// widgetId,builder时动态生成
"id": "widget_9b4aaff5-c4b1-4402-be60-d2cc4eca0476",
// widget标识
"uri": "widgets/map-mode-picker",
// 可选,widget位置,如果没有设置,默认是相对于map的left=0,top=0
"position": {
// 可选,widget位置锚点,默认值为top-left,可以设置为top-right、top-left、bottom-right、bottom-left、top-center、center-right、bottom-center、center-left、center-center
"anchor": "bottom-left",
// 可选,widget水平和垂直方向偏移,默认值为0
"horizontalOffset": 10,
"verticalOffset": 36
}
},
{
"id": "widget_9832ede9-8e67-415e-8964-d97a363e247f",
"uri": "widgets/zoom",
"position": {
"anchor": "bottom-left",
"horizontalOffset": 10,
"verticalOffset": 78
}
}
{
"position": {
"anchor": "top-left",
"horizontalOffset": 10,
"verticalOffset": 52
},
"placeholder": true
}
],
// 可选,地图上所有inPanel为true的widget所展示的面板,显示位置根据widget自动计算弹出,
// 如果不指定,使用系统默认面板MpMapWidgetPanel
"panel": {
// 面板组件名
"component": "MpMapWidgetPanel",
// 可选,显示模式(single/multi),只有relativeTo为map才有效
// 如果没有指定,则默认为single
"mode": "multi"
}
},
// 内容widgets,由布局的内容区域去使用
"contentWidgets": {
// 内容widgets分为多组,每组对应布局中的一个内容区域(主题manifest.json中的contents)
"groups": [
{
// 组名
"content": "header",
"widgets": [],
"widgetStructure": [],
"panel": {
"position": {
"anchor": "top-right",
"horizontalOffset": 10,
"verticalOffset": 10,
"bottom": 10
}
}
},
{
"content": "left",
// 该内容区域包含的widget集合,可以有多个,因为内容区域中的widget只要inPanel为true,就会放到面板中显示,所以不需要指定position
"widgets": [
{
"id": "widget_48a29d0c-ece4-474e-9259-65b5095757e7",
"uri": "widgets/data-catalog",
"config": "configs/data-catalog/config.json"
},
{
"id": "widget_3e8667b6-71ce-492d-be6f-f8193360b4d2",
"uri": "widgets/layer-list"
}
],
"widgetStructure": [],
"panel": {
// 可选,指定弹出面板相对的元素(map/content)
// 如果没有指定,则默认相对于map
"relativeTo": "content"
}
},
{
"content": "toolbar",
"widgets": [
{
"id": "widget_878815b5-3f97-4026-80a9-46e683c053b1",
"uri": "widgets/measurement"
},
{
"id": "widget_8c5d3d2e-b05b-49be-a109-8e3254a9e428",
"uri": "widgets/add-data",
"config": "configs/add-data/config.json"
},
{
"id": "widget_bfe8faf2-4568-466b-98fd-877e856ccbd9",
"uri": "widgets/retrospect"
},
{
"id": "widget_59be6878-b0c1-415b-bab4-f6bd4248e980",
"uri": "widgets/swipe"
},
{
"id": "widget_98e8c014-e015-400e-8f57-b4a22606c91a",
"uri": "widgets/func-warehouse",
"config": "configs/func-warehouse/config.json"
},
{
"id": "widget_72e58aa3-ef5a-4f9c-892d-d7c0cac782a3",
"uri": "widgets/topology-analysis"
},
{
"id": "widget_af11a3c9-c5cc-464e-acf6-d3fb24560c71",
"uri": "widgets/network-analysis"
},
{
"id": "widget_ebc4e6c1-e17a-8c5a-6d65-d7f35f1f88c4",
"uri": "widgets/scene-setting"
},
{
"id": "widget_fa2ea6fd-c838-46bc-9b89-de82fc102e67",
"uri": "widgets/scene-roaming",
"config": "configs/scene-roaming/config.json"
},
{
"id": "widget_cad68d22-8084-4616-96f3-a9152cf23444",
"uri": "widgets/visual-analysis"
}
],
"widgetStructure": [
{
"id": "widget_878815b5-3f97-4026-80a9-46e683c053b1"
}
{
"id": "folder_86c9b153-0d1e-4617-2bc3-09fbae5e6715",
"type": "folder",
"label": "对比分析",
"children": [
{
"id": "widget_8c5d3d2e-b05b-49be-a109-8e3254a9e428"
},
{
"id": "widget_bfe8faf2-4568-466b-98fd-877e856ccbd9"
},
{
"id": "widget_59be6878-b0c1-415b-bab4-f6bd4248e980"
}
]
},
{
"id": "folder_42a60a3c-ba22-03b3-de91-5c7932e45612",
"type": "folder",
"label": "矢量分析",
"children": [
{
"id": "widget_98e8c014-e015-400e-8f57-b4a22606c91a"
},
{
"id": "widget_72e58aa3-ef5a-4f9c-892d-d7c0cac782a3"
},
{
"id": "widget_af11a3c9-c5cc-464e-acf6-d3fb24560c71"
}
]
},
{
"id": "folder_566d9d41-b02d-e9a6-ab99-28ce895c91de",
"type": "folder",
"label": "三维分析",
"children": [
{
"id": "widget_ebc4e6c1-e17a-8c5a-6d65-d7f35f1f88c4"
},
{
"id": "widget_fa2ea6fd-c838-46bc-9b89-de82fc102e67"
},
{
"id": "widget_cad68d22-8084-4616-96f3-a9152cf23444"
}
]
}
],
// 可选,该内容区域widgets中所有inPanel为true的widget所展示的面板
// 如果没有指定,则使用系统默认模板MpContentWidgetPanel
"panel": {
// 面板组件名
"component": "MpContentWidgetPanel",
// 可选,指定弹出面板相对的元素(map/content)
// 如果没有指定,则默认相对于map
"relativeTo": "content",
// 可选,显示模式(single/multi),只有relativeTo为map才有效
// 如果没有指定,则默认为single
"mode": "multi",
// 可选,面板弹出位置,只有relativeTo为map才有效
"position": {
// 可选,面板位置锚点,默认值为top-right,可以设置为top-right、top-left、bottom-right、bottom-left、top-center、center-right、bottom-center、center-left、center-center
"anchor": "top-right",
// 可选,面板水平和垂直方向偏移,默认值为0(单位:像素)
"horizontalOffset": 10,
"verticalOffset": 52,
// 可选,相对于主视图顶的距离,默认值为0(单位:像素),当height没有指定,且anchor为'bottom-left', 'bottom-right', 'bottom-center'时生效
"top": 0,
// 可选,相对于主视图底的距离,默认值为0(单位:像素),当height没有指定,且anchor为'top-left', 'top-right', 'top-center'时生效
"bottom": 0
},
// 可选,面板样式
"styles": {
// 可选,是否展开,当position.anchor为top-center、bottom-center、center-left、center-right、center-center时生效
"expand": false,
// 可选,面板内容宽度,如果没有传,可设置最小宽度和最大宽度并由内容自适应
"width": 240,
// 可选,面板内容高度,如果没有传,查看是否有top或bottom,如果有,将根据距离进行自适应,如果也没有,可设置最小高度和最大高度并由内容自适应
"height": 480,
// 可选,面板默认最小内容宽度,默认值240(单位:像素)
"minWidth": 240,
// 可选,面板默认最大内容宽度,默认值为100%,只支持像素单位设置
"maxWidth": 240,
// 可选,面板默认最小内容宽度,默认值48(单位:像素)
"minHeight": 48,
// 可选,面板默认最大内容宽度,默认值为100%,只支持像素单位设置
"maxHeight": 48
}
}
]
}
}
# 其它布局组件
除了内建布局以外,在一些页面中需要进行布局,还可以使用 Ant Design Vue 提供的布局组件:Grid 和 Layout。
# Grid 组件
栅格布局是网页中最常用的布局,其特点就是按照一定比例划分页面,能够随着屏幕的变化依旧保持比例,从而具有弹性布局的特点。
而 Ant Design Vue 的栅格组件提供的功能更为强大,能够设置间距、具有支持响应式的比例设置,以及支持 flex 模式,基本上涵盖了大部分的布局场景,详情查看:Grid (opens new window)。
# Layout 组件
如果您需要辅助页面框架级别的布局设计,那么 Layout 则是您最佳的选择,它抽象了大部分框架布局结构,使得只需要填空就可以开发规范专业的页面整体布局,详情查看:Layout (opens new window)。
# 根据不同场景区分抽离布局组件
在大部分场景下,我们需要基于上面两个组件封装一些适用于当下具体业务的组件,包含了通用的导航、侧边栏、顶部通知、页面标题等元素。
通常,我们会把抽象出来的布局组件,放到 layouts 文件夹中方便管理。需要注意的是,这些布局组件和我们平时使用的其它组件并没有什么不同,只不过功能性上是为了处理布局问题而单独归类。