294 lines
7.4 KiB
Vue
294 lines
7.4 KiB
Vue
<template>
|
|
<div class="map-container">
|
|
<div id="mapContainer" class="map-box"></div>
|
|
<!-- <div class="map-control">
|
|
<img
|
|
v-for="(item, index) in nextMapControl"
|
|
:key="index"
|
|
:src="item.icon"
|
|
:title="item.title"
|
|
@click="handlerMapControlClick(item.handler)"
|
|
/>
|
|
<img v-show="nextMapControl.length > 0" @click="handlerUnDraw" src="/del.png" title="清除" />
|
|
</div> -->
|
|
<LayerComponent
|
|
@changeOpenModal="changeOpenModal"
|
|
@changeOpenInsertShpModal="changeOpenInsertShpModal"
|
|
/>
|
|
<LayerControl @draw="handlerDrawPolygon" />
|
|
<UseModal v-model:openModal="openModal" @changeOpenModal="changeOpenModal" />
|
|
<InsertShp v-model:openModal="insertShpModal" />
|
|
<DataListComponent />
|
|
<RightShowInfo v-model:openModal="openRightInfo" />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, onUnmounted, defineProps, reactive, ref } from 'vue';
|
|
import { useMessage } from '@/hooks/web/useMessage';
|
|
import mapboxgl, { Map, Popup } from 'mapbox-gl';
|
|
|
|
// 图形绘制工具类
|
|
import MapboxDraw from '@mapbox/mapbox-gl-draw';
|
|
|
|
import U from 'mapbox-gl-utils';
|
|
import 'mapbox-gl/dist/mapbox-gl.css';
|
|
import './src/index.less';
|
|
import { MapboxConfig, MapboxDefaultStyle, MapControlConfig } from './src/config';
|
|
import { MP } from './src/MP';
|
|
import { DrawingType } from '@/enums/mapEnum';
|
|
|
|
import {
|
|
SnapPolygonMode,
|
|
SnapPointMode,
|
|
SnapLineMode,
|
|
SnapModeDrawStyles,
|
|
SnapDirectSelect,
|
|
} from 'mapbox-gl-draw-snap-mode';
|
|
import LayerComponent from './LayerComponent/index.vue';
|
|
import LayerControl from './LayerControl/index.vue';
|
|
import UseModal from './Modal/index.vue';
|
|
import InsertShp from './InsertShp/index.vue';
|
|
import DataListComponent from './DataListComponent/index.vue';
|
|
import RightShowInfo from './RightShowInfo/index.vue';
|
|
|
|
const openModal = ref(false);
|
|
const insertShpModal = ref(false);
|
|
const openRightInfo = ref(false);
|
|
const changeOpenModal = (value) => {
|
|
openModal.value = value;
|
|
};
|
|
const changeOpenInsertShpModal = (value) => {
|
|
insertShpModal.value = value;
|
|
};
|
|
|
|
// map参数类型
|
|
interface MapboxOptionsInterface {
|
|
mapOptions: mapboxgl.MapboxOptions;
|
|
control: DrawingType[];
|
|
}
|
|
const props = defineProps<MapboxOptionsInterface>();
|
|
|
|
let nextMapControl: Array<any> = reactive([]);
|
|
nextMapControl = props.control
|
|
? props.control.map((item) => {
|
|
console.log('item::: ', item);
|
|
return MapControlConfig[item];
|
|
})
|
|
: [];
|
|
|
|
console.log('nextMapControl::: ', nextMapControl);
|
|
|
|
// 定义地图容器
|
|
let map: Map;
|
|
let popup: Popup;
|
|
let clickPoisition: Array<number> = [];
|
|
let selectFeature: Object = {};
|
|
let mp: any = null;
|
|
|
|
const { createConfirm, createMessage } = useMessage();
|
|
|
|
// 定义地图回调emit
|
|
// 地图加载完成回调
|
|
const emit = defineEmits(['mapOnLoad', 'mapDraw']);
|
|
|
|
onMounted(() => {
|
|
mapboxgl.accessToken = MapboxConfig.ACCESS_TOKEN;
|
|
map = initMap();
|
|
map.on('load', () => {
|
|
//挂载mapbox-gl-utils
|
|
// U.init(map);
|
|
mp = new MP(map);
|
|
emit('mapOnLoad', map);
|
|
|
|
// 初始化绘图空间
|
|
handlerInitDrawTool();
|
|
|
|
map.on('click', (e) => {
|
|
clickPoisition = e.lngLat;
|
|
});
|
|
|
|
map.on('draw.selectionchange', (e) => {
|
|
handlerCopyToTargetLayer(e);
|
|
});
|
|
|
|
window.handlerCopyFeature = handlerCopyFeature;
|
|
});
|
|
});
|
|
// 销毁地图
|
|
// 移除地图实例
|
|
onUnmounted(() => {
|
|
map ? map.remove() : null;
|
|
});
|
|
// 初始化地图
|
|
// 返回地图实例
|
|
const initMap = () => {
|
|
return new mapboxgl.Map({
|
|
container: 'mapContainer',
|
|
language: 'zh-cmn',
|
|
projection: 'equirectangular', // wgs84参考系
|
|
style: MapboxDefaultStyle,
|
|
maxZoom: 22,
|
|
minZoom: 6,
|
|
...props.mapOptions,
|
|
});
|
|
};
|
|
|
|
const handlerMapControlClick = (handler: string) => {
|
|
handler === 'handlerDrawPoint' && handlerDrawPoint();
|
|
handler === 'handlerDrawLineString' && handlerDrawLineString();
|
|
handler === 'handlerDrawPolygon' && handlerDrawPolygon();
|
|
};
|
|
//绘制点
|
|
const handlerDrawPoint = () => {
|
|
mp.draw('Point');
|
|
mp.on('Point', function (e) {
|
|
emit('mapDraw', 'Point', e);
|
|
});
|
|
};
|
|
//绘制线
|
|
const handlerDrawLineString = () => {
|
|
mp.draw('LineString');
|
|
mp.on('LineString', function (e) {
|
|
emit('mapDraw', 'LineString', e);
|
|
});
|
|
};
|
|
//绘制面
|
|
const handlerDrawPolygon = () => {
|
|
mp.draw('Polygon');
|
|
mp.on('Polygon', function (e) {
|
|
emit('mapDraw', 'Polygon', e);
|
|
});
|
|
};
|
|
//删除标记
|
|
const handlerUnDraw = () => {
|
|
mp.deleteDraw();
|
|
emit('mapDraw', 'cancel');
|
|
};
|
|
|
|
// 初始化绘图空间
|
|
const handlerInitDrawTool = () => {
|
|
let drawTool = new MapboxDraw({
|
|
modes: {
|
|
...MapboxDraw.modes,
|
|
draw_point: SnapPointMode,
|
|
draw_polygon: SnapPolygonMode,
|
|
draw_line_string: SnapLineMode,
|
|
direct_select: SnapDirectSelect,
|
|
},
|
|
// Styling guides
|
|
styles: SnapModeDrawStyles,
|
|
userProperties: true,
|
|
// Config snapping features
|
|
snap: true,
|
|
snapOptions: {
|
|
snapPx: 15, // defaults to 15
|
|
snapToMidPoints: true, // defaults to false
|
|
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
|
|
},
|
|
guides: true,
|
|
});
|
|
|
|
map.addControl(drawTool, 'top-right');
|
|
};
|
|
|
|
// 将图斑复制到指定图层
|
|
const handlerCopyToTargetLayer = (e) => {
|
|
if (e.features.length > 0) {
|
|
if (popup) {
|
|
popup.remove();
|
|
popup = null;
|
|
}
|
|
|
|
selectFeature = e.features[0];
|
|
|
|
popup = new mapboxgl.Popup({
|
|
closeButton: false,
|
|
closeOnClick: false,
|
|
});
|
|
|
|
// 设置 popup 的位置和内容
|
|
popup
|
|
.setLngLat(clickPoisition)
|
|
.setHTML(
|
|
`
|
|
<div style="color:#333;padding:3px 12px;cursor:pointer;" type="primary" icon="el-icon-search" onclick="handlerCopyFeature();">复制当前图斑</div>`,
|
|
)
|
|
.addTo(map);
|
|
} else {
|
|
popup.remove();
|
|
}
|
|
};
|
|
|
|
const handlerCopyFeature = () => {
|
|
console.log(selectFeature);
|
|
popup.remove();
|
|
createMessage.success('复制成功!');
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.mapboxgl-ctrl-group:not(:empty) {
|
|
box-shadow: none;
|
|
}
|
|
.mapboxgl-ctrl-group {
|
|
background: none !important;
|
|
}
|
|
.mapbox-gl-draw_ctrl-draw-btn {
|
|
width: 40px !important;
|
|
height: 40px !important;
|
|
float: left;
|
|
border-radius: 50%;
|
|
}
|
|
.mapboxgl-ctrl-top-right {
|
|
}
|
|
|
|
.mapboxgl-ctrl-group button + button {
|
|
border: 0px;
|
|
margin: 0px 3px;
|
|
}
|
|
|
|
.mapbox-gl-draw_ctrl-draw-btn:hover {
|
|
transform: scale(1.2);
|
|
}
|
|
.mapbox-gl-draw_polygon {
|
|
background-image: url(/polygon.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
.mapbox-gl-draw_point {
|
|
background-image: url(/point.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
.mapbox-gl-draw_line {
|
|
background-image: url(/line.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
.mapbox-gl-draw_trash {
|
|
background-image: url(/del.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
.mapbox-gl-draw_combine {
|
|
background-image: url(/combine.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
.mapbox-gl-draw_uncombine {
|
|
background-image: url(/uncombine.png);
|
|
background-size: 100% 100%;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
</style>
|