Openlayers ol.style.Text with multiple colors

6.3k views Asked by At

Is there a way to set multiple font colors for ol.style.Text class for openlayers 4+?

I am trying to do something like

const label = new ol.style.Style({
        text: new ol.style.Text({
            text: '<color1>X</color1> other text',
            textAlign: 'center',

            font: '11px roboto,sans-serif',
            fill: new ol.style.Fill({
                color: 'white'
            }),
            stroke: new ol.style.Stroke({
                color: 'black',
                lineCap: 'butt',
                width: 4
            }),
            offsetX: 0,
            offsetY: 25.5,
        })

since "other text" length or width is unknown and textAlign must be set to center, i can't add two ol.style.Text classes and position them side by side.

Thanks in advance

1

There are 1 answers

0
ahocevar On BEST ANSWER

There is no solution for this on the library level, but you can quite easily achieve it with two text styles. The trick is to measure the width of both texts using e.g. CanvasRenderingContext2D.measureText, and to adjust the offsetX property of both text styles accordingly:

var map = new ol.Map({
  target: 'map',
  view: new ol.View({
    center: [0, 0],
    zoom: 0
  })
});

var point = new ol.Feature(
    new ol.geom.Point([0, 0]));

var text1 = 'X'
var text2 = ' other text';
var font = '11px roboto,sans-serif';
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.font = font;
var width1 = context.measureText(text1).width;
var width2 = context.measureText(text2).width;

var layer = new ol.layer.Vector({
  source: new ol.source.Vector({
    features: [point]
  }),
  style: [
    new ol.style.Style({
      image: new ol.style.Circle({
        radius: 4,
        fill: new ol.style.Fill({
          color: 'blue'
        })
      }),
      text: new ol.style.Text({
        font: font,
        text: text1,
        fill: new ol.style.Fill({
          color: 'red'
        }),
        textAlign: 'center',
        textBaseline: 'bottom',
        offsetY: -5,
        offsetX: -width2 / 2
      })
    }),
    new ol.style.Style({
      text: new ol.style.Text({
        font: font,
        text: text2,
        fill: new ol.style.Fill({
          color: 'black'
        }),
        textAlign: 'center',
        textBaseline: 'bottom',
        offsetY: -5,
        offsetX: width1 / 2
      })
    })
  ]
});
map.addLayer(layer);
html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
 }
<link href="https://openlayers.org/en/v4.3.2/css/ol.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map"></div>