Text Label Placement Issues with PictureSymbols

4079
3
Jump to solution
06-11-2015 11:36 AM
JimFiddes
Occasional Contributor

I'm trying to display graphics within a GraphicsOverlay and I can't seem to get my label to appear off of the symbol. I have read that the xoffset doesn't work within an attribute label class; however, how is one to display a multi-line label next to a "pin" symbol. Below is a picture example of how it currently looks and I have added a section of code showing the construction of the layer and label.

**************Code Example**************

var pictureUri = new Uri("http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png");

await matchSym.SetSourceAsync(pictureUri);

//create a simple top level renderer

var simpleRenderer = new SimpleRenderer { Symbol = matchSym };

_inspectionResultsLayer = new GraphicsOverlay

{

  ID = GraphicLayerName,

  Labeling = { IsEnabled = true },

  Renderer = simpleRenderer

};

// create a new TextSymbol for displaying graphic labels

var labelSym = new TextSymbol

{

  Font = new SymbolFont

    ("Arial",

    12.0,

    SymbolFontStyle.Normal,

    SymbolTextDecoration.None,

    SymbolFontWeight.Bold),

  Color = Colors.Black,

  BorderLineColor = Colors.LightGray,

  BorderLineSize = 1,

  AngleAlignment = MarkerAngleAlignment.Map,

  HorizontalTextAlignment = HorizontalTextAlignment.Left,

};

// create a new LabelClass

var attributeLabelClass = new AttributeLabelClass

{

  Symbol = labelSym,

  TextExpression = "[Title] CONCAT NEWLINE CONCAT [Address]",

  LabelPlacement = LabelPlacement.PointAboveRight,

};

_inspectionResultsLayer.Labeling.LabelClasses.Add(attributeLabelClass);

MainMapMapView.GraphicsOverlays.Add(_inspectionResultsLayer);


esri.PNG

0 Kudos
1 Solution

Accepted Solutions
MichaelBranscomb
Esri Frequent Contributor

Hi,

I think the issue is just the order in which you create the symbol, the symbol is rendered and the label position is calculated. In order for the label algorithm to correctly calculate the offset to avoid overlapping the symbol, it needs to know the rendered size of the symbol. You don't include the code where the PictureMarkerSymbol is actually declared, so it's unknown if you are explicitly setting the width/height of the symbol, but you should do this as good practice. In the code example above the symbol is not downloaded and rendered until after the label position is calculated and therefore it overlaps. If the code is rewritten slightly so that the rendered symbol size is known in advance then the label does not overlap.

I hope that resolves your question, but if not please don't hesitate to ask for more info.

Cheers

Mike

View solution in original post

0 Kudos
3 Replies
MichaelBranscomb
Esri Frequent Contributor

Hi,

I think the issue is just the order in which you create the symbol, the symbol is rendered and the label position is calculated. In order for the label algorithm to correctly calculate the offset to avoid overlapping the symbol, it needs to know the rendered size of the symbol. You don't include the code where the PictureMarkerSymbol is actually declared, so it's unknown if you are explicitly setting the width/height of the symbol, but you should do this as good practice. In the code example above the symbol is not downloaded and rendered until after the label position is calculated and therefore it overlaps. If the code is rewritten slightly so that the rendered symbol size is known in advance then the label does not overlap.

I hope that resolves your question, but if not please don't hesitate to ask for more info.

Cheers

Mike

0 Kudos
JimFiddes
Occasional Contributor

Morning Mike

I always appreciate the speed in which I get a response on this forum!!

After re-reading what you wrote a few times, I tried a few different things and what I found best is assigning the symbol when the graphic gets added. This helps deal with the font layout issue. The first thing I did attempt was setting the width and height of the picturemarkersymbol when creating the renderer. I was missing that; however this did not seem to resolve my issue. Below is minor edits to my code in case others are needing to do something similar.

It would be nice to have a padding property on labels or even better a callout box like what is offered in Google Maps. As you can see from my TextExpression, I'm adding spaces before and after the values to create the desired padding within my "box".

*********************CODE EXAMPLE*********************

private GraphicsOverlay _inspectionResultsLayer;

private PictureMarkerSymbol _pictureMarkerSymbol;

private async Task CreateGraphicsLayer()

{

//create the symbol and store privately to use later

  _pictureMarkerSymbol = new PictureMarkerSymbol

  {

    Width = 50,

    Height = 50

  };

  var pictureUri = new Uri("http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png");

  await _pictureMarkerSymbol.SetSourceAsync(pictureUri);

  _inspectionResultsLayer = new GraphicsOverlay

  {

    ID = GraphicLayerName,

    Labeling = { IsEnabled = true },

  };

  // create a new TextSymbol for displaying graphic labels

  var labelSym = new TextSymbol

  {

    Font = new SymbolFont

    ("Segoe UI",

    12.0,

    SymbolFontStyle.Normal,

    SymbolTextDecoration.None,

    SymbolFontWeight.Normal),

    Color = Colors.DarkBlue,

    //create a colour with some transparency

    BackgroundColor = Color.FromArgb(150,245,245,245 ),

    BorderLineSize = 1,

    AngleAlignment = MarkerAngleAlignment.Map,

  };

  // create a new LabelClass

  var attributeLabelClass = new AttributeLabelClass

  {

    Symbol = labelSym,

    TextExpression = "\"   \" CONCAT [Title] CONCAT \"   \" CONCAT NEWLINE CONCAT \"   \" CONCAT [Address] CONCAT \"   \"",

    LabelPlacement = LabelPlacement.PointCenterRight,

  };

  _inspectionResultsLayer.Labeling.LabelClasses.Add(attributeLabelClass);

  MainMapMapView.GraphicsOverlays.Add(_inspectionResultsLayer);

}

private void AddMarkerSymbol(Marker marker)

{

  var geometry = ProjectedGeometry(marker.Coordinates.X, marker.Coordinates.Y);

  var myGraphic = new Graphic(geometry, _pictureMarkerSymbol);

  // Add attributes to the Graphic from various information in the geocode match.

  myGraphic.Attributes["Title"] = marker.Title;

  myGraphic.Attributes["Address"] = marker.Address;

  // add text and marker graphics

  _inspectionResultsLayer.Graphics.Add(myGraphic);

  SetMapView(geometry as Esri.ArcGISRuntime.Geometry.MapPoint);

}

*********************DESIRED LOOK*********************

esri2.PNG

0 Kudos
MichaelBranscomb
Esri Frequent Contributor

Hi,

I believe the label engine may in fact need the symbol to be rendered in order to determine it's relative placement, hence why the graphic, with symbol/renderer needs to be added and displayed before the label is placed. Only marker symbols and other labels are considered to be obstacles when placing labels, line and fill symbols are not.

Some form of padding and/or an offset, plus a leader line are on the roadmap for a future release, so we appreciate your feedback on this.

If there's just one object / one label and you do not need the de-cluttering then you might consider a map overlay as an alternative? See sample arcgis-runtime-samples-dotnet/MapOverlays.xaml at master · Esri/arcgis-runtime-samples-dotnet · GitH...

Cheers

Mike

0 Kudos