一、添加数据源
添加数据源
// addSource.js
import { geoUrl } from '@/fetch/env'
// 添加mapbox source
export default function addSource(map, source = []) {
for (const name of source) {
if (name) {
map.addSource(name, {
type: 'vector',
scheme: 'tms',
tiles: [`${geoUrl}/geoserver/gwc/service/tms/1.0.0/linanAI%3A${name}@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf`],
})
}
}
}
// 页面引入后使用方法
this.fileUrlArr = [leizhuShpUrl, riceShpUrl] // 此处为数据源地址数组
// 添加对应的数据源和突出
await addSource(this.mapboxInstance, [...this.fileUrlArr])
二、增
默认添加 symbol(符号),line(线),fill(填充),background(背景),raster(栅格)
点图层—> icon图标、文字
export default async function addBaseLayer(map) {
const imageList = [
{
url: require('@/assets/images/common/base_icon.png'),
usedName: 'base-marker',
},
]
for (const item of imageList) {
await new Promise((resolve, reject) => {
const existImage = map.hasImage(item.usedName)
if (existImage) resolve()
else {
map.loadImage(item.url, function (error, image) {
if (error) {
reject()
}
map.addImage(item.usedName, image)
resolve()
})
}
})
}
await map.addLayer({
id: `base-layer`,
source: `base`, // 数据源的名称
'source-layer': `base`, // 数据源的图层
type: 'symbol',
filter: true,
layout: {
// 图标类属性
'icon-image': `base-marker`, // 图标的图片名称
'icon-size': 0.8, //
'icon-allow-overlap': true, // 是否允许图标重叠
"icon-offset": [0, 0], // 图标的偏移量(可选,默认值为 [0, 0])
// 文本类属性
"text-field": "", // 文本所对应的字段
"text-size": 16, // 文本的大小(默认值为 16,单位:像素)
"text-max-width": 10, // 文本的最大宽度,超过则折行(可选,默认值为 10,单位:ems)
"text-line-height": 1.2, // 文本的行高(默认值为 1.2,单位:ems)
"text-letter-spacing": 0, // 文本的字符间距(默认值为 0,单位:ems)
"text-justify": "center", // 文本的水平对齐方式(可选值为 auto、left、center、right。默认值为 center)
"text-rotate": 0, // 文本的顺时针旋转角度
"text-padding": 2, // 文本的外边距
"text-offset": [0, 0], // 文本的偏移量
},
paint: {
// 图标类属性(需要设置 icon-image)
"icon-opacity": 1, // 图标的不透明度
"icon-halo-color": "rgba(0,0,0,0)", // 图标的光晕颜色
"icon-halo-width": 0, // 图标的光晕宽度
"icon-halo-blur": 0, // 图标的光晕模糊宽度
"icon-translate": [0, 0], // 图标的平移
"icon-translate-anchor": "map", // 图标的平移锚点,即相对的参考物(可选值为 map、viewport,默认为 map)
// 文本类属性(需要设置 text-field)
"text-opacity": 1, // 文本的不透明度
"text-color": "#000000", // 文本的颜色
"text-halo-color": "rgba(0,0,0,0)", // 文本的光晕颜色
"text-halo-width": 0, // 文本的光晕宽度
"text-halo-blur": 0, // 文本的光晕模糊宽度
"text-translate": [0, 0], // 文本的平移
"text-translate-anchor": "map", // 文本的平移锚点,即相对的参考物(可选值为 map、viewport,默认为 map)
},
})
}
线图层
// 添加线 addLinanLayer.js
// 添加临安图层
export default function addLinanLayer(map) {
return new Promise(async (resolve, reject) => {
try {
// 添加临安边界
await map.addLayer({
id: 'linan_boundary-layer', // 唯一 图层id
source: 'region_linan', // 数据源的名称
'source-layer': 'region_linan', // 数据源的图层
type: 'line', // 类型
layout: { // // 布局类属性
'line-cap': 'round',
'line-join': 'round',
},
paint: { // 绘制类属性
'line-color': borderColor,
'line-width': 2,
},
})
resolve()
} catch (err) {
reject(err)
}
})
}
面:shp图层 (矢量图)
// 添加竹图斑图层
export default function addLinanLayer(map) {
return new Promise(async (resolve, reject) => {
try {
// 添加竹图斑
await map.addLayer({
id: 'plant1_spot-layer', // 唯一 图层id
source: 'bamboo_maozhu_plant_spot', // 数据源的名称
'source-layer': 'bamboo_maozhu_plant_spot', // 数据源的图层
type: 'fill', // 类型
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
layout: { // // 布局类属性
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
},
paint: { // 绘制类属性
"fill-opacity": 1, // 填充的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
"fill-color": "#000000", // 填充的颜色
"fill-outline-color": "#000000", // 描边的颜色
"fill-translate": [0, 0], // 填充的平移
},
})
resolve()
} catch (err) {
reject(err)
}
})
}
面:tif图层(png图片)
import { geoUrl } from '@/fetch/env'
// 加载tif图
export default function addTifLayer(map, sourceTifList, isHide = false) {
return new Promise(async (resolve, reject) => {
try {
for (const tifName of sourceTifList) {
if (tifName) {
map.addLayer({
id: tifName,
type: 'raster', //这里要用raster ,因为切片得到的是图片
source: {
type: 'raster', //切片地图使用png 所以这里设置为raster
tiles: [
`${geoUrl}/geoserver/gwc/service/wmts?SERVICE=WMTS&REQUEST=GetTile&LAYER=linanAI:${tifName}&TILEMATRIX=EPSG:900913:{z}&TILEMATRIXSET=EPSG:900913&format=image%2Fpng&TileCol={x}&TileRow={y}`,
],
},
"source-layer":'source-layer-name',
tileSize: 256,
// minzoom: 15.5,
"paint": { // 绘制类属性
"raster-opacity": 1, // 图片的不透明度
}
})
}
}
resolve()
} catch (err) {
reject(err)
}
})
}
三、删
// 删除图层+删除数据源
this.mapboxInstance.removeLayer(`图层id`)
this.mapboxInstance.removeSource(`图层id`)
// 不删除图层 仅隐藏
this.mapboxInstance.setFilter(`图层id`, false)
// 显示图层
this.mapboxInstance.setFilter(`图层id`, true)
四、改
// 移动图层位置
this.mapboxInstance.moveLayer(`图层id`, `beforeId`)
// beforeId(string?)用来插入新图层的现有图层 ID。
// 如果该参数(argument)被省略,该图层将会被添加到图层最上层。
五、查/过滤
// A & B & C
filter: [
'all',
['match', ['get', 'code'], A, ['match', ['get', 'taski_id'], B, ['match', ['get', 'id'], C, true, false], false], false],
],
// A || B || C
filter: [
'all',
['any', [
['match', ['get', 'type'], A, true, false],
['match', ['get', 'type'], B, true, false],
['match', ['get', 'type'], C, true, false]
]
],
],
六、事件
// 初始化绑定对应事件
async initMapbox(map) {
// 存储 mapbox 地图实例
this.mapboxInstance = map
// 添加数据源
// 添加图层
this.bindClickEvent(this.mapboxInstance)
},
// 地图绑定点击事件
bindClickEvent(map) {
map.on('click', '图层id', async (e) => {
e.preventDefault()
let properties = e.features[0].properties
// 此处可拿到点击后的图层信息
console.log('properties: ', properties)
const lonAndLat = [Number(properties.longitude), Number(properties.latitude)]
let popup = new mapboxgl.Popup({
className: 'popup',
closeOnClick: true,
})
popup.setLngLat(lonAndLat).setHTML('<div id="dialog-moadl"></div>').addTo(this.mapboxInstance)
// PointDetailModal 为自定义的弹窗组件
const MapInsectWarnModal = Vue.extend(PointDetailModal)
new MapInsectWarnModal({
propsData: {
detail: properties,
},
}).$mount('#dialog-moadl')
let closeBtn = document.getElementsByClassName('close-icon')[0]
closeBtn.addEventListener('click', () => {
popup.remove()
})
})
},
// 清除默认弹窗样式
::v-deep .mapboxgl-popup {
z-index: 99;
.mapboxgl-popup-tip {
display: none;
}
.mapboxgl-popup-content {
background: none;
padding: 0;
}
.mapboxgl-popup-close-button {
display: none;
}
}
// PointDetailModal 组件
<template>
<div class="point-detail-modal">
<div class="close-icon"></div>
<div class="box">
<!-- 弹窗基本内容 -->
</div>
</div>
</template>
<script>
export default {
props: {
detail: {
required: true,
},
},
}
</script>