Search code examples
iosgoogle-mapsgoogle-maps-sdk-ios

Google-SDK-iOS Polygon with Hole


Hy, i am trying to achieve this, but in iOS:

Donut Google Maps Android

Basically the main idea is to have a zone highlighted and the rest faded. This is a requested feature in the Google-SDk-iOS, https://code.google.com/p/gmaps-api-issues/issues/detail?id=5464

So far what i've done:

  • Set the mapview alpha to a low value (Transparency)
  • Draw a simple circle using google sdk GMSCircle on that view

But what this achieves is the inside of the circle also fades out. Any ideas or workarounds would me much appreciated, thank you.


Solution

  • Unfortunately, you can not make a hole in GMSPolygon for iOS yet, this feature is only available in Android.

    A workaround will be using pointForCoordinate() method from GMSProjection class. This method can convert a Earth coordinate to a point in your application's window.

    Also, in order to make the hole transparent, you probably need to use CAShapeLayer in your view. You can see more details in this StackOverflow answer.

    Sample code:

    class ViewController: UIViewController, GMSMapViewDelegate {
    
        var mapView: GMSMapView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let camera = GMSCameraPosition.cameraWithLatitude(-33.86,
                longitude: 151.20, zoom: 10)
            mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
            mapView.myLocationEnabled = true
            self.view = mapView
    
            self.mapView.delegate = self
        }
    
        func mapView(mapView: GMSMapView!, didChangeCameraPosition position: GMSCameraPosition!) {
            let point = mapView.projection.pointForCoordinate(CLLocationCoordinate2DMake(-33.86, 151.20))
            print("the screen point: \(point.x) \(point.y)")
    
    
            for subview in view.subviews {
                if subview.tag == 1 {
                    subview.layer.mask = nil
                    createHole(subview, holeX: point.x, holeY: point.y, radius: 100)
                }
            }
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
    
            let overlayView = UIView(frame: view.bounds)
            overlayView.tag = 1
            overlayView.alpha = 0.6
            overlayView.backgroundColor = UIColor.blackColor()
            overlayView.userInteractionEnabled = false
            self.view.addSubview(overlayView)
        }
    
    
        func createHole(overlayView : UIView, holeX : CGFloat, holeY : CGFloat, radius: CGFloat)
        {
            let maskLayer = CAShapeLayer()
    
            // Create a path with the rectangle in it.
            let path = CGPathCreateMutable()
    
            CGPathAddArc(path, nil, holeX, holeY, radius, 0.0, 2 * 3.14, false)
            CGPathAddRect(path, nil, CGRectMake(0, 0, overlayView.frame.width, overlayView.frame.height))
    
            maskLayer.backgroundColor = UIColor.blackColor().CGColor
    
            maskLayer.path = path;
            maskLayer.fillRule = kCAFillRuleEvenOdd
    
            overlayView.layer.mask = maskLayer
            overlayView.clipsToBounds = true
        }
    }
    

    enter image description here