在Mapbox GL中,有一种方法可以使符号标签为自定义HTML

时间:2020-09-21 05:48:59

标签: mapbox-gl-js mapbox-gl

我正在使用自定义图像创建带有图层符号的符号图层,效果很好。 我还想创建带有HTML的自定义标签(基本上是带有宽松边框和标签的蓝色背景),但是我不确定这是否可行或如何实现。我包括了我现在正在使用的渲染点,获取图标渲染了每个点的自定义图像,这些图像是使用map.loadImage预先加载的。

map.addLayer({
        id: 'points',
        type: 'symbol',
        source: 'points',
        paint: {
          "text-color": "#ffffff",
        },
        layout: {
          'icon-image': ['get', 'icon'], // 'cat',
          'icon-size': 1,
          'icon-allow-overlap': true,
          
           'text-field': ['get', 'name'],
           'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],
           'text-offset': [0, 2.00],
           'text-size': 14,
           'text-anchor': 'top',
           'text-allow-overlap': false,
        },
      })

2 个答案:

答案 0 :(得分:0)

您不能在符号层中使用HTML。您可以:

  • 使用Marker对象而不是符号图层。
  • 在符号层中使用格式化的内容,并混合使用字体,字体粗细等。
  • 使用9个部分的图像制作自定义边框。

答案 1 :(得分:0)

这几乎是我过去为房屋租赁公司所做的工作。 基本上,我必须出示带有价格的标签,房子是否有3D图片,并添加蓝色背景... 下面是可以修改以满足您的需求的源代码

我所做的是像这样在“ icon-image”中编码所有信息:

...
'icon-image': ['concat', 'projectmarker|', ['get', 'id'], '|', ['get', 'price'], '|', ['get', '3d'], '|', ['get', 'name'], '|', ['get', 'highlight']]
...

然后发生的是,mapbox找不到图像,而是调用了“ styleimagemissing”回调,该回调使用该元素完成了所有工作,并最终将其转换为dataimage。


const missingImages = [];
map.on('styleimagemissing', function (e) {
        const id = e.id;
        const blue = '#1f2d41';
        const white = '#ffffff';
        const yellow = '#a3a326';

        // only create once
        if (missingImages.indexOf(id) !== -1) return;
        missingImages.push(id);

        // check if this missing icon is one this function can generate
        if (id.indexOf('projectmarker') !== 0) return;

        // extract infos
        const projectId = parseInt((id.split('|')[1]));
        let price = parseInt((id.split('|')[2])).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        const hasPrice = price !== "0";
        const threeD = 'true' === (id.split('|')[3]);
        const highlight = '1' === (id.split('|')[5]);

        if (!hasPrice) {
            price = id.split('|')[4];
        } else {
            price += ' ' + currencyCode;
        }

        // create canvas
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");

        const height = 20;
        const leftWidth = 40;
        const rightWidth = (8 * price.length) + 10;
        const leftBg = blue;
        const rightBg = highlight ? yellow : white;
        const radius = 4;

        if (threeD) {
            // 3d bg
            ctx.fillStyle = leftBg;
            roundRect(ctx, 0, 0, leftWidth, height, {tl: radius, tr: 0, br: 0, bl: radius}, true, true);

            // 3d text
            ctx.textAlign = "center";
            ctx.font = "bold 14px Arial";
            ctx.fillStyle = white;
            ctx.fillText('360°', leftWidth / 2, 16);

            // price bg
            ctx.fillStyle = rightBg;
            roundRect(ctx, leftWidth, 0, rightWidth, height, {tl: 0, tr: radius, br: radius, bl: 0}, true, true);
        } else {
            // price bg
            ctx.fillStyle = rightBg;
            roundRect(ctx, 0, 0, rightWidth, height, radius, true, true);
        }

        // price
        ctx.textAlign = "center";
        ctx.font = "14px Arial";
        ctx.fillStyle = blue;
        ctx.fillText(price.replace(',', ' '), (threeD ? leftWidth : 0) + (rightWidth / 2), 15);

        // extract data and create mapbox image
        const imageData = ctx.getImageData(0, 0, (threeD ? leftWidth : 0) + rightWidth, height);
        map.addImage(id, imageData);

    });

下面是roundRect助手

const roundRect = (ctx, x, y, width, height, radius, fill, stroke) => {
    if (typeof stroke === 'undefined') {
        stroke = true;
    }
    if (typeof radius === 'undefined') {
        radius = 5;
    }
    if (typeof radius === 'number') {
        radius = {tl: radius, tr: radius, br: radius, bl: radius};
    } else {
        const defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
        for (let side in defaultRadius) {
            radius[side] = radius[side] || defaultRadius[side];
        }
    }
    ctx.beginPath();
    ctx.moveTo(x + radius.tl, y);
    ctx.lineTo(x + width - radius.tr, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
    ctx.lineTo(x + width, y + height - radius.br);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
    ctx.lineTo(x + radius.bl, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
    ctx.lineTo(x, y + radius.tl);
    ctx.quadraticCurveTo(x, y, x + radius.tl, y);
    ctx.closePath();
    if (fill) {
        ctx.fill();
    }
    if (stroke) {
        ctx.stroke();
    }

}
相关问题