基于Cesium Billboard的图文标注

背景

项目需求:在模型上方添加文字标注,背景是一张图片。
如果只是加文字的话,Cesium 直接加一个label就行了,或者只加一个图片,Cesium 直接加一个 billboard 也是可以的。如果是两者结合是需要另外处理的。

单独文字

单独加文字可以直接用 label, 伪代码如下:

viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label: {
text: "Philadelphia",
font: "24px Helvetica",
fillColor: Cesium.Color.SKYBLUE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
},
});

效果:

单独加图片

单独显示图片使用 billboard, 伪代码如下:

viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
billboard: {
image: "../images/Cesium_Logo_overlay.png",
},
});

效果:

图文结合

  1. 思路:根据原始添加图片的过程,再结合 billboard 文档的查看其中的 image 定义:

    image : StringScene/Billboard.js 910
    Gets or sets the image to be used for this billboard. If a texture has already been created for the given image, the existing texture is used.
    This property can be set to a loaded Image, a URL which will be loaded as an Image automatically, a canvas, or another billboard's image property (from the same billboard collection).

    This property can be set to a loaded Image, a URL which will be loaded as an Image automatically, a canvas, or another billboard’s image property (from the same billboard collection).
    可以将此属性设置为已加载的图像,将自动作为图像加载的URL,画布或其他广告牌的图像属性(来自同一广告牌集合)。

    上述文字说明 image 可以是 canvas, 那我们就可以把图片和文字画到 canvas 中,最后把结果赋值给 image 就行了。

  2. 实现:

  • 绘制图文方法

          //根据图片和文字绘制canvas  ratio参数 是放大倍数
    function drawCanvas(img, text, ratio) {
    // width height
    var canvas = document.createElement('canvas'); //创建canvas标签
    var ctx = canvas.getContext('2d');

    var width = ctx.measureText(text).width + 8,
    height = 20; //高度我这里是定死的,可以作为参数参入

    canvas.style.opacity = 1;
    canvas.width = width * ratio;
    canvas.height = height * ratio;
    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';

    //然后将画布缩放,将图像放大ratio倍画到画布上 目的 使图片文字更加清晰
    ctx.scale(ratio, ratio);
    var image = new Image();
    image.src = img;
    // 图片创建是异步操作,需要在图片完成之后,再写入文字,能保证文字在图片上方。
    // 如果不在里面,会出现图片覆盖文字
    image.onload = function () {
    ctx.drawImage(image, 0, 0, width, height);
    // 名称文字
    ctx.fillStyle = '#ff0000';
    ctx.font = '8px 宋体';
    ctx.fillText(text, 8, height / 2 + 2);
    };

    return canvas;
    }
    ```
    + 加载到Cesium中
    ```js
    viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(
    109.05830792532525,
    37.44105749283626,
    16
    ),
    billboard: {
    image: drawCanvas('./source/images/bg.png', 'Hello World 你好 Cesium!', 3),
    sizeInMeters: true,
    scale: 0.1,
    },
    });
  • 效果:

    音乐小憩