openlayersopenlayers-5

How to show dynamic text with gradient style while drawing a circle in openlayers?


I couldn't show text style on circle with "renderer" option in openlayers. I think this renderer option override text style. Is there any way to show text on this gradient style? I am just trying to show radius in meter as title of drawing circle.

// Layers
var layer = new ol.layer.Tile({ source: new ol.source.Stamen({ layer: 'watercolor' }) });

    // The map
    var map = new ol.Map ({
      target: 'map',
      loadTilesWhileAnimating: true,
      loadTilesWhileInteracting: true,
      view: new ol.View ({
        zoom: 11,
        center: [260064, 6250762]
      }),
      controls: [ new ol.control.Attribution() ],
      interactions: [],
      layers: [layer]
    });

var stylex =  new ol.style.Style({
                    text: new ol.style.Text({
                        <!-- textAlign: "Start", -->
                        <!-- textBaseline: "Middle", -->
                        font: 'Normal 16px Arial',
                        text: 'Dynamic radius value!!',
                        fill: new ol.style.Fill({
                            color: '#fff'
                        }),
                        stroke: new ol.style.Stroke({
                            color: '#000000',
                            width: 3
                        }),
                        zIndex: 999999999,
                        offsetX: -45,
                        offsetY: 0,
                        rotation: 0
                    }),
                    renderer(coordinates, state) {
                        const [[x, y], [x1, y1]] = coordinates;
                        const ctx = state.context;
                        const dx = x1 - x;
                        const dy = y1 - y;
                        const radius = Math.sqrt(dx * dx + dy * dy);
                    
                        const innerRadius = 0;
                        const outerRadius = radius * 1.4;
                    
                        const gradient = ctx.createRadialGradient(
                            x,
                            y,
                            innerRadius,
                            x,
                            y,
                            outerRadius
                        );
                        gradient.addColorStop(0, 'rgba(255,0,0,0)');
                        gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)');
                        gradient.addColorStop(1, 'rgba(255,0,0,0.8)');
                        ctx.beginPath();
                        ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                        ctx.fillStyle = gradient;
                        ctx.fill();
                    
                        ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                        ctx.strokeStyle = 'rgba(255,0,0,1)';
                        ctx.stroke();
                        
                        ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                        ctx.textStyle = "center";
                        ctx.text = "deneme";
                        
                    }
                    
                });
    
    var vector2 = new ol.layer.Vector({
      name: 'Vecteur2',
      style: stylex,
      source: new ol.source.Vector()
    });
    vector2.setZIndex(99999);
    map.addLayer(vector2);
    
    <!-- var select = new ol.interaction.Select(); -->
    <!-- map.addInteraction(select); -->
    var draw = new ol.interaction.Draw({
        source: vector2.getSource(),
        type: 'Circle'
    });
    draw.on('drawstart', function(f){
    
        f.feature.setStyle(stylex);
        
    });
    draw.on('drawend',function(f){
        console.log("radius:"+f.feature.getGeometry().getRadius().toFixed(2)+" m");
        
    });
    map.addInteraction(draw);

What's wrong with these codes that i added above? Gradient style appears very well but no text sadly.

Openlayer: v5


Solution

  • A style array with separate style objects for the custom renderer and the text should work:

       var stylex =  [
                        new ol.style.Style({
                            renderer(coordinates, state) {
                                const [[x, y], [x1, y1]] = coordinates;
                                const ctx = state.context;
                                const dx = x1 - x;
                                const dy = y1 - y;
                                const radius = Math.sqrt(dx * dx + dy * dy);
                            
                                const innerRadius = 0;
                                const outerRadius = radius * 1.4;
                            
                                const gradient = ctx.createRadialGradient(
                                    x,
                                    y,
                                    innerRadius,
                                    x,
                                    y,
                                    outerRadius
                                );
                                gradient.addColorStop(0, 'rgba(255,0,0,0)');
                                gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)');
                                gradient.addColorStop(1, 'rgba(255,0,0,0.8)');
                                ctx.beginPath();
                                ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                                ctx.fillStyle = gradient;
                                ctx.fill();
                            
                                ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                                ctx.strokeStyle = 'rgba(255,0,0,1)';
                                ctx.stroke();
                                
                                ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
                                ctx.textStyle = "center";
                                ctx.text = "deneme";
                                
                            }
                        }),
                        new ol.style.Style({
                            text: new ol.style.Text({
                                <!-- textAlign: "Start", -->
                                <!-- textBaseline: "Middle", -->
                                font: 'Normal 16px Arial',
                                text: 'Dynamic radius value!!',
                                fill: new ol.style.Fill({
                                    color: '#fff'
                                }),
                                stroke: new ol.style.Stroke({
                                    color: '#000000',
                                    width: 3
                                }),
                                zIndex: 999999999,
                                offsetX: -45,
                                offsetY: 0,
                                rotation: 0
                            }),
                        })
                      ];