user3523426
user3523426

Reputation: 916

How to deduplicate feature labels when using OpenLayers and vector tiles

I have a map, where I display a grid. Each rectangle has a label. Unfortunately, when a rectangle is split between 2 or more tiles, its label is displayed on each tile. Is there a way, how to have the label displayed only once and in the middle of the split rectangle?

My style is defined as

new ol.style.Style({
        fill: new ol.style.Fill({ color: [0xfb, 0x7f, 0x7f, 0.7] }),
        stroke: new ol.style.Stroke({ color: "#ff0000", width: 1 }),
        text: new ol.style.Text({
            textAlign: "center",
            textBaseline: "middle",
            font: "15px sans-serif",
            text: "",
            fill: new ol.style.Fill({ color: [255, 0, 0, 1] }),
            stroke: null,
            offsetX: 0,
            offsetY: 0
        })
    })

I define the label inside my styling function like this:

var fontSize = Math.max(8, Math.round(180 / resolution)).toString();

var text = Math.round(parseFloat(feature.get("ceil")) * 0.3048).toString();

style.getText().setText(text);
style.getText().setFont(fontSize + "px sans-serif");

And the result is this:

enter image description here

Upvotes: 0

Views: 82

Answers (1)

Mike
Mike

Reputation: 17962

Your polygons look like a map graticule at 15 second (15/3600 of a degree) intervals.

enter image description here

If that is the case you could split the style into an array:

var polyStyle =  new ol.style.Style({
        fill: new ol.style.Fill({ color: [0xfb, 0x7f, 0x7f, 0.7] }),
        stroke: new ol.style.Stroke({ color: "#ff0000", width: 1 }),
    });

var textStyle =  new ol.style.Style({
        text: new ol.style.Text({
            textAlign: "center",
            textBaseline: "middle",
            font: "15px sans-serif",
            text: "",
            fill: new ol.style.Fill({ color: [255, 0, 0, 1] }),
            stroke: null,
            offsetX: 0,
            offsetY: 0
        });

[polyStyle, textStyle]

Then in the style function you could calculate where the label should be within that grid based on the polygon's position even if you have only part of the polygon:

var fontSize = Math.max(8, Math.round(180 / resolution)).toString();
var text = Math.round(parseFloat(feature.get("ceil")) * 0.3048).toString();
var center = ol.proj.toLonLat(ol.extent.getCenter(feature.getExtent()));
var interval = 15 / 3600;
var labelLon = Math.floor(center[0] / interval) * interval + interval / 2;
var labelLat = Math.floor(center[1] / interval) * interval + interval / 2;

textStyle.getText().setText(text);
textStyle.getText().setFont(fontSize + "px sans-serif");
textStyle.setGeometry(
  new ol.geom.Point(ol.proj.fromLonLat([labelLon, labelLat]))
);

Upvotes: 1

Related Questions