Map Objects

The MapKit SDK lets developers display objects on a map. All map objects are customizable, facilitating unique user scenarios tailored to the developer needs.

Placemarks

Add custom image placemarks to the map with the YMKMapObjectCollection.addPlacemark() method from the YMKMap.mapObjects field.

The method accepts the YMKPoint with coordinates for the placemark and the UIImage instance.

let placemark = map.mapObjects.addPlacemark()
placemark.geometry = YMKPoint(latitude: 59.935493, longitude: 30.327392)
placemark.setIconWith(UIImage(named: "icon_dollar")!)

The code above creates an instance of the YMKPlacemarkMapObject class that extends the YMKMapObject interface.

The YMKMapObject interface represents every visible object on the map. There are a few ways to configure map objects: changing visibility, allowing dragging, changing a z-index, setting a tap or drag event listener, and more.

For more details, see the YMKMapObject documentation.

Setting text

You can create text labels near placemarks. Use the YMKPlacemarkMapObject.setTextWithText(_:) method.

Use YMKTextStyle to change how labels look, including their text size, color, and position relative to the icon.

placemark.setTextWithText(
    "Special place",
    style: {
        let textStyle = YMKTextStyle()
        textStyle.size = 10.0
        textStyle.placement = .right
        textStyle.offset = 5.0
        return textStyle
    }()
)

Icon styles

You can customize how placemark icons are presented using the YMKIconStyle class. It lets you change the icon's anchor position, size, rotation type, z-index, tappable area, visibility, and flatness to the map.

let iconStyle = YMKIconStyle()
iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5))
iconStyle.scale = 0.6

let placemark = map.mapObjects.addPlacemark()
placemark.geometry = point
placemark.setIconWith(image, style: iconStyle)

Composite icons

Combine multiple icons to create a composite one.

  1. Create a default icon using YMKMapObjectCollection.addPlacemark() method.

  2. Call YMKPlacemarkMapObject.useCompositeIcon() to create a composite icon.

  3. Use YMKCompositeIcon.setIconWithName(_:image:style:) to add a new icon to the composite icon.

Complete sample code for creating a composite icon:

let placemark = map.mapObjects.addPlacemark()
placemark.geometry = GeometryProvider.compositeIconPoint
placemark.addTapListener(with: singlePlacemarkTapListener)
placemark.setTextWithText(
    "Special place",
    style: {
        let textStyle = YMKTextStyle()
        textStyle.size = 10.0
        textStyle.placement = .right
        textStyle.offset = 5.0
        return textStyle
    }()
)

let compositeIcon = placemark.useCompositeIcon()
compositeIcon.setIconWithName(
    "pin",
    image: UIImage(named: "icon_dollar")!,
    style: {
        let iconStyle = YMKIconStyle()
        iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 1.0))
        iconStyle.scale = 0.9
        return iconStyle
    }()
)
compositeIcon.setIconWithName(
    "point",
    image: UIImage(named: "icon_circle")!,
    style: {
        let iconStyle = YMKIconStyle()
        iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5))
        iconStyle.scale = 0.5
        iconStyle.flat = true
        return iconStyle
    }()
)

The result:

Composite icon example

Animated placemarks

You can create an animated placemark from an animated png file.

  1. Create the placemark using YMKMapObjectCollection.addPlacemark().

    let animatedPlacemark = pinsCollection.addPlacemark()
    animatedPlacemark.geometry = GeometryProvider.animatedImagePoint
    
  2. Call the YMKPlacemarkMapObject.useAnimation() method to create an animation object. Set the animation resource using the YRTAnimatedImageProvider instance.

    let animatedImageProvider = YRTAnimatedImageProviderFactory.fromFile(
        Bundle.main.path(forResource: "animation", ofType: "png")
    ) as! YRTAnimatedImageProvider
    
    let animation = animatedPlacemark.useAnimation()
    animation.setIconWithImage(animatedImageProvider)
    
  3. Start the animation, managing it with the YMKPlacemarkAnimation object.

    animation.play()
    

Placemark collections

