Skip to content
目录

Vue2中mapbox常用方法封装

获取行政区划边界

js
 // 获取区划边界
    // addLayer 是否需要添加边界图层
    async getBounds(region = { standardCode: '', level: 0 }, addLayer = true) {
      try {
        if (region.level === true) {
          return
        }
        const res = await axios.get(
          `https://geoserver-xxxxxxx.cn/geoserver/wg/ows?service=WFS&version=1.0.0&request=GetFeature&typename=wg:bd_bounds&srsname=EPSG:4326&maxFeatures=2000&outputFormat=application/json&CQL_FILTER=adcode like '${region.standardCode}${encodeURIComponent('%')}' and level in (${region.level},${region.level + 1})`
        )
        if (res.data.features.length) {
          if (addLayer) {
            // 注意:先添加面 在添加边界
            this.addPolygonLayer(
              'regionFill',
              res.data,
              {
                'fill-color': '#fff',
                'fill-opacity': 0.2
              }
            )
            this.addLineLayer(
              'regionBorder',
              res.data,
              {
                'line-color': '#eb6100',
                'line-width': 2.2
              }
            )
          }
          this.setZoom(res.data, { left: -20, right: 20, top: 20, bottom: 20 })
          return res.data
        } else if (region.parentCode) {
          await this.getBounds({ standardCode: region.parentCode, level: region.level - 1 })
        } else {
          Notification.error({
            title: '提示',
            message: '未查询到该地区的边界数据'
          })
        }
      } catch (err) {
        console.log('🚀 ~ [err]', err)
        Notification.error({
          title: '查询失败',
          message: err.message
        })
      }
    },

区域面积自适应视口

js
    // 区域面积自适应视口
    setZoom(bboxData, padding = 20 || {}) {
      if (!bboxData) return
      const bboxFeature = Array.isArray(bboxData) ? bboxData : bbox(bboxData)
      this.map.fitBounds(bboxFeature, { padding })
    },

添加图标点图层

js
    // 添加图标点图层
    addMarkerLayer(id, geojson, iconUrl, iconSize = 1.0, paint = {}, animation = true) {
      // 移除同名图层
      if (this.map.getLayer(id)) {
        this.map.removeLayer(id)
      }

      // 添加或更新数据源
      const source = this.map.getSource(id)
      if (source) {
        source.setData(geojson)
      } else {
        this.map.addSource(id, { type: 'geojson', data: geojson })
      }

      // 统一的图层添加逻辑
      const addLayer = () => {
        this.map.addLayer({
          id,
          type: 'symbol',
          source: id,
          layout: {
            'icon-image': Array.isArray(iconUrl) ? ['get', iconUrl[1]] : iconUrl,
            'icon-size': iconSize,
            'icon-anchor': 'bottom',
            'icon-ignore-placement': true,
            'icon-allow-overlap': true,
            'symbol-sort-key': ['get', 'priority']
          },
          paint
        })
      }

      // 如果是使用表达式,先预加载所有图标
      if (Array.isArray(iconUrl)) {
        // 获取所有不同的图标URL
        const iconUrls = new Set()
        geojson.features.forEach(feature => {
          if (feature.properties?.icon) {
            iconUrls.add(feature.properties.icon)
          }
        })

        // 预加载所有图标
        Promise.all([...iconUrls].map(url =>
          new Promise(resolve => {
            if (this.map.hasImage(url)) {
              resolve()
              return
            }
            this.map.loadImage(url, (error, image) => {
              if (error) {
                console.warn(`Failed to load image: ${url}`, error)
                resolve()
                return
              }
              this.map.addImage(url, image, { sdf: false })
              resolve()
            })
          })
        )).then(() => {
          addLayer()
        })
      } else {
        // 单一图标的处理逻辑
        if (this.map.hasImage(iconUrl)) {
          addLayer()
        } else {
          this.map.loadImage(iconUrl, (error, image) => {
            if (error) return console.warn(`Failed to load image: ${iconUrl}`, error)
            this.map.addImage(iconUrl, image, { sdf: false })
            addLayer()
          })
        }
      }
    },

添加区划面图层

js
    addPolygonLayer(id, geojson, paint = {}) {
      // 移除同名图层
      if (this.map.getLayer(id)) {
        this.map.removeLayer(id)
      }
      // 添加或更新数据源
      const source = this.map.getSource(id)
      if (source) {
        source.setData(geojson)
      } else {
        this.map.addSource(id, { type: 'geojson', data: geojson })
      }
      // 添加填充图层
      this.map.addLayer({
        id,
        type: 'fill',
        source: id,
        paint
      })
    },

添加线图层

js
    addLineLayer(id, geojson, paint = {}) {
      // 先移除之前的同名图层
      if (this.map.getLayer(id)) {
        this.map.removeLayer(id)
      }
      // 添加或更新数据源
      const source = this.map.getSource(id)
      if (source) {
        source.setData(geojson)
      } else {
        this.map.addSource(id, { type: 'geojson', data: geojson })
      }
      this.map.addLayer({
        id,
        type: 'line',
        source: id,
        paint
      })
    },

将点数据转换成GeoJson数据

js
    toGeoJSON(location, id) {
      return {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: [location.lng, location.lat]
            },
            properties: {
              id
            }
          }
        ]
      }
    }

Released under the MIT License.