我正在使用自定义图像创建带有图层符号的符号图层,效果很好。 我还想创建带有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,
},
})
答案 0 :(得分:0)
您不能在符号层中使用HTML。您可以:
Marker
对象而不是符号图层。答案 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();
}
}