Placemark collections are used to group multiple placemarks into a new collection of nested map objects.

  1. To create a collection of nested map objects, use the YMKMapObjectCollection.add() method.

    let pinsCollection = map.mapObjects.add()
    
  2. From now, you can use your new pinsCollection to display placemarks and other map objects.

    GeometryProvider.placemarkPoints.enumerated().forEach { pair in
        let point = pair.element
    
        let image = UIImage(named: "icon_dollar")!
    
        let placemark = map.mapObjects.addPlacemark()
        placemark.geometry = point
        placemark.setIconWith(image)
    
        placemark.isDraggable = true
    }
    

    What it looks like after placemarks were added to a collection of new map objects:

    Map with placemark collection

After creating pinCollection, you can add pins to it the same way as for YMKMap.mapObjects since they have the same YMKMapObjectCollection type.

Note

The YMKMapObjectCollection interface extends YMKMapObject. That is why it is allowed to create nested collections and add them to another collections.

All methods that have the YMKMapObject interface are also available in YMKMapObjectCollection.

You can iterate through YMKMapObjectCollection elements using the YMKBaseMapObjectCollection.traverse(with:) method.

Geometries

The MapKit SDK lets you draw primitive geometric objects like polygons, polylines, and circles on the map. They're all customizable, and they implement the YMKMapObject interface.

Polygons

Use a polygon when you need to display a map area to users.

  1. Start by creating a YMKPolygon instance.

    static let polygon: YMKPolygon = {
        var points = [
            YMKPoint(latitude: 59.935493, longitude: 30.327392),
            YMKPoint(latitude: 59.938185, longitude: 30.32808),
            YMKPoint(latitude: 59.937376, longitude: 30.33621),
            YMKPoint(latitude: 59.934517, longitude: 30.335059)
        ]
    
        points.append(points[0])
    
        let outerRing = YMKLinearRing(points: points)
    
        return YMKPolygon(outerRing: outerRing, innerRings: [])
    }()
    
  2. Use the YMKMapObjectCollection.addPolygon(with:) method to create a polygon map object.

    polygonMapObject = collection.addPolygon(with: GeometryProvider.polygon)
    

    After the build is complete, you will see a default-styled polygon:

    Map with default polygon

  3. Define inner points while creating a polygon to exclude a section on the inside of the polygon.

    static let polygon: YMKPolygon = {
        var points = [
            YMKPoint(latitude: 59.935493, longitude: 30.327392),
            YMKPoint(latitude: 59.938185, longitude: 30.32808),
            YMKPoint(latitude: 59.937376, longitude: 30.33621),
            YMKPoint(latitude: 59.934517, longitude: 30.335059)
        ]
    
        points.append(points[0])
        let outerRing = YMKLinearRing(points: points)
    
        var innerPoints = [
            YMKPoint(latitude: 59.937487, longitude: 30.330034),
            YMKPoint(latitude: 59.936688, longitude: 30.33127),
            YMKPoint(latitude: 59.937116, longitude: 30.33328),
            YMKPoint(latitude: 59.937704, longitude: 30.331842)
        ]
    
        innerPoints.append(innerPoints[0])
        let innerRing = YMKLinearRing(points: innerPoints)
    
        return YMKPolygon(outerRing: outerRing, innerRings: [innerRing])
    }()
    

    Polygon with inner points:

    Map with polygon using inner points

  4. Let's change the default fill color and stroke using the YMKPolygonMapObject instance we created.

    polygonMapObject.strokeWidth = 1.5
    polygonMapObject.strokeColor = Palette.olive
    polygonMapObject.fillColor = Palette.oliveTransparent
    

    Map with styled polygon

For more details on how to configure polygons, see the YMKPolygonMapObject documentation.

Polylines

Polylines are often used to display routes and trajectories.

  1. Create a YMKPolyline instance with the geometry you're looking for and add a polyline map object to the map using the YMKMapObjectCollection.addPolyline(with:) method.

    let polyline: YMKPolyline = {
        YMKPolyline(
            points: [
                YMKPoint(latitude: 59.935493, longitude: 30.327392),
                YMKPoint(latitude: 59.938185, longitude: 30.32808),
                YMKPoint(latitude: 59.937376, longitude: 30.33621),
                YMKPoint(latitude: 59.934517, longitude: 30.335059)
            ]
        )
    }()
    
    let polylineMapObject = collection.addPolyline(with: polyline)
    
  2. Configure polyline styles using the YMKPolylineMapObject variable.

    polylineMapObject.strokeWidth = 5.0
    polylineMapObject.setStrokeColorWith(.gray)
    polylineMapObject.outlineWidth = 1.0
    polylineMapObject.outlineColor = .black
    

    Once you've added the polyline to the map:

    Map with the added polyline

