CaiYuanYiTiHua/src/components/MapboxMaps/MapComponent.vue

606 lines
15 KiB
Vue

<template>
<div class="map-container">
<div id="mapContainer" class="map-box"></div>
<!-- 图层控制 -->
<div class="layer-control-center">
<p v-for="(item,index) in props.layers" >
<a-checkbox v-model:checked="item.checked" @change="handlerCheckboxChange(item)" >{{item.name}}</a-checkbox>
</p>
</div>
<!-- 绘图控制 -->
<div class="draw-control-center" v-show="drawing">
<div class="draw-btn" @click="handlerCancleDraw">
取消
</div>
<div class="draw-btn" @click="handlerDrawComplete">
保存
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, defineProps,defineEmits, reactive, ref,defineExpose } 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 {customDrawStyles} from './Styles/Styles'
import Drawtool from '@/views/datamaintenance/components/drawtool.vue';
import {WktToGeojson,GeojsonToWkt} from './src/WktGeojsonTransform'
import { features } from 'process';
const openModal = ref(false);
const insertShpModal = 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(
{
layers:{
type:Array,
default:[],
},
location:{
type:Array,
default:[],
},
type:{
type:String,
default:"",
},
feature:{
type:String,
default:"",
}
}
);
let nextMapControl: Array<any> = reactive([]);
nextMapControl = props.control
? props.control.map((item) => {
return MapControlConfig[item];
})
: [];
// 定义地图容器
let map: Map;
let drawTool:any;
let popup:Popup;
let clickPoisition:Array<number> = [];
let selectFeature:Object = {};
let mp: any = null;
let geojson = reactive({
geojson:{}
});
let drawing = ref(false)
let drawGeojson = reactive({
geojson:{
type: "FeatureCollection",
features: [],
}
})
const { createConfirm, createMessage } = useMessage();
// 定义地图回调emit
// 地图加载完成回调
const emit = defineEmits(['mapOnLoad', 'mapDraw','handlerDrawComplete']);
onMounted(() => {
mapboxgl.accessToken = MapboxConfig.ACCESS_TOKEN;
map = initMap();
map.on('load', () => {
// 初始化绘图空间
// handlerInitDrawTool(null);
map.on("click",(e)=>{
// handlerPreviewFeatureInfo(e);
clickPoisition = e.lngLat
})
map.on("draw.selectionchange",(e)=>{
// handlerCopyToTargetLayer(e);
})
emit('mapOnLoad', map)
// 设置绘图监听事件
map.on("draw.create", function (e) {
drawGeojson.geojson.features = e.features
handlerDealFeature(e.features[0])
});
map.on("draw.update", function (e) {
drawGeojson.geojson = e.features
handlerDealFeature(e.features[0])
});
map.on("draw.delete",function(e){
handlerDeleteFeature(e.features[0]);
})
window.handlerCopyFeature = handlerCopyFeature;
});
});
// 销毁地图
// 移除地图实例
onUnmounted(() => {
map ? map.remove() : null;
});
// 数据绘制完成判断
const handlerDealFeature = (feature)=>{
let existFeature = geojson.geojson.features.find((item,index)=>{
return item.id == feature.id
})
if(existFeature){ // 如果查找到了 则替换数据
for(let i=0;i<geojson.geojson.features.length;i++){
if(geojson.geojson.features[i].id == feature.id){
geojson.geojson.features[i] = feature
}
}
}else{ // 如果没找到数据 则添加到数组
geojson.geojson.features.push(feature);
}
console.log("geojson.geojson",geojson.geojson);
}
// 删除数据
const handlerDeleteFeature = (feature)=>{
for(let i=0;i<geojson.geojson.features.length;i++){
if(geojson.geojson.features[i].id==feature.id){
geojson.geojson.features.splice(i,1);
}
}
console.log("geojson.geojson",geojson.geojson);
}
// 初始化地图 返回地图实例
const initMap = () => {
return new mapboxgl.Map({
container: 'mapContainer',
language: 'zh-cmn',
projection: 'equirectangular', // wgs84参考系
style: MapboxDefaultStyle,
maxZoom: 22,
minZoom: 6,
zoom:14,
center:props.location
});
};
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 = (feature) => {
geojson.geojson = feature;
if(drawTool){
drawTool.deleteAll();
}else{
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
draw_polygon: SnapPolygonMode,
draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 12, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, "top-right");
drawTool.set(geojson.geojson);
}
// 正在绘制
drawing.value = true;
}
// 将图斑复制到指定图层
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 = () => {
popup.remove();
createMessage.success("复制成功!")
}
// 添加到图层
const handlerAddToLayerList = (layer) => {
handlerCheckLayerExist(layer);
}
// 判断图层列表中是否一定添加
const handlerCheckLayerExist = (layer) =>{
for(let i=0;i<layerList.length;i++){
if(layerList[i] == layer.id){
return;
}
}
layerList.push(layer);
}
const handlerCheckboxChange = (item) => {
handlerPreviewLayer(item)
}
// 控制图层是否显示
const handlerPreviewLayer = (layer) => {
handlerLayerControler(layer)
}
// 图层控制中心
const handlerLayerControler = (layerInfo)=>{
if(map.getSource(layerInfo.layer.id)){
if(layerInfo.checked){
map.setLayoutProperty(layerInfo.layer.id, "visibility", "visible");
}else{
map.setLayoutProperty(layerInfo.layer.id, "visibility", "none");
}
}else{
map.addLayer(layerInfo.layer)
map.on("click",layerInfo.layer.id,function(e){
handlerPreviewFeatureInfo(e);
})
}
}
// 查看列表数据
const handlerDataList = () => {
}
// 图斑属性查看
const handlerPreviewFeatureInfo = (e) => {
if(e.features){
isOpen.value = true;
}
}
const handlerClose = (e) => {
isOpen.value = e;
}
// 图斑定位
const handlerLocation = (lngLat) => {
map.flyTo({
center: lngLat,
zoom: 16,
speed: 10, // 飞行速度
curve: 1, // 飞行曲线
easing(t) {
// 飞行动画函数
return t;
},
});
}
// 编辑图斑
const handlerEdit = (info) => {
initDraw(info);
}
const initDraw = (layerInfo)=> {
// 实例化绘图工具
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
draw_polygon: SnapPolygonMode,
draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 15, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, "top-right");
// let geojson:Object = {};
// if (layerInfo.dataType == "面") {
// geojson.type = "Polygon";
// geojson.coordinates = geojson.coordinates[0];
// } else if (layerInfo.dataType == "点") {
// geojson.type = "Point";
// geojson.coordinates = geojson.coordinates;
// } else if (layerInfo.dataType == "线") {
// geojson.type = "LineString";
// geojson.coordinates = geojson.coordinates[0];
// }
// if (formData.lat && formData.lng) {
// formData.lat = geojson.coordinates[1];
// formData.lng = geojson.coordinates[0];
// }
// geojson = {
// type: "FeatureCollection",
// features: [
// {
// type: "Feature",
// geometry: geojson,
// },
// ],
// };
// map.setLayoutProperty("pbfLayer", "visibility", "none");
// drawTool.set(geojson);
}
const handlerDrawComplete = () => {
let arr= [];
geojson.geojson.features.forEach((item,index)=>{
let wktStr = GeojsonToWkt(item.geometry)
let obj = {
columnName:"mapgeom",
value:wktStr
}
arr.push(obj);
})
emit("handlerDrawComplete",arr)
}
const handlerCancleDraw = () => {
map.removeControl(drawTool)
drawing.value = false;
// drawTool.set(geojson.geojson)
}
const handlerDraw = (features=null) =>{
let geo = {
type: 'FeatureCollection',
features: []
};
if(features==null){
}else{
if(features.length > 0){
for(let i=0; i < features.length; i++){
let featureTemp = WktToGeojson(features[i].value);
featureTemp.type="Polygon";
let feature = {
"id": "cd1d93c0e4a6747ff597f"+parseInt(1000000000*Math.random()).toString(),
"type": "Feature",
"properties": {},
"geometry": featureTemp
}
geo.features.push(feature);
}
}
}
handlerInitDrawTool(geo)
}
defineExpose({
handlerDraw,
handlerLocation
});
</script>
<style>
.map-container{
width:100%;
height:100%;
}
.map-box{
width:100%;
height:100%;
}
.layer-control-center{
position:absolute;
padding:10px;
top:15px;
left:15px;
background:#ffffff;
border-radius: 12px;
}
.layer-control-center p{
margin:0px;
}
.draw-control-center{
position:absolute;
padding:7px;
top:15px;
right:15px;
background:#ffffff;
border-radius: 12px;
}
.draw-control-center .draw-btn{
float:left;
margin:0px 6px;
padding:5px;
border-radius: 5px;
}
.draw-control-center .draw-btn:hover{
background-color: rgb(0 0 0/5%);
cursor:pointer;
}
.mapboxgl-ctrl-group:not(:empty){
box-shadow: none;
}
.mapboxgl-ctrl-group{
padding:10px;
border-radius: 12px;
position:relative;
right:140px;
top:5px;
}
.mapbox-gl-draw_ctrl-draw-btn{
width:20px!important;
height:20px!important;
float:left;
}
.mapboxgl-ctrl-top-right{
}
.mapboxgl-ctrl-group button+button{
border:0px;
margin:0px 10px;
}
.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;
margin:0px 10px;
}
.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>