mapbox开发小技巧

自定义图标

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)' // 短时特大暴雨
    ]
  }
})
相关推荐
发呆小天才yy1 小时前
uniapp 微信小程序使用图表
前端·微信小程序·uni-app·echarts
@PHARAOH3 小时前
HOW - 在 Mac 上的 Chrome 浏览器中调试 Windows 场景下的前端页面
前端·chrome·macos
月月大王4 小时前
easyexcel导出动态写入标题和数据
java·服务器·前端
JC_You_Know5 小时前
多语言网站的 UX 陷阱与国际化实践陷阱清单
前端·ux
Python智慧行囊5 小时前
前端三大件---CSS
前端·css
Jinuss6 小时前
源码分析之Leaflet中Marker
前端·leaflet
成都渲染101云渲染66666 小时前
blender云渲染指南2025版
前端·javascript·网络·blender·maya
聆听+自律6 小时前
css实现渐变色圆角边框,背景色自定义
前端·javascript·css
牛马程序小猿猴7 小时前
17.thinkphp的分页功能
前端·数据库
huohuopro7 小时前
Vue3快速入门/Vue3基础速通
前端·javascript·vue.js·前端框架