606 lines
15 KiB
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>
|
|
|