Markers
Using Mappedin SDK for iOS with your own map requires a Pro license. Try a demo map for free or refer to the Pricing page for more information.
Mappedin SDK for iOS allows adding and removing Marker on a map. Markers are elements containing HTML that the Mappedin SDK anchors to any Anchorable target. They are automatically rotated and repositioned when the camera moves.
A complete example demonstrating Markers can be found in the Mappedin iOS Github repo: MarkersDemoViewController.swift

Note that the MapView class instantiates the Markers class and exposes it as MapView.markers. Use MapView.markers to utilize Markers' methods.
Creating Markers
Markers are added to the map by referencing a target that can be a Door, Space, Coordinate or any Anchorable target. The following code sample adds a marker to a coordinate.
let opts = AddMarkerOptions(
interactive: .True,
placement: .single(.center),
rank: .tier(.high)
)
let markerHtml = """
<div>
This is a Marker!
</div>
"""
self.mapView.markers.add(target: coordinate, html: markerHtml, options: opts) { _ in }
Placement
Marker placement is set using the options argument of Markers.add(). Options accepts a AddMarkerOptions value, which has a member named placement. When provided, the point of the Marker described by the Placement is placed next to the target. For example, using center will place the Marker's center at the target. Both a single placement and an array of placements can be provided. When an array is provided, the Marker is placed at the first target that has space available to display the Marker. Placement positions are defined in MarkerPlacement which contains 9 values. The placement points are as follows, with the default being center.
MarkerPlacement
centertopleftbottomrighttopLefttopRightbottomLeftbottomRight
Marker content can be styled using CSS that references the placement of the marker. This can allow the creation of a tooltip or bubble-style marker that points to its target. This is done by using the CSS Selector:
.mappedin-marker[data-placement='<PLACEMENT>'];
Where <PLACEMENT> is the placement position. Here is an example of adding a triangle pointer to the Marker's target of left:
.marker:before {
content: '';
width: 0;
height: 0;
top: calc(50% - 10px);
left: -10px;
z-index: 1;
position: absolute;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
z-index: -1;
}
.mappedin-marker[data-placement="left"] .marker:before {
left: auto;
right: -5px;
border-left: 10px solid #333333;
}
Removing Markers
Markers can be removed individually by using the Markers.remove(marker) method, passing in the marker to be removed as shown below.
mapView.markers.remove(marker: marker) { _ in }
To remove all markers from a map, call Markers.removeAll().
mapView.markers.removeAll() { _ in }
Marker Rank
Ranking can be added to markers to control which marker will be shown when more than one marker occupies the same space. The marker with the highest rank will be shown. If markers do not overlap, ranking will have no effect. Rank values low, medium, high and always-visible as defined in CollisionRankingTier.
The code below adds markers where a user clicks on the map. The marker rank is cycled with each click. If the user clicks and adds multiple markers in the same location, the marker with the highest rank is shown and lower ranking markers are hidden.
// Ranks for marker collision priority - cycles through medium, high, always-visible
private let ranks: [CollisionRankingTier] = [.medium, .high, .alwaysVisible]
private var rankIndex = 0
...
// Act on the click event and add a marker with a cycling rank.
// Observe how higher ranking markers are shown when they collide with lower ranking markers.
mapView.on(Events.click) { [weak self] event in
guard let self = self else { return }
guard let clickPayload = event as? ClickPayload else { return }
let currentRank = self.ranks[self.rankIndex]
let rankName = currentRank.rawValue
let markerTemplate = """
<div>
<style>
.marker {
display: flex;
align-items: center;
background-color: #fff;
max-height: 64px;
border: 2px solid grey;
padding: 4px 12px;
font-weight: bold;
font-family: sans-serif;
}
.marker img {
max-width: 64px;
max-height: 32px;
object-fit: contain;
margin-right: 12px;
}
</style>
<div class="marker">
<p>Marker Rank: \(rankName)</p>
</div>
</div>
"""
// Add a marker with the current rank at the clicked coordinate.
self.mapView.markers.add(
target: clickPayload.coordinate,
html: markerTemplate,
options: AddMarkerOptions(rank: .tier(currentRank))
)
// Cycle to the next rank
self.rankIndex += 1
if self.rankIndex == self.ranks.count {
self.rankIndex = 0
}
}
Moving Markers
Markers can be repositioned after they have been added to a map. There are two ways of doing this:
- Markers.setPosition() instantly repositions a Marker
- Markers.animateTo() animates a Marker to a new position
The Marker's position can be set to a Coordinate, Space or Door.
The animateTo method takes an options parameter of AnimationOptions that defines the animation duration and EasingFunction, which can be EasingFunction.linear, EasingFunction.easeIn, EasingFunction.easeOut or EasingFunction.easeInOut.
- Linear: This function implies a constant rate of change. It means the animation proceeds at the same speed from start to end. There's no acceleration or deceleration, giving a very mechanical feel.
- Ease In: This function causes the animation to start slowly and then speed up as it progresses. Initially, there's gradual acceleration, and as the function moves forward, the rate of change increases.
- Ease Out: Contrary to ease-in, ease-out makes the animation start quickly and then slow down towards the end. It begins with a faster rate of change and gradually decelerates.
- Ease In Out: This function combines both ease-in and ease-out. The animation starts slowly, speeds up in the middle, and then slows down again towards the end. It offers a balance of acceleration and deceleration.
The code samples below displays a custom Marker when the map is first clicked. When the map is clicked again, the Marker is animated to the clicked location using the default animation options.
private var marker: Marker?
...
mapView.on(Events.click) { [weak self] payload in
guard let self = self,
let click = payload as? ClickPayload else { return }
let coordinate = click.coordinate
if let existingMarker = self.marker {
// Animate existing marker to new position
self.mapView.markers.animateTo(marker: existingMarker, target: coordinate)
} else {
// Add new marker at clicked position
let options = AddMarkerOptions(
interactive: .True,
placement: .single(.right)
)
self.mapView.markers.add(target: coordinate, html: "Marker", options: options) { result in
if case .success(let newMarker) = result {
self.marker = newMarker
}
}
}
}
Enabling and Disabling Markers
Markers can be dynamically enabled or disabled using MapView.updateState(). When a marker is disabled, it will be hidden from view but remain in the map's memory. This is useful for managing marker visibility based on conditions like zoom level or user interaction, without the overhead of repeatedly adding and removing markers.
Use MapView.getState() to check a marker's current state, which returns the marker's current properties including its enabled status.
Here's an example on how to enable/disable markers on click:
private var marker: Marker?
...
mapView.on(Events.click) { [weak self] payload in
guard let self = self,
let click = payload as? ClickPayload else { return }
let coordinate = click.coordinate
if self.marker == nil {
// First click - add marker
print("Adding marker at: \(coordinate)")
self.mapView.markers.add(
target: coordinate,
html: "<div class='markerContainer'>Enabled Marker!</div>"
) { result in
if case .success(let newMarker) = result {
self.marker = newMarker
}
}
} else {
// Get current state of marker
self.mapView.getState(marker: self.marker!) { result in
if case .success(let markerState) = result {
print("Current Marker State: \(String(describing: markerState))")
// Toggle enabled state
let newState = !(markerState?.enabled ?? true)
self.mapView.updateState(marker: self.marker!, state: MarkerUpdateState(enabled: newState))
print("Marker is now \(newState ? "enabled" : "disabled")")
}
}
}
}
A complete example demonstrating Markers can be found in the Mappedin iOS Github repo: MarkersDemoViewController.swift