CaiYuanYiTiHua/src/components/MapboxMaps/MapComponent.vue

614 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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);
}
handlerDrawComplete()
}
// 删除数据
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);
}
}
handlerDrawComplete()
}
// 初始化地图 返回地图实例
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();
drawTool.set(geojson.geojson);
}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)
drawTool = null;
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++){
try{
let featureTemp = WktToGeojson(features[i].value);
let feature = {
"id": "cd1d93c0e4a6747ff597f"+parseInt(1000000000*Math.random()).toString(),
"type": "Feature",
"properties": {},
"geometry": featureTemp
}
geo.features.push(feature);
}catch(e){
console.log("WKT解析错误请检查WKT数据格式是否有误")
}
}
}
}
console.log("geo.geo",geo);
handlerInitDrawTool(geo)
}
defineExpose({
handlerDraw,
handlerLocation,
handlerCancleDraw,
});
</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>