For more details, see the YMKPolylineMapObject documentation.

Circles

Circles are used to display circular areas.

  1. Create a YMKCircle instance with the geometry you're looking for: a center point and a radius in meters.

    var circleWithRandomRadius: YMKCircle {
        YMKCircle(center: YMKPoint(latitude: 59.935493, longitude: 30.327392), radius: 400.0)
    }
    
  2. Using the YMKMapObjectCollection.addCircle(with:stroke:strokeWidth:fill:) method, add a circle object to the map.

    let circle = pinsCollection.addCircle(with: GeometryProvider.circleWithRandomRadius)
    circle.strokeColor = Palette.red
    circle.strokeWidth = 2.0
    circle.fillColor = Palette.redTransparent
    

    After adding a circle to the map:

    Map with the circle

For more details on how to configure a circular map object, see the YMKCircleMapObject documentation.

Clusters

Clusterized collections are used to display multiple placemarks.

  1. Start by creating a YMKClusterListener with a single YMKClusterListener.onClusterAdded(with:) method that controls the appearance of the cluster on the map.

    final class ClusterListener: NSObject, YMKClusterListener, YMKClusterTapListener {
    // MARK: - Constructor
    
    init(controller: UIViewController) {
        self.controller = controller
    }
    
    // MARK: - Public methods
    
    func onClusterTap(with cluster: YMKCluster) -> Bool {
        AlertPresenter.present(
            from: controller,
            with: "Tapped the cluster",
            message: "With \(cluster.size) items"
        )
        return true
    }
    
    func onClusterAdded(with cluster: YMKCluster) {
        let placemarks = cluster.placemarks.compactMap { $0.userData as? PlacemarkUserData }
        cluster.appearance.setViewWithView(YRTViewProvider(uiView: ClusterView(placemarks: placemarks)))
        cluster.addClusterTapListener(with: self)
    }
    
    // MARK: - Private properties
    
    private weak var controller: UIViewController?
    }
    

    The YMKCluster.appearance property returns a YMKPlacemarkMapObject object. In our example, we're using the YMKPlacemarkMapObject.setViewWithView(_:) method to change how the cluster looks.

    ClusterView is a custom defined class. Check out its implementation in out Github repository.

  2. Create a new nested collection using the YMKMapObjectCollection.addClusterizedPlacemarkCollection(with:) method.

    clusterizedCollection = collection.addClusterizedPlacemarkCollection(with: clusterListener)
    
  3. Add multiple placemarks to the new clusterizedCollection.

    GeometryProvider.clusterizedPoints.enumerated().forEach { pair in
        let index = pair.offset
        let point = pair.element
    
        let type = PlacemarkType.random
        let image = type.image
    
        let iconStyle = YMKIconStyle()
        iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5))
        iconStyle.scale = 0.6
    
        let placemark = clusterizedCollection.addPlacemark()
        placemark.geometry = point
        placemark.setIconWith(image, style: iconStyle)
    
        placemark.isDraggable = true
        placemark.setDragListenerWith(mapObjectDragListener)
        placemark.userData = PlacemarkUserData(name: "Data_\(index)", type: type)
        placemark.addTapListener(with: mapObjectTapListener)
    }
    
  4. Call the YMKClusterizedPlacemarkCollection.clusterPlacemarks(withClusterRadius:minZoom:) method. It accepts two arguments:

    • clusterRadius: the minimum distance in units between objects that remain in separate clusters.
    • minZoom: the minimum zoom level that displays clusters.
    clusterizedCollection.clusterPlacemarks(withClusterRadius: Const.clusterRadius, minZoom: Const.clusterMinZoom)
    

    Warning

    The YMKClusterizedPlacemarkCollection.clusterPlacemarks(withClusterRadius:minZoom:) should be called explicitly whenever placemarks are added to or removed from clusterized collections.

    Otherwise, clusterized placemarks will be not re-rendered.

    Clusterized placemarks at different zooms:

    Clusters

Source code

For full code samples from the tutorial, see the MapObjects application in our GitHub repository.