Compare commits

...

3 Commits

Author SHA1 Message Date
徐景良 fa56b958f5 merege 2024-05-18 16:46:31 +08:00
徐景良 8308554ab0 地图绘图组件封装 2024-05-18 16:35:24 +08:00
徐景良 b198558205 图层选择、图层控制、地图交互 2024-05-17 16:27:54 +08:00
23 changed files with 1269 additions and 311 deletions

View File

@ -102,6 +102,7 @@
"mapbox-gl-utils": "^0.44.0",
"@mapbox/mapbox-gl-draw": "^1.4.1",
"mapbox-gl-draw-snap-mode": "^0.2.0",
"terraformer-wkt-parser": "^1.2.1",
"mars3d": "^3.7.0",
"mars3d-cesium": "^1.113.0",
"min-dash": "^4.2.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 409 B

BIN
public/iocn/combine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/iocn/del.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
public/iocn/line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/iocn/point.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
public/iocn/polygon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/iocn/uncombine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 401 B

View File

@ -3,8 +3,12 @@
<a-table :columns="columns" :data-source="dataSource" :pagination="false" :bordered="true">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<a-button class="operation-button" shape="round">
操作
<a-button class="operation-button" shape="round" @click="handlerLocation(record)">
定位
</a-button>
<a-button class="operation-button" shape="round" @click="handlerEdit(record)">
编辑
</a-button>
</template>
</template>
@ -14,8 +18,10 @@
<script setup lang="ts">
import { DeleteOutlined } from '@ant-design/icons-vue'
import { h } from "vue"
import { h,defineEmits } from "vue"
import './index.scss'
const emits = defineEmits(["handlerLocation","handlerEdit"])
const columns = [
{
title: '位置',
@ -57,6 +63,15 @@ const dataSource = [
is_del: '上海市普陀区金沙江路 1516 弄',
},
]
const handlerLocation = () => {
emits("handlerLocation",[118.630881,35.800163])
}
const handlerEdit = () => {
emits("handlerEdit")
}
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,543 @@
<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'
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) => {
console.log('item::: ', item);
return MapControlConfig[item];
})
: [];
console.log('nextMapControl::: ', nextMapControl);
//
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:{}
})
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);
})
//
map.on("draw.create", function (e) {
console.log(e);
drawGeojson.geojson = e.features[0]
});
map.on("draw.update", function (e) {
console.log(e);
drawGeojson.geojson = e.features[0]
});
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,
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;
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 = () => {
console.log("selectFeature",selectFeature);
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)=>{
console.log("layerinfoinfo",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){
console.log("EEEEEEE",e.features[0].layer.id,e.features[0].properties);
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 = () => {
emit("handlerDrawComplete",GeojsonToWkt(drawGeojson.geojson.geometry))
}
const handlerCancleDraw = () => {
map.removeControl(drawTool)
drawing.value = false;
// drawTool.set(geojson.geojson)
}
const handlerDraw = (feature=null) =>{
let featureTemp = WktToGeojson(feature);
console.log("传入的WKT",featureTemp);
let geo = {
type: "FeatureCollection",
features: [
{
"id": "cd1d93c0e4a6747ff597f190c311d0e3",
"type": "Feature",
"properties": {},
"geometry": featureTemp
}
],
}
console.log("geo",geo);
handlerInitDrawTool(geo)
}
defineExpose({
handlerDraw,
handlerLocation
});
</script>
<style>
.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>

View File

@ -1,293 +1,294 @@
<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)"
<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"
/>
<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();
<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 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>
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>

View File

@ -38,8 +38,13 @@
<div class="button">
<!-- <a-button type="primary" style="background-color:#09B66D;margin-right: 10px">
编辑
<<<<<<< HEAD
</a-button>
<a-button type="primary" @click="handlerAddToLayerList">
=======
</a-button> -->
<a-button type="primary">
>>>>>>> 2aed0750b8d9679d2f0bc47b0c629ecf78313c2c
<template #icon>
<PlusOutlined />
</template>
@ -84,10 +89,13 @@
<script setup lang="ts">
import { PlusOutlined } from '@ant-design/icons-vue'
import { errorImage } from '../../util.js'
import { ref } from "vue"
import { ref,defineEmits } from "vue"
import MapboxMap from '@/components/MapboxMaps/index.vue'
import { DrawingType } from '@/enums/mapEnum';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const emits = defineEmits(["handlerAddToLayerList"])
const data = ref('vector-data')
const sort = ref('default')
const key = ref('')
@ -184,6 +192,47 @@ const showInfo = (item) => {
jsonData.value = JSON.stringify(data, null, 4);
console.log(jsonData.value)
}
//
const handlerAddToLayerList = (item) => {
let layerInfo = {
id:parseInt(10*Math.random()),
name:parseInt(10000000*Math.random()).toString(),
checked:false,
layer:{
'id': 'roadnetLine'+parseInt(10000000*Math.random()).toString(),
'type': 'line',
'source': {
type: 'vector',
tiles: [ 'http://192.168.10.102:9020/api/DroneCaseinfo/QueryVectorTileByTable?z={z}&x={x}&y={y}&table=yishuixian&X-Token=1ded3fe7'],
minzoom: 1,
maxzoom: 20
},
"source-layer": "yishuixian",
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': [
"case",
["==", ["get", "handle_status_id"], 0],
"#E6A23C",
["==", ["get", "handle_status_id"], 1],
"#409EFF",
["==", ["get", "handle_status_id"], 2],
"#67C23A",
//
"#67C23A",
],
'line-width': 1
}
}
}
createMessage.success("图层已添加到工作区!")
emits("handlerAddToLayerList",layerInfo);
}
</script>
<style lang="scss" scoped>

