creating balloon callout on graphics layer

1732
12
Jump to solution
10-26-2021 09:06 AM
LeLuong
New Contributor III

All,

Has anyone successfully created a balloon callout on graphics layer by codes ?  I asked this question before with previous version of arcgis Pro.  I was under the impression with version 2.8 I should be able to do it but no luck so far.  Below is my codes.  I got all other properties correct but NO callout arrow.   Thanks in advance for your help.

Not a calloutNot a callout

 

 _subjectTextSymbol = await CreateBalloonCalloutAsync(ColorFactory.Instance.RedRGB);
.
.
.
 subjectLabelGraphic.Text = "Subject";
                            subjectLabelGraphic.Symbol = _subjectTextSymbol.MakeSymbolReference();
                            //Add the graphic label
                            graphicsLayer.AddElement(subjectLabelGraphic);
.
.
.


private static Task<CIMTextSymbol> CreateBalloonCalloutAsync(CIMColor textColor)
        {
            return QueuedTask.Run<CIMTextSymbol>(() =>
            {
                //create a text symbol
                var textSymbol = SymbolFactory.Instance.ConstructTextSymbol(textColor, 11, "Corbel", "Regular");
                //A balloon callout
                var balloonCallout = new CIMBalloonCallout();
                //set the callout's style
                balloonCallout.BalloonStyle = BalloonCalloutStyle.RoundedRectangle;
                //Create a solid fill polygon symbol for the callout.
                var polySymbol = SymbolFactory.Instance.ConstructPolygonSymbol(ColorFactory.Instance.GreyRGB, SimpleFillStyle.Solid);
                //Set the callout's background to be the black polygon symbol
                balloonCallout.BackgroundSymbol = polySymbol;
                //margin inside the callout to place the text
                balloonCallout.Margin = new CIMTextMargin
                {
                    Left = 5,
                    Right = 5,
                    Bottom = 5,
                    Top = 5
                };
                //assign the callout to the text symbol's callout property
                textSymbol.Callout = balloonCallout;
                return textSymbol;
            });
        }

 

0 Kudos
1 Solution

Accepted Solutions
CharlesMacleod
Esri Regular Contributor

Looks like the leader is part of the graphic not the symbol. I made a text graphic in the UI and added a leader to it then deconstructed the CIM xml.

Note that, w/ a map via graphics layer, the leader position is specified in map units (not page units/points). In my case, the base map is the World Topo in Web Mercator, meters. The leader offset (in the symbol) seems to be the minimum distance beyond which a leader is shown.

callout.png

 

var graphicsLayer = MapView.Active.Map.TargetGraphicsLayer;
      //This is your method
      var textSymbol = await CreateBalloonCalloutAsync(ColorFactory.Instance.WhiteRGB);
      var textGraphic = new CIMTextGraphic()
      {
        Text = "Callout Text",
        Placement = Anchor.CenterPoint,
        Symbol = textSymbol.MakeSymbolReference(),
        Shape = MapView.Active.Extent.Center,
        //Leaders is an array of CIMLeader - add a Leader point to show
        //the leader, remove Leaders to hide the leader.
        Leaders = new CIMLeader[] { new CIMLeaderPoint()
        {
          //for a graphics layer, the leader location is in map coords
          Point = MapPointBuilderEx.CreateMapPoint(MapView.Active.Extent.Center.X - 5000,
                                                      MapView.Active.Extent.Center.Y - 1500)
        }
        }
      };
      QueuedTask.Run(() =>
      {
        graphicsLayer.AddElement(textGraphic);
      });

 

 

 

 

 

View solution in original post

12 Replies
JeremyWiles
New Contributor III

Do you have an offset?  It will not make the callout arrow unless there is an offset.

0 Kudos
LeLuong
New Contributor III

I tried 

balloonCallout.LeaderOffset = 20;

but didn't see any changes.  Is that the correct offset property you talked about ?  Thanks @JeremyWiles .

0 Kudos
LeLuong
New Contributor III

In Pro, if you want it to show the leader line , you can do right-click -> show/hide leader line but I'm unable to  find that property in proSDK.

0 Kudos
JeremyWiles
New Contributor III

I believe it is LeaderOffset, and your LeaderTolerance should be a lower number than the leader offset.  Have you changed the LeaderTolerance proeprty?

