Search code examples
labellinepixeloffsetcesiumjs

Cesium js. How Draw line binding a label to a position


I would like to draw a line binding a entity to its label with an offset. CesiumJS allows to offset the label, however its not possible to draw a line (or polyline) from a position to an offset like the red line in this image.

enter image description here

How can i do it? any sugestion?

i'm using pixel offset. but there is no problem to use eye offset

 labels.add({
        position: Cesium.Cartesian3.fromDegrees(-75.1641667, 29.9522222),
        text: 'Another label',
        pixelOffset: new Cesium.Cartesian2(100,-100)

    });

Solution

  • The best way to do this is probably a billboard with an image of the line on it. The length will never change if it's a pixelOffset. You can put an image of a white line, and use the color property to set any other color.

    var viewer = new Cesium.Viewer('cesiumContainer', {
        navigationInstructionsInitiallyVisible: false, animation: false, timeline: false,
        // These next 6 lines are just to avoid Stack Snippet error messages.
        imageryProvider : new Cesium.TileMapServiceImageryProvider({
            url: Cesium.buildModuleUrl("Assets/Textures/NaturalEarthII"),
        }),
        baseLayerPicker : false,
        geocoder : false,
        infoBox : false
    });
    
    var scene = viewer.scene;
    var offsetX = 50, offsetY = -80;
    var pos = Cesium.Cartesian3.fromDegrees(-75.1641667, 29.9522222);
    
    var labels = scene.primitives.add(new Cesium.LabelCollection());
    labels.add({
        position: pos,
        text: 'Another label',
        pixelOffset: new Cesium.Cartesian2(offsetX, offsetY)
    });
    
    var canvas = document.createElement('canvas');
    canvas.width = Math.abs(offsetX);
    canvas.height = Math.abs(offsetY);
    var context2D = canvas.getContext('2d');
    context2D.beginPath();
    context2D.lineWidth = 3;
    context2D.strokeStyle = '#ffffff';
    context2D.moveTo((offsetX < 0) ? -offsetX : 0, (offsetY < 0) ? -offsetY : 0);
    context2D.lineTo((offsetX < 0) ? 0 : offsetX, (offsetY < 0) ? 0 : offsetY);
    context2D.stroke();
    
    var billboards = scene.primitives.add(new Cesium.BillboardCollection());
    
    var billboard = billboards.add({
        color : Cesium.Color.RED,
        image : canvas,
        pixelOffset: new Cesium.Cartesian2(offsetX * 0.5, offsetY * 0.5),
        position : pos
    });
    html, body, #cesiumContainer {
      width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
    }
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.78/Build/Cesium/Widgets/widgets.css" rel="stylesheet"/>
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.78/Build/Cesium/Cesium.js"></script>
    <div id="cesiumContainer"></div>