自定义图标
js
复制代码
// 1、单个图标
const url = './static/assets/symbols/code24x24/VIDEO.png' // 图标路径
map.loadImage(url ,(error, image) => {
if (error) throw error
map.addImage('video-icon', image)
})
// 2、雪碧图利用canvas
// json和png图片
function getStyleImage(fileName: any) {
return new URL('/json/style/' + fileName + '.png', import.meta.url).href;
}
fetch(new URL('/json/style/' + fileName + '.json', import.meta.url).href)
.then(response => response.json())
.then(spriteJson => {
var img = new Image()
img.crossOrigin = 'anonymous'
img.src = getStyleImage(spriteName)
img.onload = function () {
Object.keys(spriteJson).forEach((key: any) => {
let spriteItem = spriteJson[key]
let { X, Y, Width, Height } = spriteItem
let canvas = createCavans(Width, Height)
let context: any = canvas.getContext('2d') || ''
context.drawImage(img, X, Y, Width, Height, 0, 0, Width, Height)
// 单位雪碧图项,转base64字符串
map.addImage(key, canvas.toDataURL('image/png'))
})
console.log(spriteName, '完成加载...')
}
});
vue2.0中自定义弹窗(核心代码)
样式文件
css
复制代码
// 地图弹窗
.mapbox-msgBox {
position: relative;
border: 0;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
// 弹窗内容
.mapboxgl-popup-content {
padding: 0 !important;
}
// 弹窗标题
h2 {
width: 100%;
height: 40px !important;
line-height: 40px !important;
font-size: 18px !important;
color: #fff;
background: #0057a7;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0 15px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
// 关闭按钮
.mapboxgl-popup-close-button {
height: 40px;
font-size: 3em;
padding: 0 5px;
color: white;
cursor: pointer;
&:hover {
color: #aaaaaa;
}
}
}
vue文件
vue
复制代码
<template>
<div>
<h2>{{ title }}</h2>
</div>
</template>
<script>
export default {
name: 'popTemplate',
components: {},
props: ['attrs', 'title'],
data() {
return {}
},
mounted() {
console.log('props:', this.attrs)
},
methods: {
callback(attrs) {
this.$emit('callback', attrs)
}
}
</script>
实现代码
javascript
复制代码
const location = [110,30]
// 初始化弹窗
const mapboxPopup = new mapboxgl.Popup({
closeButton: true,
closeOnClick: false,
className: 'mapbox-msgBox',
maxWidth: '450px',
offset: [0, 0]
})
// popTemplate为引用的vue文件
const popDetail = Vue.extend(popTemplate)
const vm = new popDetail({
propsData: {
title,
attrs
},
methods: {
callback(config) {
console.log('🚀 ~ callback ~ config:', config)
}
}
})
vm.$mount() // 挂载
mapboxPopupLayer
.setLngLat(location)
.setDOMContent(vm.$el)
.addTo(map)
创建自定义标签(核心代码)
定义样式为扩散圆
css
复制代码
/* 标签选择器之属性匹配选择 */
.mapbox-marker span[class^='pulse'] {
/* 保证小盒子水平垂直居中 */
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
box-shadow: 0 0 5px #ff0000;
border-radius: 50%;
animation: pulse 3s linear infinite;
}
.mapbox-marker .pulse1 {
animation-delay: 0s !important;
}
.mapbox-marker .pulse2 {
animation-delay: 1s !important;
}
.mapbox-marker .pulse3 {
animation-delay: 2s !important;
}
@keyframes pulse {
0% {
width: 8px;
height: 8px;
}
40% {
width: 40px;
height: 40px;
opamapbox-marker: 1;
}
100% {
width: 70px;
height: 70px;
opamapbox-marker: 0;
}
}
实现代码
js
复制代码
// 创建一个新的标记并添加到地图上
const location = [110,30]
const el = document.createElement('div')
el.className = 'mapbox-marker'
const el1 = document.createElement('span')
el1.className = 'pulse1'
el.appendChild(el1)
const el2 = document.createElement('span')
el2.className = 'pulse2'
el1.appendChild(el2)
const el3 = document.createElement('span')
el3.className = 'pulse3'
el1.appendChild(el3)
const currentMarker = new mapboxgl.Marker(el).setLngLat(location).addTo(map)
map.setCenter(location)
// 实现扩散效果(例如放大到特定区域)
map.flyTo({
center: location,
zoom: 18,
speed: 1, // 动画速度
curve: 1, // 动画曲线类型
easing: function (t) {
return t
} // 动画缓动函数
})
// 5s之后移除
setTimeout(() => {
// 如果已存在标记,则移除它
if (currentMarker) {
currentMarker.remove()
}
}, 5000)
聚合图层
bash
复制代码
// 添加数据源
map.addSource('videoLayer', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: videoListFeatures
},
cluster: true,
clusterMaxZoom: 14, // 最大缩放级别,超过该级别不再聚合
clusterRadius: 50 // 聚合半径,单位为像素
})
// 添加聚合图层
map.addLayer({
id: 'videoLayer-cluster',
type: 'circle',
source: 'videoLayer',
filter: ['has', 'point_count'],
paint: {
'circle-color': [
'step',
['get', 'point_count'],
'#51bbd6',
100,
'#f1f075',
750,
'#f28cb1'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
})
// 添加聚合点计数图层
map.addLayer({
id: 'videoLayer-cluster-count',
type: 'symbol',
source: 'videoLayer',
filter: ['has', 'point_count'],
layout: {
'text-field': ['get', 'point_count_abbreviated'],
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
'text-size': 12
}
})
// 添加非聚合点图层
map.addLayer({
id: 'videoLayer-unclustered-point',
source: 'videoLayer',
filter: ['!', ['has', 'point_count']],
type: 'symbol',
layout: {
'icon-image': 'video-icon',
'icon-size': 1
}
})
分类渲染降雨等值面事例
js
复制代码
map.addLayer({
id: 'grid_line',
type: 'fill',
source: {
type: 'geojson',
data: { type: 'FeatureCollection', features }
},
paint: {
'fill-opacity': 1,
'fill-outline-color': 'rgba(255, 255, 255, 0)',
'fill-color': [
'step',
['get', 'rain'],
'rgba(255, 255, 255, 0)', // 无降雨
0.000001,
'rgb(165, 243, 141)', // 短时小雨
0.25,
'rgb(61, 185, 63)', // 短时中雨
0.5,
'rgb(99, 184, 249)', // 短时大雨
1,
'rgb(0, 0, 254)', // 短时暴雨
2.5,
'rgb(243, 5, 238)', // 短时大暴雨
7.5,
'rgb(129, 0, 64)' // 短时特大暴雨
]
}
})