Select to view content in your preferred language

Multiple Callouts / Popups / Info boxes along a path

151
1
3 weeks ago
radimbachb
New Contributor III

In our app we'd like to display information at  multiple points along a flight path.

The end result should look something like this where the blue line is the flight path, the black crosses are the points of interest, and the blue triangle the plane itself with an info box that displays its current state, for example altitude, speed etc. The boxes are connected / anchored to their respective locations.

radimbachb_0-1719847059157.png

I've read quite a bit about Callouts and Popups but I'm not sure they're the right approach. With callouts for example the MapView Class | ArcGIS Maps SDK for Qt | Esri Developer only has a single calloutData property, so we would not be able to render more than 1 info box at a time.

MarkerSymbol Class | ArcGIS Maps SDK for Qt | Esri Developer has OffsetX and OffsetY properties. With that we can get an info box symbol to the correct place with an offset relative to the location. But how could we draw the line or "leader" that connects the offset box and the location? MarkerSymbol has leaderOffsetX, leaderOffsetY properties, but I'm not sure how to even draw this leader...

We're also using a custom dictionary style to render some of our symbols. Is there any way we could define such an info box with a leader in our dictionary style? I saw that the CIM spec has some Callout symbols defined (see CIMCompositeCallout cim-spec/docs/v3/CIMSymbols.md at main · Esri/cim-spec (github.com)) but so far I don't know how I could create such a symbol and use it as part of our dictionary style.

 

0 Kudos
1 Reply
LucasDanzinger
Esri Frequent Contributor

From the description, it seems like labels with leader lines might suit your use case well. Leader lines are unfortunately not supported in the Maps SDK yet, but it is something we have had a lot of requests for. If you have access to ArcGIS Pro and can try to prototype Label callouts with leader lines, that would be useful to know if that satisfies your requirements. If so, if you could message me some details about your organization/app so I can add it to our tracking issue internally, that would be great.

 

The other avenue as you mentioned is using the Callout. Unfortunately, it is pretty tightly coupled to having 1 display at a time. However, since it is open source, you do have the option of poking around and seeing if you get something to suit your needs.

 

I have some ideas that may or may not help get you on the right track. One thing you can do with the Callout is set the contentItem to display whatever you want (doesn't need to be tied to title/description properties)

 

Callout {                
    contentItem: Column {
        spacing: 10
        anchors.fill: parent
        Text {
            text: "Custom Callout"
            font.bold: true
            font.pixelSize: 18
        }
        Text {
            text: "This is a custom callout"
        }
    }
    palette.windowText: "black"
}

 

This solves the display customization question, but the remaining problem at this point is that the location the callout displays at is tied to the location provided from the callout data. Since we want multiple callouts, we can't rely on that single location.

However, Callout itself is just a QML Pane, so you can theoretically display it wherever you like (as QML allows). The nice thing that CalloutData does for you is that it converts the map coordinate to a screen coordinate for you, and it updates whenever the viewpoint changes or the data changes. However, you could theoretically explicitly set the XY location of the Callout, and update each at any given interval. Here is a contrived example of showing 2 callouts at the same time at a different location. The bit you'd need to work out is updating the various callouts to be in the right place all the time. This could involve some custom app code or even modification of the Callout.qml code itself.

 

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Esri.ArcGISRuntime
import Esri.ArcGISRuntime.Toolkit
import DemoApp

DemoPage {
    mapViewContents: Component {
        MapView {
            id:view

            Callout {
                id: callout
                calloutData : view.calloutData //binding to parent. Any change is reflected on this
                accessoryButtonVisible: false
                implicitHeight: 100
                leaderPosition: Callout.LeaderPosition.Automatic
                x: 200
                y: 200
                maxWidth: 250
                background: Rectangle {
                    radius: 5
                    border.width: 2
                    border.color: "black"
                }
                contentItem: Column {
                    spacing: 10
                    anchors.fill: parent
                    Text {
                        text: "Custom Callout"
                        font.bold: true
                        font.pixelSize: 18
                    }
                    Text {
                        text: "This is a custom callout"
                    }
                }
                palette.windowText: "black"
            }

            Callout {
                id: callout2
                calloutData : view.calloutData //binding to parent. Any change is reflected on this
                accessoryButtonVisible: false
                implicitHeight: 100
                leaderPosition: Callout.LeaderPosition.Automatic
                x: 350
                y: 350
                maxWidth: 250
                background: Rectangle {
                    radius: 5
                    border.width: 2
                    border.color: "black"
                }
                contentItem: Column {
                    spacing: 10
                    anchors.fill: parent
                    Text {
                        text: "Custom Callout 2"
                        font.bold: true
                        font.pixelSize: 18
                    }
                    Text {
                        text: "This is a custom callout 2"
                    }
                }
                palette.windowText: "black"
            }

            CalloutDemo {
                geoView: view
            }
        }
    }
}

(modification of https://github.com/Esri/arcgis-maps-sdk-toolkit-qt/blob/main/uitools/examples/cpp_quick/src/demos/Ca...)  

 

I wish we had something that worked for you right out of the box, but hopefully this gives you some ideas to pursue.