前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mapboxGL中多颜色图标的实现

mapboxGL中多颜色图标的实现

作者头像
lzugis
发布2023-03-31 14:09:20
6380
发布2023-03-31 14:09:20
举报

概述

mapboxGL中图标可以通过配置sprite,也可通过map.addImage添加。但在实际工作中,sprite多用于底图图标的配置,通过map.addImage对于图标较多的情况下,由于图片的异步导致使用起来比较麻烦。本文讲述如何结合OffscreenCanvas在mapboxGL中实现多颜色的图标的展示。

效果

实现

1. 分析

map.addImage添加的是一个ImageBitmap,可通过OffscreenCanvastransferToImageBitmapcanvas转换为ImageBitmap

图标分为两个部分:底部背景,根据不同的业务属性展示不同的颜色,可通过修改ImageData实现颜色的修改;叠加的图标,如果是多个图片,可通过sprite合成一张图片,再通过drawImage绘制对应的图标,如果是一个就直接绘制就可。

2. 实现

添加测试数据源

代码语言:javascript
复制
const features = res.map(({lon, lat, name}) => {
  const type = Math.round(Math.random() * 3).toString()
  return new Point({name, type}, [lon, lat])
})
map.addSource('vector-source', {
  type: 'geojson',
  data: new Geojson(features)
})

加载背景图片和图标图片,并添加图层

代码语言:javascript
复制
const imgBg = new Image()
imgBg.src = bgIcon
imgBg.onload = () => { // 加载背景图片
  const img = new Image()
  img.src = icon
  img.onload = () => { // 加载图标图片
    // 根据业务值获取图标
    const getIcon = (type, color) => {
      const [r, g, b] = hex2rgb(color)  // 将16进制颜色转换为rgb
      const canvas = new OffscreenCanvas(imgBg.width, imgBg.height)
      const ctx = canvas.getContext('2d')
      ctx.drawImage(imgBg, 0, 0)
      const imageD = ctx.getImageData(0, 0, imgBg.width, imgBg.height);
      const pdata = imageD.data;
      for (let j = 0; j < pdata.length; j+=4) {
        pdata[j] = r;
        pdata[j + 1] = g;
        pdata[j + 2] = b;
      }
      ctx.putImageData(imageD, 0, 0);
      const scale = 0.52
      const w = img.width * scale, h = img.height * scale
      ctx.drawImage(img, img.width * 0.24, img.height * 0.12, w, h)
      const imgId = 'icon-' + type
      map.addImage(imgId, canvas.transferToImageBitmap())
      return imgId
    }
    const colorDict = {
      '1': '#e30404',
      '0': '#0863e5'
    }
    let icons = [
          'match',
          ['get', 'type']
    ]
    for (const k in colorDict) {
      icons.push(k)
      icons.push(getIcon(k, colorDict[k]))
    }
    icons.push(getIcon('default', '#0aaf1b'))
    map.addLayer({
      id: 'vector-source',
      type: 'symbol',
      source: 'vector-source',
      layout: {
        'icon-image': icons,
        'icon-size': 0.8,
        'icon-allow-overlap': true
      }
    })
  }
}

16进制转换为rgb的方法

代码语言:javascript
复制
function hex2rgb(hex) {
  if (typeof hex !== "string") return;
  hex = hex.toLowerCase();
  const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  if (hex && reg.test(hex)) {
    if (hex.length === 4) {
      let hexNew = "#";
      for (var i = 1; i < 4; i += 1) {
        hexNew += hex.slice(i, i + 1).concat(hex.slice(i, i + 1));
      }
      hex = hexNew;
    }
    let hexChange = [];
    for (let i = 1; i < 7; i += 2) {
      hexChange.push(parseInt("0x" + hex.slice(i, i + 2)));
    }
    return hexChange
  }
  return hex;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 效果
  • 实现
    • 1. 分析
      • 2. 实现
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档