1

I'm making app that displays my markers, and because there is a lot of them I need to make clusters. Everything but text works as expected.

I've tried changing anchor and anchor[X/Y]Units but even if i change it to a fixed pixels it always renders wrong.

This is my code:

const style = new Style({
    image: new CircleStyle({
        radius: 12,
        stroke: new Stroke({
            color: '#ffffff',
            width: 1,
        }),
        fill: new Fill({
            color: '#3399CC'
        }),
        anchorXUnits: 'fraction',
        anchorYUnits: 'fraction',
        anchor: [0.5, 0.5],
    }),
    text: new Text({
        font: '14px/24px sans-serif',
        text: '2',
        fill: new Fill({
            color: '#ffffff'
        })
    })
});

var clusters = new VectorLayer({
    source: clusterSource,
    style: style
});

Text in clusters is not aligning properly. I attach some images to ilustrate the problem further.

not aligning cluster texts
(source: devhub.pl)

not aligning cluster texts
(source: devhub.pl)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Pascal
  • 43
  • 7
  • 1
    I suspect the text is snapping to a pixel at the corner of the text while circles are independently snapping to a center pixel. Setting `snapToPixel: false` in the circle style might reduce the effect, but with no similar option for text there would be no way to completely eliminate it. – Mike Feb 06 '19 at 11:05
  • @Mike thanks for the suggestion. I've tried it and checked the documentation but the `snapToPixel` is deprecated and does nothing in the `CircleStyle` options. The numbers didn't move even by one pixel. – Pascal Feb 07 '19 at 07:18

2 Answers2

2

I think there is no way to align it properly using OpenLayers API alone. I came up with another solution. I made a function to render the circle and text in Canvas Context.

I use this function:

const createImage = function (diameter, text) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    // set canvas width and height to double the outer diameter
    canvas.width = diameter * 2;
    canvas.height = diameter * 2;

    // white border
    ctx.beginPath();
    ctx.arc(diameter, diameter, diameter, 0, 2 * Math.PI);
    ctx.fillStyle = '#ffffff';
    ctx.fill();

    // inner circle
    ctx.beginPath();
    ctx.arc(diameter, diameter, diameter - 1.5, 0, 2 * Math.PI); // the -1.5 makes a nice offset
    ctx.fillStyle = '#104ddb';
    ctx.fill();

    // text in the circle
    ctx.beginPath();
    ctx.font = '14px Arial';
    ctx.fillStyle = '#ffffff';
    ctx.textAlign = 'center'; // center horizontally
    ctx.textBaseline = 'middle'; // center vertically
    ctx.fillText(text, diameter, diameter);

    return canvas.toDataURL();
};

And style look like this:

style = new Style({
    image: new Icon({
        src: createImage(24, '2'), // createImage(radius, text)
        imgSize: [24, 24],
    }),
});

I hope it helps somebody.

Pascal
  • 43
  • 7
0

Check the example on earthquake clusters. All text alignment seems to be OK.

https://openlayers.org/en/latest/examples/earthquake-clusters.html

Ulas
  • 190
  • 5
  • It's just an illusion because every cluster they are showing in the demo is different size (even if it has the same text displayed), so it's less visible. – Pascal Feb 06 '19 at 08:55
  • Does https://openlayers.org/en/latest/examples/cluster.html look correct for you? There can be differences depending on font and browser, but in general alignment should work as advertised. – ahocevar Feb 08 '19 at 17:18
  • @ahocevar The example has this issue as well. – Pascal Feb 11 '19 at 08:34