前言-地图初始化
map.js 代码如下:
/*
* @Descripttion: 地图入口文件
* @version:
* @Author: WangMingJun
* @Date: 2023-08-04 09:11:44
* @LastEditors: WangMingJun
* @LastEditTime: 2023-08-05 10:46:31
*/
//id domid callback
export function createMap(id='map2d',callback){
/******************************** 参数定义开始 ********************************/
//定义配置对象
var Cfg = {}
//服务名称
Cfg.mapWMTS_Gauss_Name = 'Gauss WMTS'
//服务地址
// Cfg.mapWMTS_Gauss_Url = 'http://158.10.0.219/arcgis/rest/services/PT_07_HP/MapServer/WMTS'
//瓦片原点
Cfg.mapWMTS_Gauss_tileOrigin = '-66000.0,75000.0'
//服务版本
Cfg.mapWMTS_Gauss_Version = '1.0.0'
//图层标识
Cfg.mapWMTS_Gauss_LayerIdentifier = 'PT_07_HP'
//样式标识
Cfg.mapWMTS_Gauss_StyleIdentifier = 'default028mm'
//矩阵集名称
Cfg.mapWMTS_Gauss_MatrixSet = 'default028mm'
//比例尺
// Cfg.mapWMTS_Gauss_Scales =
// '967620.9828608917,483810.49143044587,241905.24571522293,120952.62285761147,60476.31142880573,30238.155714402867,15119.077857201433,7559.538928600717,3779.7694643003583,1889.8847321501792,944.9423660750896,472.4711830375448'
Cfg.mapWMTS_Gauss_Scales ='1024000,512000,256000,128000,64000,32000,16000,8000,4000,2000,1000,500'
//数据格式
Cfg.mapWMTS_Gauss_Format = 'image/png'
//图层范围 8156.459021,-2166.412666,-17658.940818,1847.769029
// Cfg.mapWMTS_Gauss_TileFullExtent = '-17658.968247100234,-2166.4719941083636,1847.8231668325498,8156.412449628424'
Cfg.mapWMTS_Gauss_TileFullExtent ='8156.459021,-2166.412666,-17658.940818,1847.769029'
//地图级别偏移量
Cfg.mapWMTS_Gauss_ZoomOffset = 0
//投影单位
Cfg.mapWMTS_Gauss_Uints = 'm'
//投影
Cfg.mapWMTS_Gauss_Projection = 'EPSG:3857'
/******************************** 参数定义结束 ********************************/
//图层的顶层级别
var scale = parseFloat(Cfg.mapWMTS_Gauss_Scales.split(',')[0])
//比例尺转分辨率
var resolution = GeoGlobe.Util.getResolutionFromScale(
scale,
Cfg.mapWMTS_Gauss_Uints
)
//最大分辨率
var maxResolution = resolution * Math.pow(2, Cfg.mapWMTS_Gauss_ZoomOffset)
//金字塔顶层左上角第一个瓦片的左上角X轴
const topTileFromX = parseFloat(Cfg.mapWMTS_Gauss_tileOrigin.split(',')[0])
//金字塔顶层左上角第一个瓦片的左上角Y轴
const topTileFromY = parseFloat(Cfg.mapWMTS_Gauss_tileOrigin.split(',')[1])
//金字塔顶层左上角第一个瓦片的右下角X轴
const topTileToX = topTileFromX + maxResolution * 512
//金字塔顶层左上角第一个瓦片的右下角Y轴
const topTileToY = topTileFromY - maxResolution * 512
var origin = Cfg.mapWMTS_Gauss_tileOrigin.split(',')
//高斯瓦片+高斯交互
var gauss_gauss_mapcrs = {
topTileExtent: [topTileFromX, topTileToY, topTileToX, topTileFromY],
coordtransform: 'none',
}
var extents = Cfg.mapWMTS_Gauss_TileFullExtent.split(',')
var x = parseFloat(extents[0]) + parseFloat(extents[2])
var y = parseFloat(extents[1]) + parseFloat(extents[3])
const map = new GeoGlobe.Map({
mapCRS: gauss_gauss_mapcrs,
container: 'map2d',
maxZoom: 19, // 最大缩放级别
minZoom: 4.2, // 最大缩放级别
zoom: Cfg.mapWMTS_Gauss_ZoomOffset,
// center: [x / 2, y / 2],
center:[-7331.732615831789, 1929.152198216229],
units: 'm',
renderWorldCopies: false, // 是否创建地图副本
isConstrain: true, // 设置地图是否在地图边界以内拖动 GeoGlobe
isIntScrollZoom: false, // 缩放级别是否为整数处理模式
preserveDrawingBuffer: true,//
// dragRotate:false,
})
window.map = map
map.on('load', () => {
loadLayer()
// const drawControl = new window.MapboxDraw({
// displayControlsDefault: false,
// controls: {},
// styles: [
// // ACTIVE (being drawn)
// // line stroke
// {
// 'id': 'gl-draw-line',
// 'type': 'line',
// 'filter': ['all', ['==', '$type', 'LineString'], ['!=', 'mode', 'static']],
// 'layout': {
// 'line-cap': 'round',
// 'line-join': 'round'
// },
// 'paint': {
// 'line-color': '#D20C0C',
// // "line-dasharray": [0.2, 2],
// 'line-width': 2
// }
// },
// // polygon fill
// {
// 'id': 'gl-draw-polygon-fill',
// 'type': 'fill',
// 'filter': ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
// 'paint': {
// 'fill-color': '#D20C0C',
// 'fill-outline-color': '#D20C0C',
// 'fill-opacity': 0.3
// }
// },
// // polygon mid points
// {
// 'id': 'gl-draw-polygon-midpoint',
// 'type': 'circle',
// 'filter': ['all',
// ['==', '$type', 'Point'],
// ['==', 'meta', 'midpoint']],
// 'paint': {
// 'circle-radius': 3,
// 'circle-color': '#fbb03b'
// }
// },
// // polygon outline stroke
// // This doesn't style the first edge of the polygon, which uses the line stroke styling instead
// {
// 'id': 'gl-draw-polygon-stroke-active',
// 'type': 'line',
// 'filter': ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
// 'layout': {
// 'line-cap': 'round',
// 'line-join': 'round'
// },
// 'paint': {
// 'line-color': '#D20C0C',
// // "line-dasharray": [0.2, 2],
// 'line-width': 4
// }
// },
// // vertex point halos
// {
// 'id': 'gl-draw-polygon-and-line-vertex-halo-active',
// 'type': 'circle',
// // "filter": ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["!=", "mode", "static"]],
// 'paint': {
// 'circle-radius': 5,
// 'circle-color': '#578EFE'
// }
// },
// // vertex points
// {
// 'id': 'gl-draw-polygon-and-line-vertex-active',
// 'type': 'circle',
// 'filter': ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static']],
// 'paint': {
// 'circle-radius': 7,
// 'circle-color': '#D20C0C',
// }
// },
// ]
// })
// map.$drawControl = drawControl
// map.addControl(drawControl) //标绘
// const MeasureControl = new GeoGlobe.Control.Measure({
// hasTools: false,
// })
// map.$MeasureControl = MeasureControl
// map.addControl(MeasureControl) //测量
addImage()
map.on('click', (evt)=>{
const zoom = map.getZoom()
let prePoint = map.getCenter()
if (evt && evt.type !== 'zoomend') {
prePoint = evt.lngLat
copyUrl(prePoint.lng, prePoint.lat)
callback&&callback({type:'mapClick',value:prePoint})
}
})
map.on('mousemove', logMapinfo)
map.on('zoomend', logMapinfo)
callback&&callback({type:'mapLoad'})
})
}
//获取层级
export function logMapinfo(evt) {
const zoom = map.getZoom()
let prePoint = map.getCenter()
if (evt && evt.type !== 'zoomend') {
prePoint = evt.lngLat
}
// this.$store.commit('setZindex', zoom)
// this.$store.commit('setJwd', { lon: prePoint.lng, lat: prePoint.lat })
}
//复制
export function copyUrl(lon, lat) {
// 模拟 输入框
if (process.env.NODE_ENV === 'development') {
var cInput = document.createElement('input')
cInput.value = lon + ',' + lat
document.body.appendChild(cInput)
cInput.select() // 选取文本框内容
// 执行浏览器复制命令
// 复制命令会将当前选中的内容复制到剪切板中(这里就是创建的input标签)
// Input要在正常的编辑状态下原生复制方法才会生效
document.execCommand('copy')
// 复制成功后再将构造的标签 移除
document.body.removeChild(cInput)
}
}
//加载pio 落点时需要
export function addImage() {
//参数:1.路径;2.是否遍历子目录;3.正则表达式
const files = require.context('@/assets/images', true, /\.*\.jpg|jpeg|png$/).keys()
const filelist = files.map(e => {
const temp = e.slice(2).split('.')
return {
name: temp[0],
gs: temp[1]
}
})
console.log('🚀 ~ file: Map2d.vue:283 ~ filelist ~ filelist', filelist)
filelist.forEach(e => {
map.loadImage(require(`@/assets/images/${e.name}.${e.gs}`), (error, image) => {
if (error) throw error
map.addImage(e.name, image)
})
})
}
//loadLayer加载图层
export function loadLayer(){
map.addLayer({
id: 'map-basic',
type: 'raster',
source: {
type: 'raster',
tiles: [
//暗色
// 'http://158.10.0.219/arcgis/rest/services/PT_07_JCSJ/MapServer/tile/{z}/{y}/{x}?blankTile=false&token=bEbVt7F7-cerWxeIDDwylopxIcrF3BcMafhAdzD9JYwSrR0oH2hU2q8nmOZ-K1SlwK3mO7MWGBZiIOIorqyN76GumXAria4Y8bHjy2rE6z8id2j7XqeHbj-fSZDIy0eI'
//亮色
// 'http://158.10.0.219/arcgis/rest/services/PT_07_White/MapServer/tile/{z}/{y}/{x}?blankTile=false&token=bEbVt7F7-cerWxeIDDwylopxIcrF3BcMafhAdzD9JYwSrR0oH2hU2q8nmOZ-K1SlwK3mO7MWGBZiIOIorqyN76GumXAria4Y8bHjy2rE6z8id2j7XqeHbj-fSZDIy0eI'
//影像图
`${app_config.yxtMap}token=${app_config.mapToken}`
],
maxzoom: 16,
tileSize: 512,
// zoomOffset:10,
}
})
//注记图层
map.addLayer({
id: 'map-basic-label',
type: 'raster',
source: {
type: 'raster',
tiles: [
`${app_config.yxtLabelMap}token=${app_config.mapToken}`
],
minzoom: 5,
maxzoom: 16,
tileSize: 512,
// zoomOffset:10,
}
})
}
使用方法
<template>
<div id="map2d"></div>
</template>
<script>
import { mapState } from 'vuex'
import {
setLayer,
setLayerVisible,
setHightLightLayerVisible,
setLineLayerAndData,
setFillLayerAndData,
setTextLayerAndData
} from '@/map2d/symbol'
import { createMap } from '@/map2d/map'
// import layerClickEvents2d from "@/map2d/layerClick2d";
// import mapboxgl from '@cgcs2000/mapbox-gl'
// mapboxgl.accessToken = 'pk.eyJ1Ijoic2FudG9yaW5penp6IiwiYSI6ImNqcWxwdDdsbDAwMHE0OHBpZmR1ZHJiYzQifQ.zz3lWDejAMyHwvsEQ0V4zw'
export default {
name: 'Map2d',
computed: {
...mapState(['isPoint']),
},
mounted() {
this.init()
},
methods: {
init() {
createMap('map2d', (e) => {//回调
if (e.type == 'mapLoad') {
//画点
// setLayer([
// { lon: -7248.463154571035, lat: 1771.4616940348967, imageName: '楼宇', },
// { lon: -7248.463154571035, lat: 1871.4616940348967, imageName: 'red_2', },
// ], { id: 'test', iconSize: 1, located: true }, (e) => {
// console.log('🚀 ~ file: Map2d.vue:437 ~ addImage ~ e:', e)
// })
}
if (e.type == 'mapClick') {
let res = e.value
console.log(res.lng, res.lat)
this.isPoint && this.$emit('pointClick', { x: res.lng, y: res.lat })
// setLayerVisible({layName:'test',show:false})
// setHightLightLayerVisible({list:{lon:res.lng,lat:res.lat}},(e) => {
// console.log("🚀 ~ file: Map2d.vue:40 ~ setHightLightLayerVisible ~ e:", e)
// })
//画线
// let arr = [{
// type: 'Feature',
// geometry: {
// "type": "LineString",
// "coordinates": [
// [-7470.56215241897, 1826.5272490861244],
// [-7314.746004220826, 1806.067982015753],
// [-7202.663154570902, 1771.2616940344014],
// [-7193.234565362647,1812.561690976887],
// [-7470.56215241897, 1826.5272490861244],
// ]
// },
// properties: { name: '24234', type: '测试划线' },
// }]
// setLineLayerAndData(arr, { lineColor: 'blue' }, (e) => {
// console.log("🚀 ~ file: Map2d.vue:59 ~ setLineLayerAndData ~ e:", e)
// })
//画面
// let arr1 = [
// {
// "type": "Feature",
// "properties": { name: '测试画面' ,fillColor: 'red',},
// "geometry": {
// "type": "Polygon",
// "coordinates": [
// [
// [-7470.56215241897, 1826.5272490861244],
// [-7314.746004220826, 1806.067982015753],
// [-7202.663154570902, 1771.2616940344014],
// [-7193.234565362647,1812.561690976887]
// ],
// ]
// }
// }
// ]
// setFillLayerAndData(arr1, { lineColor: 'red',located:true }, (e) => {
// console.log("🚀 ~ file: Map2d.vue:59 ~ setFillLayerAndData ~ e:", e)
// })
//画文字
// let arr2 =[
// {
// type: 'Feature',
// geometry: {
// type: 'Point',
// coordinates: [-7148.463154571204,1831.4616940344422]
// },
// properties: {name:'测试'}
// },
// ]
// setTextLayerAndData(arr2,{textSize:20},(e)=>{
// console.log(1);
// })
}
})
},
},
}
</script>
<style scoped lang="scss">
#map2d {
height: 100%;
width: 100%;
background-color: #f5f4ee;
}
</style>
画点、线、面、文字的相关方法
/*
* @Descripttion:
* @version:
* @Author: WangMingJun
* @Date: 2023-02-07 10:38:43
* @LastEditors: WangMingJun
* @LastEditTime: 2023-08-07 21:13:13
*/
/**
* @Author zhoucw
* @Date 2022/6/20
* @Description
*/
import layerClick2d from '@/map2d/layerClick2d'
//加载图层
/*
使用示例
setLayer([
{lon:-26.9875715328385,lat:-8.426351109196744, imageName: 'poi-marker_1',},
{lon:-26.9875715328385,lat:-9.426351109196744, imageName: 'poi-marker_2',}
], { id: 'test', iconSize: 1},(e) => {
console.log('🚀 ~ file: Map2d.vue:437 ~ addImage ~ e:', e)
})
*/
export function setLayer(list, option = {}, callback) {
const {
id, //图层名简称
iconImage = 'imageName', //图标字段名 list数据里要有这个字段
iconfs = true, //是否取本地加载的图标 是则需要执行addImage() 否则需要加载雪碧图
iconSize = 1,//图标大小
textField = 'name',//取数据中的文字的字段名
textSize = 14, //文字大小
textColor = '#fff', //文字颜色
located = false, //是否定位
iconIgnorePlacement = true,
iconAllowOverlap = true,
visible = 'visible',
textHaloColor,//文字外边颜色
click //点击事件名
} = option
add2DPoint(list, { id, iconImage, iconfs, iconSize, textField, textSize, textColor,textHaloColor, located, iconIgnorePlacement, iconAllowOverlap, visible })
map.on('click', `${id}-layer`, (e) => {
const properties = e.features[0].properties
callback && callback(properties)
click && layerClick2d[click] && layerClick2d[click](properties)
})
}
//添加点图层及设置数据
export function add2DPoint(data, options) {
const {
id,
iconImage = 'zdgzry-1',
iconfs = true,
iconSize = 1,
textField = 'name',
textSize = 12,
located = false,
iconIgnorePlacement = true,
iconAllowOverlap = true,
textColor = '#fff',
textHaloColor,
visible = 'visible'
} = options
let obj ={}
if(textHaloColor){
obj={
'text-halo-color': textHaloColor || '#fff',
'text-halo-width': 1,
}
}
const features = getPointFeatures(data, options)
if (map.getSource(`${id}-source`)) {
map.getSource(`${id}-source`).setData({
type: 'FeatureCollection',
features
})
} else {
map.addSource(`${id}-source`, {
type: 'geojson',
data: {
type: 'FeatureCollection',
features
}
})
map.addLayer({
id: `${id}-layer`,
type: 'symbol',
source: `${id}-source`,
layout: {
// 'icon-image': ['get', iconImage],
'icon-image': iconfs ? ['get', iconImage] : iconImage,
'icon-size': iconSize,
// {
// base: iconSize ,
// // stops: [
// // [6, iconSize+0.1 ],
// // [7, iconSize+0.2 ],
// // [8, iconSize+0.3],
// // [9, iconSize +0.4],
// // [10, iconSize +0.5]
// // ]
// },
'text-field': ['get', textField],
'text-size': textSize,
'icon-allow-overlap': iconAllowOverlap,
'icon-ignore-placement': iconIgnorePlacement,
'visibility': visible,
'text-offset': [0, 1.8],
},
paint: {
'text-color': textColor || '#568CFE',
...obj
},
})
}
if (located) {
const bbox = turf.bbox({
type: 'FeatureCollection',
features
})
map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {
padding: {
top: 50,
bottom: 250,
left: 450,
right: 450
},
maxZoom: 10
})
}
}
//设置点图层数据
export function setPointLayerData(id, data, options = {}) {
const features = getPointFeatures(data, options)
map.getSource(id + '-source').setData({
type: 'FeatureCollection',
features
})
if (options.located) {
const bbox = turf.bbox({
type: 'FeatureCollection',
features
})
map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {
padding: {
top: 50,
bottom: 250,
left: 550,
right: 500
},
maxZoom: 17
})
}
}
export function getPointFeatures(data, options) {
const { lonField = 'lon', latField = 'lat' } = options
return data.map(item => {
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [Number(item[lonField]), Number(item[latField]), 20]
},
properties: item
}
})
}
//显隐图层
export function setLayerVisible(params) {
const { layName = "point", show = true } = params
map.getLayer(layName + '-layer') && map.setLayoutProperty(layName + '-layer', 'visibility', show ? 'visible' : 'none')
}
//设置高亮点以及其相关显隐
export function setHightLightLayerVisible(params, callback) {
const {
list = { lon: -7248.463154571035, lat: 1771.4616940348967 }, //数据
imageName = 'blue_1', //图标名
layName = "hightLight", //图层民
show = true, //是否显隐
} = params
setLayer([
{ ...list, imageName: imageName }
], { id: layName, iconSize: 1, ...params }, (e) => {
callback && callback(e)
})
map.getLayer(layName + '-layer') && map.setLayoutProperty(layName + '-layer', 'visibility', show ? 'visible' : 'none')
}
//设置文字图层及数据
export function setTextLayerAndData(data, options, callback) {
const {
id = 'text',
iconSize = 0.1,
textField = 'name',
textSize = 14,
textColor = '#568CFE',
textHaloColor = '#fff',
located = false,
iconIgnorePlacement = true,
iconAllowOverlap = true,
visible = 'visible',
click
} = options
if (map.getSource(`${id}-source`)) {
map.getSource(`${id}-source`).setData({
type: 'FeatureCollection',
features:data
})
} else {
map.addSource(`${id}-source`, {
type: 'geojson',
data: {
type: 'FeatureCollection',
features:data
}
})
map.addLayer({
id: `${id}-layer`,
type: 'symbol',
source: `${id}-source`,
layout: {
'icon-image': 'circle',
'icon-size': iconSize,
'text-field': ['get', textField],
'text-size': textSize,
'icon-allow-overlap': iconAllowOverlap,
'icon-ignore-placement': iconIgnorePlacement,
'visibility': visible,
'text-offset': [0, 0],
},
paint: {
// 'text-color': '#9E9E9E',
'text-color': textColor || '#568CFE',
'text-halo-color': textHaloColor || '#fff',
'text-halo-width': 1,
},
})
map.on('click', `${id}-layer`, (e) => {
const properties = e.features[0].properties
callback && callback(properties)
})
}
if (located) {
const bbox = turf.bbox({
type: 'FeatureCollection',
features: data
})
map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {
padding: {
top: 50,
bottom: 250,
left: 450,
right: 450
},
maxZoom: 17
})
}
}
//设置面图层及数据
export function setFillLayerAndData(data, options, callback) {
const {
id = 'fill',
fillColorName = 'fillColor',
fillOpacity = 0.5,
visible = 'visible',
located = false,
fillColor,
click
} = options
if (map.getSource(`${id}-source`)) {
map.getSource(`${id}-source`).setData({
type: 'FeatureCollection',
features:data
})
} else {
map.addSource(`${id}-source`, {
type: 'geojson',
data: {
type: 'FeatureCollection',
features:data
}
})
map.addLayer({
id: `${id}-layer`,
type: 'fill',
source: `${id}-source`,
layout: {
'visibility': visible,
},
paint: {
'fill-color': fillColor|| ['get', fillColorName],
'fill-opacity': fillOpacity
},
})
map.on('click', `${id}-layer`, (e) => {
const properties = e.features[0].properties
callback && callback(properties)
})
}
if (located) {
const bbox = turf.bbox({
type: 'FeatureCollection',
features:data
})
map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {
padding: {
top: 50,
bottom: 250,
left: 450,
right: 450
},
maxZoom: 17
})
}
}
//设置线图层及数据
//data
//[{
// type: 'Feature',
// geometry: {
// "type": "LineString",
// "coordinates": [[ -7248.463154571035, 1771.4616940348967], [-7248.463154571035, 1871.4616940348967]]
// },
// properties: { name: '24234', type: '测试' },
// }]
export function setLineLayerAndData(data, options, callback) {
const {
id = 'line',
lineWidth = 2,
lineColor = '#66BB6A',
visible = 'visible',
click
} = options
if (map.getSource(`${id}-source`)) {
map.getSource(`${id}-source`).setData({
type: 'FeatureCollection',
features:data
})
} else {
map.addSource(`${id}-source`, {
type: 'geojson',
data: {
type: 'FeatureCollection',
features:data
}
})
map.addLayer({
id: `${id}-layer`,
type: 'line',
source: `${id}-source`,
layout: {
'visibility': visible,
},
paint: {
'line-width': lineWidth,
'line-color': lineColor,
},
})
map.on('style.load',e=>{
})
map.on('click', `${id}-layer`, (e) => {
const properties = e.features[0].properties
callback && callback(properties)
})
}
}
//获取面的中心点
// list:[
// [1,1],
// [1,1]
// ]
export function getFillCenter(list){
let arr = list.map(e => {
return turf.point(e)
})
return turf.center(turf.featureCollection(arr))
}
//关闭图层及数据源
落点点击事件
layerClick2d.js
import VideoPopup from '@/map2d/popup/VideoPopup' //自定义组件
import Vue from 'vue'
import router from '@/router'
import store from '@/store'
let popup = null
//单纯点击事件
export function clickZdcs(row){
store.commit('setZdcsInfo', row)
}
//需要加气泡
function clickZdqy(row) {
const zdqyPopup = Vue.extend(ZdqyPopup)
removePopup()
const vm = new zdqyPopup({
propsData: {row},
store,
router
})
vm.$mount()
popup = new GeoGlobe.Popup().setLngLat([row.lon, row.lat]).setDOMContent(vm.$el).addTo(map)
}
function removePopup() {
popup && popup.remove()
popup = null
}
const layerClickEvents2d = {
removePopup,
clickZdqy
}
export default layerClickEvents2d