openlayersqgisopenlayers-8

Placing feature labels at specific coordinates in OpenLayers


I have a map which is maintained in QGIS and the layers are periodically exported to geojson for use in OpenLayers on a website.

QGIS allows me to set custom label positions on features, and will store the coordinates of the custom label position in the attribute table for that layer.

OpenLayers, on the other hand, does not have a way to deal with specific coordinates for the label, instead only having a way to define an offset.

Easy enough, I just need to get the coordinates from the feature, and measure the distance to the coordinates stored for the label, and make that be the offset. Or so I thought.

Here's my existing code, which calculates the offset from the center of the feature's extent:

    var offsetX = 0;
    var offsetY = 0;
    var labelX = +(feature.get('LabelX'));
    var labelY = +(feature.get('LabelY'));
    if (labelX && labelY) {
        var labelXY_coor = [labelX, labelY];
        var labelXY = map.getPixelFromCoordinate(labelXY_coor);
        var centerXY_coor = ol.extent.getCenter(feature.getGeometry().getExtent());
        var centerXY = map.getPixelFromCoordinate(centerXY_coor);
        offsetX = (labelXY[0] - centerXY[0]);
        offsetY = (labelXY[1] - centerXY[1]);
    }

However, it appears as though the offset interpreted by OpenLayers is not from the center of the feature, but offset from where OpenLayers would have originally put the label. Which isn't always the center, depending on the shape. Thus my code only works correctly when the feature in question happens to be completely symmetric, and in that case I'm unlikely to have customized the position anyway.

I've been searching around for a while trying to figure out how OpenLayers determines the default label position without much luck, and there doesn't seem to be a method in the API docs to tell me where it's going to put it.

In order to create my offset correctly, how would I find the coordinates where OpenLayers plans to put the label (rather than the center of the extent as I'm doing now)?

Or am I even barking up the right tree and there's a better way to keep custom label positions in sync between QGIS and OpenLayers?


Solution

  • OpenLayers has a geometry option to deal with specific coordinates https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html

    In your case you could use something like

    var geometry = new ol.geom.Point([+(feature.get('LabelX')), +(feature.get('LabelY'))]);