View File

@ -4,7 +4,9 @@
<CloseCircleOutlined />
</template>
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="服务资源" ><ServeResource /></a-tab-pane>
<a-tab-pane key="1" tab="服务资源" >
<ServeResource @handlerAddToLayerList="handlerAddToLayerList" />
</a-tab-pane>
<!-- <a-tab-pane key="2" tab="第三方服务"><ThirdPartyServe /></a-tab-pane>
<a-tab-pane key="3" tab="离线文件"><OfflineFile /></a-tab-pane> -->
</a-tabs>
@ -19,8 +21,12 @@ import ThirdPartyServe from './ThirdPartyServe/index.vue'
import OfflineFile from './OfflineFile/index.vue'
import './index.scss'
const props = defineProps(['openModal'])
const emits = defineEmits(['changeOpenModal','update:openModal'])
const emits = defineEmits(['changeOpenModal','update:openModal','handlerAddToLayerList'])
const activeKey = ref('1')
const handlerAddToLayerList = (item) => {
emits("handlerAddToLayerList",item)
}
</script>
<style lang="scss" scoped>

View File

@ -1,5 +1,9 @@
<template>
<<<<<<< HEAD
<a-drawer class="right-show-info" placement="right" :open="isOpen" @close="handlerClose">
=======
<a-drawer class="right-show-info" placement="right" :open="open" @close="() => (open = false)">
>>>>>>> 2aed0750b8d9679d2f0bc47b0c629ecf78313c2c
<div class="title">
<div class="tag"></div>
<div class="title-text">操作</div>
@ -16,6 +20,25 @@
</template>
<script setup lang="ts">
<<<<<<< HEAD
import { ref,defineProps,defineEmits } from "vue"
import './index.scss'
const props = defineProps({
isOpen:{
type:Boolean,
default:false
}
})
const emits = defineEmits(['handlerClose'])
const handlerClose = () => {
emits("handlerClose",false)
}
=======
import { ref, defineProps, watch } from 'vue';
import './index.scss';
const open = ref(true);
@ -26,6 +49,7 @@
open.value = newValue;
},
);
>>>>>>> 2aed0750b8d9679d2f0bc47b0c629ecf78313c2c
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,231 @@
let customDrawStyles = [{
"id": "gl-draw-polygon-fill-inactive",
"type": "fill",
"filter": ["all", ["==", "active", "false"],
["==", "$type", "Polygon"],
["!=", "mode", "static"]
],
"paint": {
"fill-color": "#3bb2d0",
"fill-outline-color": "#6495ed",
"fill-opacity": 0.5
}
}, {
"id": "gl-draw-polygon-fill-active",
"type": "fill",
"filter": ["all", ["==", "active", "true"],
["==", "$type", "Polygon"]
],
"paint": {
"fill-color": "#fbb03b",
"fill-outline-color": "#fbb03b",
"fill-opacity": 0.5
}
}, {
"id": "gl-draw-polygon-midpoint",
"type": "circle",
"filter": ["all", ["==", "$type", "Point"],
["==", "meta", "midpoint"]
],
"paint": {
"circle-radius": 3,
"circle-color": "#fbb03b"
}
}, {
"id": "gl-draw-polygon-stroke-inactive",
"type": "line",
"filter": ["all", ["==", "active", "false"],
["==", "$type", "Polygon"],
["!=", "mode", "static"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#3bb2d0",
"line-width": 2
}
}, {
"id": "gl-draw-polygon-stroke-active",
"type": "line",
"filter": ["all", ["==", "active", "true"],
["==", "$type", "Polygon"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#fbb03b",
"line-dasharray": [0.2, 2],
"line-width": 2
}
}, {
"id": "gl-draw-line-inactive",
"type": "line",
"filter": ["all", ["==", "active", "false"],
["==", "$type", "LineString"],
["!=", "mode", "static"],
["!=", "user_isSnapGuide", "true"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#3bb2d0",
"line-width": 2
}
}, {
"id": "gl-draw-line-active",
"type": "line",
"filter": ["all", ["==", "$type", "LineString"],
["==", "active", "true"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#fbb03b",
"line-dasharray": [0.2, 2],
"line-width": 2
}
}, {
"id": "gl-draw-polygon-and-line-vertex-stroke-inactive",
"type": "circle",
"filter": ["all", ["==", "meta", "vertex"],
["==", "$type", "Point"],
["!=", "mode", "static"]
],
"paint": {
"circle-radius": 5,
"circle-color": "#fff"
}
}, {
"id": "gl-draw-polygon-and-line-vertex-inactive",
"type": "circle",
"filter": ["all", ["==", "meta", "vertex"],
["==", "$type", "Point"],
["!=", "mode", "static"]
],
"paint": {
"circle-radius": 3,
"circle-color": "#fbb03b"
}
}, {
"id": "gl-draw-point-point-stroke-inactive",
"type": "circle",
"filter": ["all", ["==", "active", "false"],
["==", "$type", "Point"],
["==", "meta", "feature"],
["!=", "mode", "static"]
],
"paint": {
"circle-radius": 5,
"circle-opacity": 1,
"circle-color": "#fff"
}
}, {
"id": "gl-draw-point-inactive",
"type": "circle",
"filter": ["all", ["==", "active", "false"],
["==", "$type", "Point"],
["==", "meta", "feature"],
["!=", "mode", "static"]
],
"paint": {
"circle-radius": 3,
"circle-color": "#3bb2d0"
}
}, {
"id": "gl-draw-point-stroke-active",
"type": "circle",
"filter": ["all", ["==", "$type", "Point"],
["==", "active", "true"],
["!=", "meta", "midpoint"]
],
"paint": {
"circle-radius": 7,
"circle-color": "#fff"
}
}, {
"id": "gl-draw-point-active",
"type": "circle",
"filter": ["all", ["==", "$type", "Point"],
["!=", "meta", "midpoint"],
["==", "active", "true"]
],
"paint": {
"circle-radius": 5,
"circle-color": "#fbb03b"
}
}, {
"id": "gl-draw-polygon-fill-static",
"type": "fill",
"filter": ["all", ["==", "mode", "static"],
["==", "$type", "Polygon"]
],
"paint": {
"fill-color": "#404040",
"fill-outline-color": "#404040",
"fill-opacity": 0.1
}
}, {
"id": "gl-draw-polygon-stroke-static",
"type": "line",
"filter": ["all", ["==", "mode", "static"],
["==", "$type", "Polygon"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#404040",
"line-width": 2
}
}, {
"id": "gl-draw-line-static",
"type": "line",
"filter": ["all", ["==", "mode", "static"],
["==", "$type", "LineString"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#404040",
"line-width": 2
}
}, {
"id": "gl-draw-point-static",
"type": "circle",
"filter": ["all", ["==", "mode", "static"],
["==", "$type", "Point"]
],
"paint": {
"circle-radius": 5,
"circle-color": "#404040"
}
}, {
"id": "guide",
"type": "line",
"filter": ["all", ["==", "$type", "LineString"],
["==", "user_isSnapGuide", "true"]
],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "#c00c00",
"line-width": 1,
"line-dasharray": [5, 5]
}
}]
export {customDrawStyles}

View File

@ -1,6 +1,6 @@
<template>
<div class="map-container">
<div :id="`mapContainer-${id}`" class="map-box"></div>
<div id="mapContainerComponent" class="map-box"></div>
<div class="map-control">
<img
v-for="(item, index) in nextMapControl"
@ -15,7 +15,7 @@
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, defineProps, reactive, ref, h } from 'vue';
import { onMounted, onUnmounted, defineProps, reactive } from 'vue';
import mapboxgl, { Map } from 'mapbox-gl';
import U from 'mapbox-gl-utils';
import 'mapbox-gl/dist/mapbox-gl.css';
@ -23,8 +23,7 @@
import { MapboxConfig, MapboxDefaultStyle, MapControlConfig } from './src/config';
import { MP } from './src/MP';
import { DrawingType } from '@/enums/mapEnum';
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4()
// map
interface MapboxOptionsInterface {
mapOptions: mapboxgl.MapboxOptions;
@ -39,7 +38,6 @@
return MapControlConfig[item];
})
: [];
console.log('nextMapControl::: ', nextMapControl);
//
let map: Map;
@ -66,7 +64,7 @@
//
const initMap = () => {
return new mapboxgl.Map({
container: `mapContainer-${id}`,
container: 'mapContainerComponent',
language: 'zh-cmn',
projection: 'equirectangular', // wgs84
style: MapboxDefaultStyle,

View File

@ -0,0 +1,11 @@
import WKT from "terraformer-wkt-parser"
const WktToGeojson = (wktData)=> {
return WKT.parse(wktData)
}
const GeojsonToWkt = (geojsonData)=> {
return WKT.convert(geojsonData)
}
export {WktToGeojson,GeojsonToWkt}

View File

@ -1,29 +1,108 @@
<template>
<div class="w-full" style="height: 100%">
<MapboxMaps
:mapOptions="mapOptions"
:control="mapDrawControl"
@map-on-load="mapOnLoad"
@map-draw="handlerMapDraw"
:layers="layers"
:location="location"
@handlerDrawComplete="handlerDrawComplete"
ref="MapboxComponent"
/>
<MapboxMap></MapboxMap>
</div>
</template>
<script lang="ts" setup>
import MapboxMaps from '@/components/MapboxMaps/MapboxMap.vue';
import MapboxMaps from '@/components/MapboxMaps/MapComponent.vue';
import {ref,reactive} from 'vue';
import { DrawingType } from '@/enums/mapEnum';
const mapOptions = {
center: [116.404, 39.905],
center: [118.556717,35.80391],
zoom: 8,
};
//
const layers = reactive([
{
id:1,
name:"沂水县道路中心线1",
checked:false,
layer:{
'id': 'roadnetLine1',
'type': 'line',
'source': {
type: 'vector',
tiles: [ 'http://192.168.10.102:9020/api/DroneCaseinfo/QueryVectorTileByTable?z={z}&x={x}&y={y}&table=yishuixian&X-Token=1ded3fe7'],
minzoom: 1,
maxzoom: 20
},
"source-layer": "yishuixian",
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': [
"case",
["==", ["get", "handle_status_id"], 0],
"#E6A23C",
["==", ["get", "handle_status_id"], 1],
"#409EFF",
["==", ["get", "handle_status_id"], 2],
"#67C23A",
//
"#67C23A",
],
'line-width': 1
}
}
}
])
//
const location = reactive([118.556717,35.80391])
//
const type = ref('add')
//
// const feature ="LINESTRING (118.55483239594203 35.81329409678203, 118.54889167836416 35.806406839795216, 118.55647247134772 35.80285975465173, 118.56157492816281 35.803303140294986)"
const feature = "POLYGON ((118.54774514802972 35.80786133598188, 118.54515277045988 35.79816597053564, 118.55919536113471 35.80085134034624, 118.56021460056033 35.80462789316549, 118.5595188628206 35.80695604583504, 118.5580066425723 35.80815336506183, 118.54774514802972 35.80786133598188))"
// geom
const handlerDrawComplete = (geom)=>{
console.log("绘制完成返回的图斑",geom);
}
//
const MapboxComponent = ref()
//
setTimeout(function(){
//
// MapboxComponent.value.handlerDraw()
//
MapboxComponent.value.handlerDraw(feature)
},3000)
//
setTimeout(function(){
MapboxComponent.value.handlerLocation([118.556717,35.80391]);
},6000)
const mapDrawControl: DrawingType[] = [DrawingType.Polygon, DrawingType.Line];
const mapOnLoad = (map) => {
//
// map
console.log('map::: ', map);
// mapU