add
This commit is contained in:
BIN
src/assets/image/add.png
Normal file
BIN
src/assets/image/add.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/assets/image/avoidP.png
Normal file
BIN
src/assets/image/avoidP.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/assets/image/end.png
Normal file
BIN
src/assets/image/end.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/image/start.png
Normal file
BIN
src/assets/image/start.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/assets/image/updown.png
Normal file
BIN
src/assets/image/updown.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 629 B |
@ -1,34 +1,663 @@
|
||||
<template>
|
||||
<div id="home"></div>
|
||||
<div>
|
||||
<div class="home-header">
|
||||
<img @click="drawStartPoint" src="@/assets/image/start.png" />
|
||||
<img @click="drawEndPoint" src="@/assets/image/end.png" />
|
||||
<img @click="drawViaPoint" src="@/assets/image/add.png" />
|
||||
<img @click="drawAvoidPoint" src="@/assets/image/avoidP.png" />
|
||||
<img @click="drawAvoidArea" src="@/assets/image/updown.png" />
|
||||
<div @click="calculateShortestPath" class="sure">确定</div>
|
||||
<!-- <div class="control-panel">
|
||||
<button @click="drawStartPoint">绘制起点</button>
|
||||
<button @click="drawEndPoint">绘制终点</button>
|
||||
<button @click="drawViaPoint">绘制途径点</button>
|
||||
<button @click="drawAvoidPoint">绘制避让点</button>
|
||||
<button @click="drawAvoidArea">绘制避让区域</button>
|
||||
<button @click="calculateShortestPath">计算最短路径</button>
|
||||
<button @click="clear">清除所有</button>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="home">
|
||||
<div class="main-container">
|
||||
<div class="control-panel">
|
||||
<div class="title">参数</div>
|
||||
<el-form
|
||||
@submit.native.prevent="calculateShortestPath"
|
||||
label-width="80px"
|
||||
label-position="left"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item label="起点">
|
||||
<el-input v-model="form.startPoint"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="终点">
|
||||
<el-input v-model="form.endPoint"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="途径点">
|
||||
<el-input v-model="form.viaPoints" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="避让点">
|
||||
<el-input v-model="form.avoidPoints" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="避让区域">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="form.avoidAreas"
|
||||
:rows="4"
|
||||
placeholder=""
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item>
|
||||
<el-button type="primary" @click="calculateShortestPath">计算最短路径</el-button>
|
||||
<el-button @click="clear">清除所有</el-button>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<div class="importJson">导入json文件</div>
|
||||
</div>
|
||||
<div class="control-panel">
|
||||
<div class="title">机动属性</div>
|
||||
<el-form
|
||||
@submit.native.prevent="calculateShortestPath"
|
||||
label-width="80px"
|
||||
label-position="left"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item label="起点">
|
||||
<el-input v-model="form.startPoint"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="终点">
|
||||
<el-input v-model="form.endPoint"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="途径点">
|
||||
<el-input v-model="form.viaPoints" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="避让点">
|
||||
<el-input v-model="form.avoidPoints" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="避让区域">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="form.avoidAreas"
|
||||
:rows="4"
|
||||
placeholder=""
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item>
|
||||
<el-button type="primary" @click="calculateShortestPath">计算最短路径</el-button>
|
||||
<el-button @click="clear">清除所有</el-button>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<div class="importJson">导入json文件</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div id="map"></div> -->
|
||||
<div id="mapbox"></div>
|
||||
<div class="main-container">
|
||||
<div class="control-panel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Header from "./header/index.vue";
|
||||
import Header from './header/index.vue'
|
||||
export default {
|
||||
name: "",
|
||||
name: '',
|
||||
components: {
|
||||
Header,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
form: {},
|
||||
viewer: null,
|
||||
graphicLayer: null,
|
||||
polygonZAM: null,
|
||||
pointQD: null,
|
||||
pointZD: null,
|
||||
shortestPathLayer: null,
|
||||
roadNetworkLayer: null,
|
||||
roadNetworkGeoJSON: null,
|
||||
mapOptions: null,
|
||||
viaPoints: [], // 途径点
|
||||
avoidPoints: [], // 避让点
|
||||
avoidAreas: [], // 避让区域
|
||||
roadNetworkGeoJSONBuild: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.receiveBUS();
|
||||
async mounted() {
|
||||
await this.getMapOption()
|
||||
this.initMap()
|
||||
},
|
||||
|
||||
methods: {
|
||||
receiveBUS() {
|
||||
this.$bus.$on("setActiveIndex", (val) => {
|
||||
console.log("val===>", val);
|
||||
});
|
||||
async getMapOption() {
|
||||
await fetch('./config/map.json')
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then((data) => {
|
||||
this.mapOptions = data.map3d
|
||||
})
|
||||
.catch((error) => {})
|
||||
},
|
||||
async initMap() {
|
||||
this.viewer = new window.mars3d.Map('map', this.mapOptions || {})
|
||||
this.graphicLayer = new window.mars3d.layer.GraphicLayer()
|
||||
this.viewer.addLayer(this.graphicLayer)
|
||||
|
||||
this.shortestPathLayer = new window.mars3d.layer.GraphicLayer()
|
||||
this.viewer.addLayer(this.shortestPathLayer)
|
||||
this.loadShapefile()
|
||||
// 添加地图点击事件监听,用于结束绘制
|
||||
this.viewer.on(mars3d.EventType.dblClick, (event) => {
|
||||
// 如果正在绘制,点击地图可以结束绘制(除了绘制点)
|
||||
this.graphicLayer.stopDraw()
|
||||
})
|
||||
},
|
||||
clear() {
|
||||
// 清除障碍面
|
||||
if (this.polygonZAM) {
|
||||
this.polygonZAM.remove()
|
||||
this.polygonZAM = null
|
||||
}
|
||||
|
||||
// 清除起点
|
||||
if (this.pointQD) {
|
||||
this.pointQD.remove()
|
||||
this.pointQD = null
|
||||
}
|
||||
|
||||
// 清除终点
|
||||
if (this.pointZD) {
|
||||
this.pointZD.remove()
|
||||
this.pointZD = null
|
||||
}
|
||||
|
||||
// 清除途径点
|
||||
this.viaPoints.forEach((point) => {
|
||||
point.remove()
|
||||
})
|
||||
this.viaPoints = []
|
||||
|
||||
// 清除避让点
|
||||
this.avoidPoints.forEach((point) => {
|
||||
point.remove()
|
||||
})
|
||||
this.avoidPoints = []
|
||||
|
||||
// 清除避让区域
|
||||
this.avoidAreas.forEach((area) => {
|
||||
area.remove()
|
||||
})
|
||||
this.avoidAreas = []
|
||||
|
||||
// 清除最短路径图层
|
||||
this.shortestPathLayer.clear()
|
||||
|
||||
// 清除路网数据图层
|
||||
// this.graphicLayer.clear();
|
||||
},
|
||||
async loadShapefile() {
|
||||
try {
|
||||
// 1. 读取本地 SHP(浏览器)
|
||||
// const shpBuffer = await fetch('./config/map/data/dlfs_lines.zip').then(r => r.arrayBuffer());
|
||||
// const shpJson = await shp(shpBuffer); // {features: [...]}
|
||||
|
||||
// 1. 读取本地 jeojson
|
||||
const shpBuffer = await fetch('./config/map/data/dao.geojson')
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then((data) => {
|
||||
return data
|
||||
})
|
||||
.catch((error) => {})
|
||||
|
||||
// 2. 处理 GeoJSON 数据
|
||||
this.roadNetworkGeoJSON = shpBuffer
|
||||
|
||||
/// 3. 将 GeoJSON 数据添加到 graphicLayer
|
||||
this.roadNetworkGeoJSON.features.forEach((feature) => {
|
||||
const positions = feature.geometry.coordinates[0]
|
||||
const graphic = new window.mars3d.graphic.PolylineEntity({
|
||||
positions: positions,
|
||||
style: {
|
||||
color: '#FF0000',
|
||||
width: 2,
|
||||
outline: false,
|
||||
},
|
||||
})
|
||||
this.graphicLayer.addGraphic(graphic)
|
||||
})
|
||||
this.roadNetworkGeoJSONBuild = this.buildGraph(this.roadNetworkGeoJSON)
|
||||
} catch (error) {
|
||||
console.error('加载 Shapefile 数据失败:', error)
|
||||
}
|
||||
},
|
||||
async drawPolygon() {
|
||||
if (this.polygonZAM) {
|
||||
this.polygonZAM.remove()
|
||||
this.polygonZAM = null
|
||||
}
|
||||
this.polygonZAM = await this.graphicLayer.startDraw({
|
||||
type: 'polygon',
|
||||
style: {
|
||||
color: '#00ffff',
|
||||
opacity: 0.4,
|
||||
clampToGround: true,
|
||||
outline: true,
|
||||
outlineWidth: 1,
|
||||
outlineColor: '#ffffff',
|
||||
},
|
||||
})
|
||||
},
|
||||
drawStartPoint() {
|
||||
if (this.pointQD) {
|
||||
this.pointQD.remove()
|
||||
this.pointQD = null
|
||||
}
|
||||
this.graphicLayer.startDraw({
|
||||
type: 'point',
|
||||
style: {
|
||||
pixelSize: 10,
|
||||
color: 'red',
|
||||
label: {
|
||||
text: '起点',
|
||||
font_size: 20,
|
||||
color: '#ffffff',
|
||||
outline: true,
|
||||
outlineColor: '#000000',
|
||||
pixelOffsetY: -20,
|
||||
},
|
||||
},
|
||||
success: (graphic) => {
|
||||
this.pointQD = graphic
|
||||
this.graphicLayer.stopDraw()
|
||||
},
|
||||
})
|
||||
},
|
||||
drawEndPoint() {
|
||||
if (this.pointZD) {
|
||||
this.pointZD.remove()
|
||||
this.pointZD = null
|
||||
}
|
||||
this.graphicLayer.startDraw({
|
||||
type: 'point',
|
||||
style: {
|
||||
pixelSize: 10,
|
||||
color: 'red',
|
||||
label: {
|
||||
text: '终点',
|
||||
font_size: 20,
|
||||
color: '#ffffff',
|
||||
outline: true,
|
||||
outlineColor: '#000000',
|
||||
pixelOffsetY: -20,
|
||||
},
|
||||
},
|
||||
success: (graphic) => {
|
||||
this.pointZD = graphic
|
||||
this.graphicLayer.stopDraw()
|
||||
},
|
||||
})
|
||||
},
|
||||
// 途径点
|
||||
drawViaPoint() {
|
||||
this.graphicLayer.startDraw({
|
||||
type: 'point',
|
||||
style: {
|
||||
pixelSize: 10,
|
||||
color: 'blue',
|
||||
label: {
|
||||
text: '途径点',
|
||||
font_size: 20,
|
||||
color: '#ffffff',
|
||||
outline: true,
|
||||
outlineColor: '#000000',
|
||||
pixelOffsetY: -20,
|
||||
},
|
||||
},
|
||||
success: (graphic) => {
|
||||
this.viaPoints.push(graphic)
|
||||
this.graphicLayer.stopDraw()
|
||||
},
|
||||
})
|
||||
},
|
||||
// 避让点
|
||||
drawAvoidPoint() {
|
||||
this.graphicLayer.startDraw({
|
||||
type: 'point',
|
||||
style: {
|
||||
pixelSize: 10,
|
||||
color: 'orange',
|
||||
label: {
|
||||
text: '避让点',
|
||||
font_size: 20,
|
||||
color: '#ffffff',
|
||||
outline: true,
|
||||
outlineColor: '#000000',
|
||||
pixelOffsetY: -20,
|
||||
},
|
||||
},
|
||||
success: (graphic) => {
|
||||
this.avoidPoints.push(graphic)
|
||||
this.graphicLayer.stopDraw()
|
||||
},
|
||||
})
|
||||
},
|
||||
// 避让区域
|
||||
drawAvoidArea() {
|
||||
this.graphicLayer.startDraw({
|
||||
type: 'polygon',
|
||||
drawEndEventType: window.mars3d.EventType.dblClick,
|
||||
style: {
|
||||
color: '#ff0000',
|
||||
opacity: 0.4,
|
||||
clampToGround: true,
|
||||
outline: true,
|
||||
outlineWidth: 1,
|
||||
outlineColor: '#ffffff',
|
||||
},
|
||||
success: (graphic) => {
|
||||
this.avoidAreas.push(graphic)
|
||||
this.graphicLayer.stopDraw()
|
||||
},
|
||||
})
|
||||
},
|
||||
// 1. 构建路网拓扑图(经纬度坐标直接处理
|
||||
buildGraph(geojson) {
|
||||
const graph = {}
|
||||
const nodeCoords = {} // 存储节点经纬度
|
||||
|
||||
geojson.features.forEach((road) => {
|
||||
const startNode = road.properties.FNODE_
|
||||
const endNode = road.properties.TNODE_
|
||||
const coords = road.geometry.coordinates
|
||||
|
||||
// 记录节点经纬度(取首尾点)
|
||||
if (!nodeCoords[startNode]) {
|
||||
nodeCoords[startNode] = coords[0][0]
|
||||
}
|
||||
if (!nodeCoords[endNode]) {
|
||||
nodeCoords[endNode] = coords[coords.length - 1][0]
|
||||
}
|
||||
// 计算边权重(距离,单位:米)
|
||||
const distance =
|
||||
turf.distance(
|
||||
turf.point(coords[0][0]),
|
||||
turf.point(coords[coords.length - 1][0]),
|
||||
{units: 'kilometers'}
|
||||
) * 1000
|
||||
|
||||
// 构建邻接表(双向图)
|
||||
graph[startNode] = graph[startNode] || {}
|
||||
graph[startNode][endNode] = distance
|
||||
|
||||
graph[endNode] = graph[endNode] || {}
|
||||
graph[endNode][startNode] = distance
|
||||
})
|
||||
|
||||
return {graph, nodeCoords}
|
||||
},
|
||||
// 2. 匹配最近路网节点(经纬度坐标)
|
||||
findNearestNode(pointCoord, nodeCoords) {
|
||||
let nearestNode = null
|
||||
let minDist = 10000
|
||||
|
||||
for (const [node, coord] of Object.entries(nodeCoords)) {
|
||||
const dist = turf.distance(turf.point(pointCoord), turf.point(coord), {
|
||||
units: 'meters',
|
||||
})
|
||||
|
||||
if (dist < minDist) {
|
||||
minDist = dist
|
||||
nearestNode = node
|
||||
}
|
||||
}
|
||||
return nearestNode
|
||||
},
|
||||
// 3. 路径规划主函数(经纬度坐标输入) - 支持途径点 + 避让点/区域
|
||||
async planRoute(
|
||||
startCoord,
|
||||
endCoord,
|
||||
viaPoints = [],
|
||||
avoidObstacles = null
|
||||
) {
|
||||
const {graph, nodeCoords} = this.roadNetworkGeoJSONBuild
|
||||
|
||||
// 按顺序组合点:起点 -> 途径点 -> 终点
|
||||
const points =
|
||||
viaPoints && viaPoints.length > 0
|
||||
? [startCoord, viaPoints[0].geometry.coordinates, endCoord]
|
||||
: [startCoord, endCoord]
|
||||
const fullPath = []
|
||||
|
||||
for (let i = 0; i < points.length - 1; i++) {
|
||||
const segmentStart = points[i]
|
||||
const segmentEnd = points[i + 1]
|
||||
|
||||
// 匹配最近节点
|
||||
const startNode = this.findNearestNode(segmentStart, nodeCoords)
|
||||
const endNode = this.findNearestNode(segmentEnd, nodeCoords)
|
||||
|
||||
if (!startNode || !endNode) {
|
||||
console.log('无法匹配到路网节点,请检查坐标是否在路网范围内')
|
||||
continue
|
||||
}
|
||||
// 构建临时 graph
|
||||
const tempGraph = JSON.parse(JSON.stringify(graph))
|
||||
|
||||
// 删除避让点节点
|
||||
if (avoidObstacles) {
|
||||
const obstacleNodes = []
|
||||
for (const [node, coord] of Object.entries(nodeCoords)) {
|
||||
const pt = turf.point(coord)
|
||||
avoidObstacles.features.forEach((ob) => {
|
||||
if (turf.booleanPointInPolygon(pt.geometry, ob.geometry))
|
||||
obstacleNodes.push(node)
|
||||
})
|
||||
}
|
||||
obstacleNodes.forEach((node) => delete tempGraph[node])
|
||||
|
||||
// 删除与避让区域相交的边
|
||||
for (const [node, edges] of Object.entries(tempGraph)) {
|
||||
for (const targetNode of Object.keys(edges)) {
|
||||
if (!tempGraph[targetNode]) {
|
||||
// 避让点节点已经删除
|
||||
delete tempGraph[node][targetNode]
|
||||
continue
|
||||
}
|
||||
const line = turf.lineString([
|
||||
nodeCoords[node],
|
||||
nodeCoords[targetNode],
|
||||
])
|
||||
avoidObstacles.features.forEach((area) => {
|
||||
if (turf.booleanCrosses(line, area)) {
|
||||
delete tempGraph[node][targetNode]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dijkstra 计算最短路径
|
||||
const pathNodes = dijkstra.find_path(tempGraph, startNode, endNode)
|
||||
if (!pathNodes || pathNodes.length === 0) {
|
||||
console.log('未找到可行路径段:', i)
|
||||
continue
|
||||
}
|
||||
|
||||
// 生成路径几何
|
||||
for (let j = 0; j < pathNodes.length - 1; j++) {
|
||||
const currentNode = pathNodes[j]
|
||||
const nextNode = pathNodes[j + 1]
|
||||
const segment = this.roadNetworkGeoJSON.features.find(
|
||||
(f) =>
|
||||
(f.properties.FNODE_ == currentNode &&
|
||||
f.properties.TNODE_ == nextNode) ||
|
||||
(f.properties.FNODE_ == nextNode &&
|
||||
f.properties.TNODE_ == currentNode)
|
||||
)
|
||||
if (segment) {
|
||||
fullPath.push(...segment.geometry.coordinates[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fullPath
|
||||
},
|
||||
async calculateShortestPath() {
|
||||
if (!this.pointQD || !this.pointZD || !this.roadNetworkGeoJSON) {
|
||||
alert('请先加载路网数据并绘制障碍面、起点和终点!')
|
||||
return
|
||||
}
|
||||
this.shortestPathLayer.clear()
|
||||
const startPoint = turf.point(
|
||||
this.pointQD.toGeoJSON().geometry.coordinates
|
||||
).geometry.coordinates // 起点
|
||||
const endPoint = turf.point(this.pointZD.toGeoJSON().geometry.coordinates)
|
||||
.geometry.coordinates // 终点
|
||||
// 途径点
|
||||
const viaPointsGeoJSON =
|
||||
this.viaPoints.map((point) => point.toGeoJSON()) || []
|
||||
const viaPointsTurf = viaPointsGeoJSON.map((p) =>
|
||||
turf.point(p.geometry.coordinates)
|
||||
)
|
||||
// 避让点
|
||||
const avoidPointsGeoJSON =
|
||||
this.avoidPoints.map((point) => point.toGeoJSON()) || []
|
||||
const avoidPointsPolygons = avoidPointsGeoJSON.map((point) => {
|
||||
return turf.circle(
|
||||
turf.point(point.geometry.coordinates),
|
||||
10, // 半径10米(根据需求调整)
|
||||
{steps: 32, units: 'meters'} // 显式指定单位
|
||||
)
|
||||
})
|
||||
// 避让区域
|
||||
const avoidAreasGeoJSON =
|
||||
this.avoidAreas.map((area) => area.toGeoJSON({closure: true})) || []
|
||||
const obstaclesGeoJSON = turf.featureCollection([
|
||||
...avoidPointsPolygons,
|
||||
...avoidAreasGeoJSON,
|
||||
])
|
||||
const route = await this.planRoute(
|
||||
startPoint,
|
||||
endPoint,
|
||||
viaPointsTurf,
|
||||
obstaclesGeoJSON
|
||||
)
|
||||
this.drawPath(route)
|
||||
},
|
||||
|
||||
// 单独的路径绘制方法
|
||||
drawPath(path) {
|
||||
const positions = path
|
||||
const polyline = new window.mars3d.graphic.PolylinePrimitive({
|
||||
positions: positions,
|
||||
style: {
|
||||
clampToGround: true,
|
||||
color: '#55ff33',
|
||||
width: 8,
|
||||
},
|
||||
})
|
||||
this.shortestPathLayer.addGraphic(polyline)
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#home {
|
||||
<style scoped>
|
||||
.home-header {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 34px;
|
||||
box-sizing: border-box;
|
||||
background: #abc6bc;
|
||||
}
|
||||
.home-header img {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.sure {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* padding: 4px 12px; */
|
||||
gap: 10px;
|
||||
background: #176363;
|
||||
border-radius: 4px;
|
||||
width: 54px;
|
||||
height: 24px;
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
}
|
||||
.home {
|
||||
display: flex;
|
||||
height: calc(100% - 60px);
|
||||
background: #abc6bc;
|
||||
}
|
||||
.main-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
.control-panel {
|
||||
width: 340px;
|
||||
padding: 20px 26px;
|
||||
margin-left: 4px;
|
||||
background-size: cover;
|
||||
background: #d4e5db;
|
||||
}
|
||||
|
||||
.control-panel .title {
|
||||
/* text-align: center; */
|
||||
margin-bottom: 10px;
|
||||
color: #1c1c1c;
|
||||
}
|
||||
.importJson {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #2f705f;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
width: 260px;
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#map,
|
||||
#mapbox,
|
||||
.el-main {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user