efremidze / Cluster

Easy Map Annotation Clustering 📍
MIT License
1.27k stars 121 forks source link

Exact Same Location. #29

Closed kwstasna closed 7 years ago

kwstasna commented 7 years ago

Hey guys and very nice work! Congrats to all of you :clap: Although I have one question.

I'm running one app about Events. And some Venues have multiple Events in the exact same location (lat, lon) in the map. Do we have a workaround about it? Cause if i zoom in this location spot, the cluster doesn't break. And this is normal. Thanks a lot !

muh-azharudheen commented 7 years ago

same issue here

efremidze commented 7 years ago

thanks for reporting this, ill push a fix

efremidze commented 7 years ago

what do u prefer, displaying just one annotation there?

kwstasna commented 7 years ago

It would be great to show them all for example in a circle around the location.

muh-azharudheen commented 7 years ago

img_0079 issue is 2 annotation in exact place not showing can't zoom its showing the cluster only

MaeseppTarvo commented 7 years ago

It would be awesome to see something like this in this library: https://stackoverflow.com/questions/44698027/correctly-handle-clustering-when-markers-are-placed-identically-and-overlapping

My question was based on Google maps but I switched to AppleMaps and would like to use this library for clustering and would like to be able to make them appear in the circle like in the stackoverflow question.

efremidze commented 7 years ago

Thanks Ill fix asap.

Alex293 commented 7 years ago

That indeed would be a good solution !

kwstasna commented 7 years ago

Hello and thanks for the fix. I've updated the pod but now when i zoom the Cluster pin dissapears and there is no other regular pins. Can you point me if you changed anything to the example code ?

efremidze commented 7 years ago

I'm not seeing any issues. What device, iOS version, etc?

kwstasna commented 7 years ago

iPhone SE, iOS 10.3.3, Xcode 8.3.3, Swift 3

With the following custom code of mine.

import UIKit
import MapKit
import Cluster

class EventAnnotation : MKPointAnnotation {
    var myEvent:Events?
    var myRealmEvent:RealmEventNew?
}

extension CGRect{
    init(_ x:CGFloat,_ y:CGFloat,_ width:CGFloat,_ height:CGFloat) {
        self.init(x:x,y:y,width:width,height:height)
    }

}

class ClusterMapViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var eventCount: UILabel!

    let manager = ClusterManager()
    lazy var events = [Events]()
    var add: Double!
    var newLat: Double!
    var counter = 0
    var tileRenderer: MKTileOverlayRenderer!
    override func viewDidLoad() {
        super.viewDidLoad()

        mapView.delegate = self
        mapView.showsUserLocation = true
        mapView.setUserTrackingMode(.follow, animated: true)

        manager.minimumCountForCluster = 3
        manager.shouldRemoveInvisibleAnnotations = false
        for event in events {
            let eventpins = EventAnnotation()
            eventpins.myEvent = event // Here we link the event with the annotation
            eventpins.title = event.eventName
            eventpins.coordinate = CLLocationCoordinate2D(latitude: event.eventLat, longitude: event.eventLon)
manager.add(eventpins)

        eventCount.text = "\(events.count) Events Nearby"
    }

    @IBAction func goToUser(_ sender: Any) {
        self.mapView.setUserTrackingMode( MKUserTrackingMode.follow, animated: true)

    }
    deinit {
        print("deinit cluster")
        if events.isEmpty == false {
            events.removeAll(keepingCapacity: false)
        }
        mapView.mapType = .standard
        mapView.removeFromSuperview()
        mapView.delegate = nil
    }

    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
    {

        if overlay is MKTileOverlay
        {
            let renderer = MKTileOverlayRenderer(overlay:overlay)

            renderer.alpha = 0.8

            return renderer
        }
        return MKOverlayRenderer()
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        let reuseId:String
        switch annotation {
        case is MKUserLocation:
            return nil // blue pulsy dot
        case is ClusterAnnotation:
            reuseId = "Cluster"
            var clusterView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
            clusterView = ClusterAnnotationView.init(annotation: annotation, reuseIdentifier: reuseId, type:.color(UIColor.init(hexString: "#2E294E"), radius: 25))
            return clusterView
        default:
            reuseId = "Pin"
            var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
            if pinView != nil {
                pinView!.annotation = annotation
            } else {
                pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)

                pinView!.image = UIImage.init(named: "pin")
                pinView!.canShowCallout = false
            }
            return pinView
        }
    }

    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        manager.reload(mapView, visibleMapRect: mapView.visibleMapRect)
    }

    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        guard let annotation = view.annotation else { return }
        if view.annotation!.isKind(of: MKUserLocation.self){
            return
        }
        if let cluster = annotation as? ClusterAnnotation {
            mapView.removeAnnotations(mapView.annotations)

            var zoomRect = MKMapRectNull
            for annotation in cluster.annotations {
                let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
                let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)
                if MKMapRectIsNull(zoomRect) {
                    zoomRect = pointRect
                } else {
                    zoomRect = MKMapRectUnion(zoomRect, pointRect)
                }
            }
            manager.reload(mapView, visibleMapRect: zoomRect)
            mapView.setVisibleMapRect(zoomRect, animated: true)
        } else if let eventAnnotation = view.annotation as? EventAnnotation {
                    let theEvent = eventAnnotation.myEvent
                    let customView = (Bundle.main.loadNibNamed("CustomCalloutView", owner: self, options: nil))?[0] as! CustomCalloutView;
                    let calloutViewFrame = customView.frame;
                    customView.frame = CGRect(x: -calloutViewFrame.size.width/2.23, y: -calloutViewFrame.size.height-7, width: 315, height: 200)
                    customView.configureCell(events: theEvent!)

                    view.addSubview(customView)

                }
    }

    func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView)
    {
        for childView:AnyObject in view.subviews{
            childView.removeFromSuperview();
        }
    }

}
extension UIImage {

    func filled(with color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        color.setFill()
        guard let context = UIGraphicsGetCurrentContext() else { return self }
        context.translateBy(x: 0, y: size.height)
        context.scaleBy(x: 1.0, y: -1.0);
        context.setBlendMode(CGBlendMode.normal)
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        guard let mask = self.cgImage else { return self }
        context.clip(to: rect, mask: mask)
        context.fill(rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }

}

class BorderedClusterAnnotationView: ClusterAnnotationView {
    let borderColor: UIColor

    init(annotation: MKAnnotation?, reuseIdentifier: String?, type: ClusterAnnotationType, borderColor: UIColor) {
        self.borderColor = borderColor
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier, type: type)
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func configure(with type: ClusterAnnotationType) {
        super.configure(with: type)

        switch type {
        case .image:
            layer.borderWidth = 0
        case .color:
            layer.borderColor = borderColor.cgColor
            layer.borderWidth = 2
        }
    }
}
efremidze commented 7 years ago

where do u add annotations? manager.add(eventpins)

simulator screen shot - iphone 7 - 2017-09-19 at 12 25 49

kwstasna commented 7 years ago

Accidentaly deleted it on edit. Although on my code i have it properly.

I edited the above comment. This is the issue with images. On the first image you can see that there are 19 pins inside a cluster.

21769841_10212560663184140_1153705894_n

and when i tap the cluster

21905402_10212560662744129_453762582_n

there are no pins on the map!

efremidze commented 7 years ago

ur removing all the annotations on select? mapView.removeAnnotations(mapView.annotations)

kwstasna commented 7 years ago

If i comment this line, then when i select the Cluster, it is still there! So i only remove the clusters. and not the normal pins

efremidze commented 7 years ago

I'm still not seeing that issue.

demo.zip

kwstasna commented 7 years ago

@efremidze don't forget that in your example inside this repo, there are no pins on the exact same location. This is my issue, that even after the update of the pod, the pins that are in the exact same location don't show up!

efremidze commented 7 years ago

Ill add pins in the same location and try to reproduce.

sasha9878 commented 6 years ago

Any solution for this ?