CaiYuanYiTiHua/src/components/MapboxMaps/MapboxMap.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>