Here is an example

 

 

balloonCallout.Margin = New CIMTextMargin With {.Left = 2.5, .Right = 2.5, .Bottom = 2, .Top = 2}
balloonCallout.LeaderOffset = 10
balloonCallout.LeaderTolerance = 0

 

 

 

0 Kudos
LeLuong
New Contributor III

Thanks @JeremyWiles .  I tried what you suggested.  No luck! 😞

Have you tried it ?  Did you get the balloon ? 

0 Kudos
CharlesMacleod
Esri Regular Contributor

Looks like the leader is part of the graphic not the symbol. I made a text graphic in the UI and added a leader to it then deconstructed the CIM xml.

Note that, w/ a map via graphics layer, the leader position is specified in map units (not page units/points). In my case, the base map is the World Topo in Web Mercator, meters. The leader offset (in the symbol) seems to be the minimum distance beyond which a leader is shown.

callout.png

 

var graphicsLayer = MapView.Active.Map.TargetGraphicsLayer;
      //This is your method
      var textSymbol = await CreateBalloonCalloutAsync(ColorFactory.Instance.WhiteRGB);
      var textGraphic = new CIMTextGraphic()
      {
        Text = "Callout Text",
        Placement = Anchor.CenterPoint,
        Symbol = textSymbol.MakeSymbolReference(),
        Shape = MapView.Active.Extent.Center,
        //Leaders is an array of CIMLeader - add a Leader point to show
        //the leader, remove Leaders to hide the leader.
        Leaders = new CIMLeader[] { new CIMLeaderPoint()
        {
          //for a graphics layer, the leader location is in map coords
          Point = MapPointBuilderEx.CreateMapPoint(MapView.Active.Extent.Center.X - 5000,
                                                      MapView.Active.Extent.Center.Y - 1500)
        }
        }
      };
      QueuedTask.Run(() =>
      {
        graphicsLayer.AddElement(textGraphic);
      });

 

 

 

 

 

JeremyWiles
New Contributor III

I had never considered that there was a CIMLeader / CIMLeaderPoint in the graphic.

In my case, I did not want a leader.  I wanted to be sure there was no leader.  

So, I am curious, what does it look like if you added more than one CIMLeaderPoint to the array?  I don't think I have seen any label that looked like that in ArcGIS Pro or ArcMap before.

 

Just creating it on a layout, I can only see one place for a leader point.

JeremyWiles_0-1635373058659.png

 

 

Then there is also the option to "Remove Leader."  There is never any option to add another vertex to an array of leader points.  I am very curious what that would look like.

JeremyWiles_1-1635373058591.png

 

0 Kudos
JeremyWiles
New Contributor III

If you find something, I would love to see it.

0 Kudos
LeLuong
New Contributor III

@JeremyWiles In my case, it'll loop through many polygons in query and create a label for each of them.

 

                    using (var foundCursor = parcelLayer.Search(accountQf))
                    {
                        while (foundCursor.MoveNext())
                        {
                            using (var row = foundCursor.Current)
                            {
                                //The parcel is found. Get the center point to label at.
                                var shape = row as Feature;
                                var poly = shape.GetShape() as Polygon;
                                var maxY = poly.Extent.YMax + 10;
                                var maxX = poly.Extent.XMax + 10;
                                MapPoint maxPoint = MapPointBuilder.CreateMapPoint(maxX, maxY);

                                var textSymbol = await CreateBalloonCalloutAsync(ColorFactory.Instance.BlueRGB);
                                var textGraphic = new CIMTextGraphic()
                                {
                                    Text = $"Comp {counter}",
                                    Placement = Anchor.CenterPoint,
                                    Symbol = textSymbol.MakeSymbolReference(),
                                    Shape = maxPoint,

                                    Leaders = new CIMLeader[] { new CIMLeaderPoint()
                                        {
                                          //for a graphics layer, the leader location is in map coords
                                          Point = MapPointBuilderEx.CreateMapPoint(poly.Extent.Center.X,
                                                                                      poly.Extent.Center.Y)
                                        }
                                        }
                                };

                                graphicsLayer.AddElement(textGraphic);

 

CompLabel2.PNG

0 Kudos