效果

使用
const points = [
{ name: '这是携带icon并且很长的文字', theme: 'icon', center: [120.153576, 30.287459] },
{ name: '很短', theme: 'icon', center: [120.582112, 29.997117] },
{ name: '无Icon的文字', theme: 'normal', center: [121.549792, 29.868388] },
];
new LayerBoxOperations('LevelOne', points, { show: true });
封装方法
import SuperMap3DLayer from '@/pages/screen/SuperMap3DLayer';
interface Theme {
bg: string[];
arrow: string[];
icon?: string;
}
interface Themes {
normal: Theme;
icon: Theme;
}
interface Options {
show: boolean;
theme?: 'normal' | 'town' | 'village' | 'province' | 'country';
}
export default class LayerBoxOperations {
points: any;
private entities: any;
private options: any;
private themes: Themes;
private layerName: string;
constructor(layerName: string, points: any[], options) {
this.layerName = layerName;
this.points = [
{ name: '这是携带icon并且很长的文字', theme: 'icon', center: [120.153576, 30.287459] },
{ name: '很短', theme: 'icon', center: [120.582112, 29.997117] },
{ name: '无Icon的文字', theme: 'normal', center: [121.549792, 29.868388] },
];
this.options = options;
this.themes = {
normal: {
bg: ['#558DFF', '#DF82FF'],
arrow: ['rgba(85,141,255,0)', '#DF82FF'],
},
icon: {
bg: ['#558DFF', '#DF82FF'],
arrow: ['rgba(38,55,95,0)', '#6699FF'],
icon: 'bg_g.png',
},
};
this.entities = [];
this.renderPoints();
}
createGradientTextImage(text) {
return new Promise((resolve) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const option = this.themes[theme];
const hasIcon = theme === 'ICON';
const baseText = 20;
canvas.width = baseText * text.length;
if (hasIcon) {
canvas.width += 30;
}
canvas.height = 86;
context.beginPath();
context.moveTo(canvas.width / 2 - 15, 30);
context.lineTo(canvas.width / 2 + 15, 30);
context.lineTo(canvas.width / 2, 72);
context.closePath();
const gradient2 = context.createLinearGradient(15, 0, 15, 72);
gradient2.addColorStop(0, option.arrow[0]);
gradient2.addColorStop(1, option.arrow[1]);
context.fillStyle = gradient2;
context.fill();
const gradient = context.createLinearGradient(0, 0, canvas.width, 40);
gradient.addColorStop(0, option.bg[0]);
gradient.addColorStop(1, option.bg[1]);
context.fillStyle = gradient;
context.font = '16px Arial';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.shadowColor = 'rgba(0, 0, 0, 0.5)';
context.shadowBlur = 8;
context.shadowOffsetY = 1;
context.fillRect(0, 0, canvas.width, 40);
context.fillStyle = 'white';
if (hasIcon) {
context.fillText(text, canvas.width / 2 + 15, 20);
const img = new Image();
img.onload = function () {
context.drawImage(img, 8, 3, 34, 34);
resolve(canvas.toDataURL());
};
img.src = `/static/screen/${option.icon}`;
} else {
context.fillText(text, canvas.width / 2, 20);
resolve(canvas.toDataURL());
}
});
}
renderPoints() {
for (let i = 0; i < this.points.length; i++) {
const point = this.points[i];
if (!point.center) break;
this.createGradientTextImage(point.name).then((imageUrl) => {
const entitie = {
show: this.options.show || false,
position: SuperMap3D.Cartesian3.fromDegrees(point.center[0], point.center[1]),
dataset: point,
billboard: {
image: imageUrl,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
name: this.layerName,
};
this.entities.push(entitie);
SuperMap3DLayer.viewer.entities.add(entitie);
});
}
}
}