Take a screenshot of the map.
Use case
GIS users may want to export a screenshot of a map to enable sharing as an image or printing.
How to use the sample
Pan and zoom to find an interesting location, then tap the button to take a screenshot. The screenshot will be displayed. Note that there may be a small delay if the map is still rendering when you tap the button.
How it works
- Wait for the map view to finish rendering the map.
- Call
AGSMapView.exportImage(completion:)
to get aUIImage
object.
Relevant API
- AGSGeoView.exportImage(completion:)
- AGSMapView
Tags
capture, export, image, print, screen capture, screenshot, share, shot
Sample Code
MapViewScreenshotViewController.swift
// Copyright 2016 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import UIKit
import ArcGIS
class MapViewScreenshotViewController: UIViewController {
@IBOutlet private weak var mapView: AGSMapView!
@IBOutlet private weak var overlayParentView: UIView!
@IBOutlet private weak var overlayImageView: UIImageView!
var map: AGSMap!
var tapGestureRecognizer: UITapGestureRecognizer!
var shutterSound: SystemSoundID = 0
override func viewDidLoad() {
super.viewDidLoad()
// add the source code button item to the right of navigation bar
(self.navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["MapViewScreenshotViewController"]
// instantiate map with imagegry basemap
self.map = AGSMap(basemapStyle: .arcGISImageryStandard)
// assign the map to the map view
self.mapView.map = self.map
// initialize and assign tap gesture to hide overlay parent view
self.tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MapViewScreenshotViewController.hideOverlayParentView))
self.overlayParentView.addGestureRecognizer(self.tapGestureRecognizer)
// add border to the overlay image view
self.overlayImageView.layer.borderColor = UIColor.white.cgColor
self.overlayImageView.layer.borderWidth = 2
}
// MARK: - Actions
// hide the screenshot overlay view
@objc
func hideOverlayParentView() {
self.overlayParentView.isHidden = true
}
// show the screenshot overlay view
private func showOverlayParentView() {
self.overlayParentView.isHidden = false
}
// called when the user taps on the screenshot button
@IBAction private func screenshotAction(_ sender: AnyObject) {
// hide the screenshot view if currently visible
self.hideOverlayParentView()
// the method on map view we can use to get the screenshot image
self.mapView.exportImage { [weak self] (image: UIImage?, error: Error?) in
if let error = error {
self?.presentAlert(error: error)
}
if let image = image {
// on completion imitate flash
self?.imitateFlashAndPreviewImage(image)
}
}
}
// imitate the white flash screen when the user taps on the screenshot button
private func imitateFlashAndPreviewImage(_ image: UIImage) {
let flashView = UIView(frame: self.mapView.bounds)
flashView.backgroundColor = .white
self.mapView.addSubview(flashView)
// animate the white flash view on and off to show the flash effect
UIView.animate(
withDuration: 0.3,
animations: {
flashView.alpha = 0
},
completion: { [weak self] (_) in
// On completion play the shutter sound
self?.playShutterSound()
flashView.removeFromSuperview()
// show the screenshot on screen
self?.overlayImageView.image = image
self?.showOverlayParentView()
}
)
}
// to play the shutter sound once the screenshot is taken
func playShutterSound() {
if self.shutterSound == 0 {
if let filepath = Bundle.main.path(forResource: "Camera Shutter", ofType: "caf") {
let url = URL(fileURLWithPath: filepath)
AudioServicesCreateSystemSoundID(url as CFURL, &self.shutterSound)
}
}
AudioServicesPlaySystemSound(self.shutterSound)
}
deinit {
AudioServicesDisposeSystemSoundID(self.shutterSound)
}
}