当前位置: 首页 > news >正文

mapbox开发小技巧

自定义图标

// 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中自定义弹窗(核心代码)

样式文件

// 地图弹窗
.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文件

<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>

实现代码

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)

创建自定义标签(核心代码)

定义样式为扩散圆

/* 标签选择器之属性匹配选择 */
.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;
  }
}

实现代码

 // 创建一个新的标记并添加到地图上
 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)

聚合图层

// 添加数据源
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
  }
})

分类渲染降雨等值面事例

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)' // 短时特大暴雨
    ]
  }
})

相关文章:

  • 【简单的c程序设计精选题】
  • 《几何原本》命题I.22
  • 最大连续1的个数III --- 滑动窗口
  • VBA 数据库同一表的当前行与其他行的主键重复判断实现方案
  • Docker 安装 Nacos 2.1.1(单机版)
  • Ubuntu下MySQL的安装与使用(一)
  • 新手学习爬虫的案例
  • LLM时代的小模型思考:《What is the Role of Small Models in the LLM Era: A Survey》论文笔记
  • yolov7-3d算法原理
  • Git与GitHub:理解两者差异及其关系
  • 题海拾贝:P9241 [蓝桥杯 2023 省 B] 飞机降落
  • 初识脑机接口情绪识别
  • Express 中 get 参数获取
  • 51 单片机中断控制寄存器 TCON
  • Python爬虫:爬虫基础知识
  • 解决电脑问题(2)——主板问题
  • MySQL面试篇——性能优化
  • 微分方程家族:常微分方程(ODE)、偏微分方程(PDE)和随机微分方程(SDE)
  • Redis-主从架构
  • SQL SELECT DISTINCT 语句
  • 适合手机的网站/推广宣传
  • 注册网站费属于什么费用/网站seo推广平台
  • 丫个网站建设/青岛网站建设策划
  • 做自己的网站如何赚钱的/国际新闻最新消息美国
  • 工商注册名字查重/优化搜索引擎的方法
  • 网站策划书哪个容易做/三只松鼠软文范例500字