I need to change radius of my MKCircle continuously as user pinches on the screen. As its radius property is read-only, I am removing and recreating the circle and the renderer continuously, which, I believe, causes "flickering" effect when user pinches. It continuously appears/disappears when "animating" which looks really bad visually, creating a crappy UX. Here is my code:
//this method may be called many times a second.
-(void)refreshRadius{ //called when user pinches after updating to correct radius.
if(radiusCircle){
[self.mapView removeOverlay:radiusCircle];
}
radiusCircle = [MKCircle circleWithCenterCoordinate:userCoordinates radius:radius];
[self.mapView addOverlay:radiusCircle level:MKOverlayLevelAboveLabels];
}
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if(overlay == radiusCircle){
MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithCircle:radiusCircle];
renderer.strokeColor = [UIColor colorWithWhite:1 alpha:0.5];
renderer.lineWidth = 0.8;
renderer.fillColor = [UIColor colorWithRed:0.3 green:0.36 blue:0.7 alpha:0.2];
return renderer;
}else{
return nil;
}
}
How can I "animate" the radius smoothly on scale?
After a bit experimenting, I've luckily found a solution. However, while it works perfectly now, it's prone to future internal changes in iOS SDK. I've first set the read-only property "radius" using KVC. Then, I've invalidated my renderer's path, causing it to redraw itself immediately using the new radius. It is not the most-smooth-60FPS-animation-ever but it works really nicely. Here is the code:
[radiusCircle setValue:#(radius) forKey:#"radius"];
[renderer invalidatePath];
radiusCircle is my MKCircle instance, and renderer is my circle renderer. It works.
Related
I am trying to add a circular region on my MKMapView like the picture below for my current location. I can pin the map with annotations but don't know how to get it to show a circular region like this with a radius and have it shaded.
So I figured it out...
Below is how I did it along with code.
Step 1: - Create MKCircle
MKCircle *circleOverlay = [MKCircle circleWithCenterCoordinate:zoomLocation radius:300];//radius in meters
Step 2: - Set title and add to Map Overlays
[circleOverlay setTitle:#"Circle1"];
[_mapView addOverlay:circleOverlay];
Step 3: - Implement the mapView:rendererForOverlay: method in my MapViewDelegate
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if ([overlay isKindOfClass:[MKCircle class]])
{
MKCircleRenderer* aRenderer = [[MKCircleRenderer alloc] initWithCircle:(MKCircle *)overlay];
aRenderer.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
aRenderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
aRenderer.lineWidth = 3;
return aRenderer;
}else{
return nil;
}
}
That was it! Boom! Hope it helps someone in the future! Not sure if this is the best way but it achieve my goal!
Edit: make sure to set your mapView's delegate to self or the required delegate method will not be called.
I am drawing x amount of lines on an MKMapView. The data is being downloaded from a webservice and for each line that needs drawing I am creating a MKPolyline, adding it to an overlayArray (some overlays have more than one polyline) and finally adding that overlay to the map via:
[self.mapView addOverlays:overlayArray];`
The next function is therefore called which works wonderfully:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
if (![overlay isKindOfClass:[MKPolygon class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
renderer.strokeColor = [lineColours objectForKey:route.title];
renderer.lineWidth = 3.0;
return renderer;
} else {
return nil;
}
}
As you can see, the strokeColor gets the correct UIColor from a pre-defined NSMutableDictionary. This all works as expected.
However, some of the lines overlap and using a single colour is not always desired. I was wondering if there was a way of creating a line made up of two or even 3 colours, but not a gradient along the line as seen in many fitness apps, but colours across the line. For example, another use would be to draw a motorway route made up of two white lines with a transparent strip in the middle.
This is quite important for an app I am developing so I will post any findings I find here, and I hope that other people can share their thoughts and knowledge too.
I am making the navigation application by drawing a direction between 2 points. I successfully archive the functionality.
But the direction line is drawn on top of the road label and that label cannot be read as show in the picture below.
this is my code to draw overlay
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKPolylineView *overlayView = [[MKPolylineView alloc] initWithPolyline:overlay];
overlayView.lineWidth = 10.0f;
//overlayView.strokeColor = [[UIColor redColor] colorWithAlphaComponent:0.5f];
overlayView.strokeColor = [UIColor redColor];
return overlayView;
}
I can overcome this with a transparent line but it is not the efficient way.
The best way is to draw the line between the map layer and label layer of MKMapView but i don't know how can i archive that.
So any help please.
Thanks.
Assuming you are writing this for iOS maps (not google maps as you tagged the question) and using iOS 7 then when you add the overlay to the map view you have the option of defining which level it is on addOverlay:level:. The levels are defined in the MKMapView class reference
[theMapView addOverlay:theOverlay level:MKOverlayLevelAboveRoads];
I have seen this question posed before and all responses appear largely similar. However, I am simply unable to get any of them to work for my project.
I have an action, updateMap, that is triggered by a button. It shows current location on map (MapKit), and shows some other info relative to their location (geocoding). All of that works fine. What I need to do though is show a radius around their location on the map. Here is what I'm trying that isn't working:
(in updateMap)
//display radius
CLLocationCoordinate2D center = {current.coordinate.latitude, current.coordinate.longitude};
MKCircle *circle = [MKCircle circleWithCenterCoordinate:center radius:1000];
[self.mapView addOverlay:circle];
("current" is a CLLocation var that has the user's current location)
Then, after the action in the implementation file I have this:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKCircleView *circleView = [[MKCircleView alloc] initWithOverlay:overlay];
[circleView setFillColor:[UIColor redColor]];
[circleView setStrokeColor:[UIColor blackColor]];
[circleView setAlpha:0.5f];
return circleView;
}
It builds fine, but no circle is ever shown on the map.
Other solutions on this site involved putting the first code shown in the viewDidLoad method, but since the location hasn't been calculated yet (only determined within above-mentioned action) that isn't an option for me.
I appreciate your time and any help you can provide. I'm by no means on the level of many on here so please excuse me if this has an obvious answer. I'm not wanting to be spoon fed, I'm wanting to learn! Thanks for reading.
I have an overlay on the map, and I would like to change its coordinates. To do this seamlessly I'm going to call the setNeedsDisplayInMapRect: method after the change has been made to the view.
I've tested this out by just changing the fillColor and it works fine:
overlayView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.3];
[overlayView setNeedsDisplayInMapRect:mapView.visibleMapRect];
However I've seemingly hit a brick wall trying to also change the center coordinates of my overlay view (which is an MKCircleView with an MKCircle). There is a method in
MKAnnotation, which MKCircle conforms to, called setCoordinate: - which seems like what I need. Unfortunately though, the circle property in MKCircleView is readonly. Moreover the overlay property in MKOverlayView is also readonly.
Is there actually a way of changing the coordinates for an overlay, without resort to remove the overlay view and adding a new one (which would cause very noticeable flicker on the screen.) ?
same problem is occurred here , so i'm creating set of method and calling it according to requirement.
-(void)removeAllAnnotationFromMapView{
if ([[self.tmpMapView annotations] count]) {
[self.tmpMapView removeAnnotations:[self.tmpMapView annotations]];
}
}
-(void)removeAllOverlays{
if ([[self.tmpMapView overlays] count]) {
[self.tmpMapView removeOverlays:[self.tmpMapView overlays]];
}
}
-(void)removeOverlayWithTag:(int)tagValue{
for (MKOverlayView *oView in [self.tmpMapView overlays]) {
if (oView.tag == tagValue) {
[self.tmpMapView removeOverlay:oView];
}
}
}