1
votes

I'd like to have features in a vector source layer that each have an icon, text, AND a line. I can get the icon and text to display but I can't get a line to draw. Using a different geometry I can get a line with a label to draw but no icon.

Is this possible without creating another feature? What geometry should I use for the feature?

Here's the code I'm using to draw an icon with text:

feature.setGeometry(new ol.geom.Point(
    ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857')
));

feature.setStyle([
    new ol.style.Style({
        image: new ol.style.Icon({
            anchor: [0.5, 0.5],
            anchorXUnits: 'fraction',
            anchorYUnits: 'fraction',
            opacity: 1.0,
            scale: 0.75,
            src: 'res/ship_a_flash.png',
            rotation: 30.0
        })
    }),
    new ol.style.Style({
        text: new ol.style.Text({
            text: feature.text,
            font: 'bold 20px Times New Roman',
            offsetY: -25,
            fill: new ol.style.Fill({color: 'rgb(0,0,0)'}),
            stroke: new ol.style.Stroke({color: 'rgb(255,255,255)', width: 1})
        })      
    })
]);

So now I want to add a single line from the first point. I realize I need to add another point to the geometry so I tried MultiPoint and LineString like below.

feature.setGeometry(new ol.geom.MultiPoint([
    ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857'),
    ol.proj.transform([lon+1, lat+1], 'EPSG:4326', 'EPSG:3857')]
));

feature.setStyle([
    new ol.style.Style({
        image: new ol.style.Icon({
            anchor: [0.5, 0.5],
            anchorXUnits: 'fraction',
            anchorYUnits: 'fraction',
            opacity: 1.0,
            scale: 0.75,
            src: 'res/ship_a_flash.png',
            rotation: 30.0
        })
    }),
    new ol.style.Style({
        text: new ol.style.Text({
            text: feature.text,
            font: 'bold 20px Times New Roman',
            offsetY: -25,
            fill: new ol.style.Fill({color: 'rgb(0,0,0)'}),
            stroke: new ol.style.Stroke({color: 'rgb(255,255,255)', width: 1})
        })      
    }),
    new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: 'rgb(0,0,0)',
            width: 2,
        })      
    })
]);

I was hoping that the first point would be used for the Icon and Text and the 2 points would be used for the Stroke. With MultiPoint, the feature (icon and text) are drawn twice - once at each point in the geometry. With LineString, a line and text is drawn between the 2 points but the icon is not drawn.

It seems like I can either have an icon or a line in the feature, not both.

1
please be more specific about what techniques/methods you have used and attempted. - Jess Patton

1 Answers

4
votes

You could do the following: Use a geometry collection which contains a point and a line. Then use a StyleFunction which gets the point and the line and returns two separate styles for them:

var iconFeature = new ol.Feature({
  geometry: new ol.geom.GeometryCollection([
      new ol.geom.Point([0, 0]),
      new ol.geom.LineString([[0,0], [1E6, 1.5E6]])
  ]),
  ...
});

var styleFunction = function(feature, resolution) {
    var geometries = feature.getGeometry().getGeometries();
    var point = geometries[0];
    var line = geometries[1];

    var iconStyle = new ol.style.Style({
      geometry: point,
      image: ...,
      text: ...
    });

    var lineStyle = new ol.style.Style({
      geometry: line,
      stroke: ...
    });

    return [iconStyle, lineStyle];
};

http://jsfiddle.net/p8tzv9ms/11/