[GIS] Setting label at top right of MultiLineString in OpenLayers 4

labelingopenlayers

I would like to set the label a the top right of the geometry because i want to see it entirely.

I dont want the label overlapping the geometry.

Move label to the top right of the extent

I tried with the extent without success.

var labelStyle = new ol.style.Style({
  geometry: function(feature) {
    var geometry = feature.getGeometry();
    if (geometry.getType() == 'MultiLineString') {
      // Only render label for the widest polygon of a multipolygon
      var polygons = geometry.getLineStrings();
      var widest = 0;
      for (var i = 0, ii = polygons.length; i < ii; ++i) {
        var polygon = polygons[i];
        var width = ol.extent.getWidth(polygon.getExtent());
        if (width > widest) {
          widest = width;
          geometry = polygon;
        }
      }
    }
    return geometry;
  },
  text : new ol.style.Text({
    font: '12px Calibri,sans-serif',
    fill: new ol.style.Fill({color: 'black'}),
    //stroke: new ol.style.Stroke({color: 'white', width: 1}),
    overflow: true,
    backgroundFill : new ol.style.Fill({color: 'orange'}),
    placement : "point",
    textBaseline : "top"
  })
});

  var styles = [geomStyle, labelStyle];

  var vector = new ol.layer.Vector({
    source: vectorSource,
    style: function(feature) {
      labelStyle.getText().setText(feature.get('QUALIF') +' '+feature.get('DENOM'));

var styles = [geomStyle, labelStyle];

var vector = new ol.layer.Vector({
  source: vectorSource,
  style: function(feature) {
    labelStyle.getText().setText(feature.get('QUALIF') +' '+feature.get('DENOM'));

    var geometry = feature.getGeometry();
    var ext = geometry.getExtent();
    var offsetX = (ext[2]-ext[0]);
    var offsetY = (ext[3]-ext[1]);
    console.log(offsetX);
    /*
    labelStyle.getText().setOffsetX(offsetX);
    labelStyle.getText().setOffsetX(offsetY);
    */
    return styles;
  },
  declutter: true
});

The full code on GITBUB

Best Answer

You can use style function similarly as you did, but with using new point as geometry for another additional style. This function will label any feature on the coordinates of it's extent top right corner.

function styleFunc(feature) {
var styles = [
  new ol.style.Style({
    stroke: new ol.style.Stroke({
      color: "#ffcc33",
      width: 2
    })
  })
];
var extent = feature.getGeometry().getExtent();
var topRightCoor = [extent[2], extent[3]];
styles.push(new ol.style.Style({
  geometry: new ol.geom.Point(topRightCoor),
  text: new ol.style.Text({
    text: feature.get('QUALIF') + ' ' + feature.get('DENOM'),
    font: '12px Calibri,sans-serif',
    fill: new ol.style.Fill({
      color: 'black'
    }),
    //stroke: new ol.style.Stroke({color: 'white', width: 1}),
    overflow: true,
    backgroundFill: new ol.style.Fill({
      color: 'orange'
    }),
    placement: "point",
    textBaseline: "top"
  })
}));
return styles;
};  
var vector = new ol.layer.Vector({
  source: vectorSource,
  style:styleFunc,
  declutter: true
});

I've learned this based on this example, maybe it will help you too. There are a lot of other labeling strategies. For example label feature on position of first or last point of its geometry, label only in the middle of the last segment of line, or label only on mouse hover.