summaryrefslogtreecommitdiff
path: root/platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift')
-rw-r--r--platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift141
1 files changed, 141 insertions, 0 deletions
diff --git a/platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift b/platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift
new file mode 100644
index 0000000000..66ba7c0481
--- /dev/null
+++ b/platform/ios/demo/Examples/Swift/UserTrackingModesExample.swift
@@ -0,0 +1,141 @@
+import Mapbox
+
+@objc(UserTrackingModesExample_Swift)
+
+class UserTrackingModesExample_Swift: UIViewController, MGLMapViewDelegate {
+ var mapView: MGLMapView!
+ @IBOutlet var button: UserLocationButton!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ mapView = MGLMapView(frame: view.bounds, styleURL: MGLStyle.darkStyleURL(withVersion: 9))
+ mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ mapView.delegate = self
+
+ mapView.tintColor = .red
+ mapView.attributionButton.tintColor = .lightGray
+
+ view.addSubview(mapView)
+
+ setupLocationButton()
+ }
+
+ func mapView(_ mapView: MGLMapView, didChange mode: MGLUserTrackingMode, animated: Bool) {
+ button.updateArrow(for: mode)
+ }
+
+ @IBAction func locationButtonTapped() {
+ var mode: MGLUserTrackingMode
+
+ switch (mapView.userTrackingMode) {
+ case .none:
+ mode = .follow
+ break
+ case .follow:
+ mode = .followWithHeading
+ break
+ case .followWithHeading:
+ mode = .followWithCourse
+ break
+ case .followWithCourse:
+ mode = .none
+ break
+ }
+
+ mapView.userTrackingMode = mode
+ }
+
+ func setupLocationButton() {
+ button = UserLocationButton()
+ button.addTarget(self, action: #selector(locationButtonTapped), for: .touchUpInside)
+ button.tintColor = mapView.tintColor
+ view.addSubview(button)
+
+ // Do some basic auto layout.
+ button.translatesAutoresizingMaskIntoConstraints = false
+
+ let constraints = [
+ NSLayoutConstraint(item: button, attribute: .top, relatedBy: .greaterThanOrEqual, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 10),
+ NSLayoutConstraint(item: button, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 10),
+ NSLayoutConstraint(item: button, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: button.frame.size.height),
+ NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: button.frame.size.width)
+ ]
+
+ view.addConstraints(constraints)
+ }
+
+}
+
+class UserLocationButton : UIButton {
+ private let size: CGFloat = 80
+ private var arrow: CAShapeLayer?
+
+ required init() {
+ super.init(frame: CGRect(x: 0, y: 0, width: size, height: size))
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func layoutSubviews() {
+ backgroundColor = UIColor.black.withAlphaComponent(0.5)
+ layer.cornerRadius = 4
+
+ layoutArrow()
+ }
+
+ private func layoutArrow() {
+ if arrow == nil {
+ let arrow = CAShapeLayer()
+ arrow.path = arrowPath()
+ arrow.bounds = CGRect(x: 0, y: 0, width: size / 2, height: size / 2)
+ arrow.position = CGPoint(x: size / 2, y: size / 2)
+ arrow.shouldRasterize = true
+ arrow.rasterizationScale = UIScreen.main.scale
+ arrow.drawsAsynchronously = true
+
+ self.arrow = arrow
+ updateArrow(for: .none)
+ layer.addSublayer(self.arrow!)
+ }
+ }
+
+ private func arrowPath() -> CGPath {
+ let max: CGFloat = size / 2
+
+ let bezierPath = UIBezierPath()
+ bezierPath.move(to: CGPoint(x: max * 0.5, y: 0))
+ bezierPath.addLine(to: CGPoint(x: max * 0.1, y: max))
+ bezierPath.addLine(to: CGPoint(x: max * 0.5, y: max * 0.65))
+ bezierPath.addLine(to: CGPoint(x: max * 0.9, y: max))
+ bezierPath.addLine(to: CGPoint(x: max * 0.5, y: 0))
+ bezierPath.close()
+
+ return bezierPath.cgPath
+ }
+
+ func updateArrow(for mode: MGLUserTrackingMode) {
+ var stroke: CGColor
+ switch (mode) {
+ case .none:
+ stroke = UIColor.white.cgColor
+ case .follow:
+ stroke = tintColor.cgColor
+ case .followWithHeading, .followWithCourse:
+ stroke = UIColor.clear.cgColor
+ }
+ arrow!.strokeColor = stroke
+
+ // Re-center the arrow, based on its current orientation.
+ arrow!.position = (mode == .none || mode == .followWithCourse) ? CGPoint(x: size / 2, y: size / 2) : CGPoint(x: size / 2 + 2, y: size / 2 - 2)
+
+ arrow!.fillColor = (mode == .none || mode == .follow) ? UIColor.clear.cgColor : tintColor.cgColor
+
+ let rotation: CGFloat = (mode == .follow || mode == .followWithHeading) ? 0.66 : 0
+ arrow!.setAffineTransform(CGAffineTransform.identity.rotated(by: rotation))
+
+ layoutIfNeeded()
+ }
+}