Remove or edit user location blue pulsing circle - swift

I'm trying to change the radius and color of the blushing blue circle that's created around a current user's location a MapKit? After searching for answers I found an old question Change User Location Blue Pulsing Circle Radius but the answer is an old objective-C service that costs money. Is there anything new in swift that would make this task easier, or is there a way to just remove the pulsing blue circle all together

The blue color for the user location is based on the tint color of your map view, changing this will set the new color for the user location circle.
//Objective-C
mapView.tintColor = [UIColor redColor];
//Swift
mapView.tintColor = redColor()
If you wish to remove or replace the user location circle with something different you can change the didAnnotation delegate method.
-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *usrLoc = [mapView viewForAnnotation:mapView.userLocation];
usrLoc.hidden = YES;
}

You cannot change the radius since it represents the GPS accuracy.

In swift 4,
I choosed a clear color so it is less anoying than a red or blue color to see below the map's details.
mapView.tintColor = UIColor.clear

Related

CoreGraphics draw intersection of ellipses

I am coding up a ViewController that will have a legend on the left (A vertical list of labels and colored boxes: Category1: yellow, Category2: gree, Category 3: blue, etc....)
A user can tap an item in the list and then draw an ellipse within a UIView. I am tracking the touch events and can draw the ellipses no problem using core graphics.
The next step is to draw the intersection of two sets. Suppose a user draws a green ellipse and a red ellipse which overlap somewhat. I'd like to color the intersection yellow (red + green = yellow), but don't have any ideas on how to do this.
I have been able to accomplish this using alpha channels of < 1.0 as in the following image:
And then additionally, I need a way to have the user tap a point in the UIImage and then retrieve the intersection of all sets that that pixel is in.
If you're using Core Graphics to draw the ellipses, you can change the blend mode to create different looks. The blend mode you want is addition, but it doesn't appear to be supported by Core Graphics (possibly due to the Quantel patent, though I thought that had expired). You can probably create a similar effect by using 50% alpha and using normal mode. Or maybe one of the other modes will provide something that looks better.
If that's not going to work, you could do it in OpenGL using additive blending.
The answer came from user1118321, but I'm posting this answer to have inline pictures rather than reply inline. First I selected a better set of colors for the venn diagram:
These colors overlap and hide each other. The solution was to use kCGBlendModeScreen:
However this augmented the original colors. The solution to this was to set the background to black:
For those code curious or lazy, here is some of the code. On the touchesBegan/Ended/Moved events I'm creating SMVennObjects, then drawing them in drawRect. SMVennObject merely contains two CGPoints and a UIColor (assigned in sequence using a static int).
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect{
for(NSUInteger index = 0; index < self.vennObjects.count; index++){
NSLog(#"drawing index %d", index);
SMVennObject* vo = [self.vennObjects objectAtIndex:index];
[self drawVennObject:vo context:UIGraphicsGetCurrentContext()];
}
}
-(void)drawVennObject:(SMVennObject*)vo context:(CGContextRef)cgContext{
if((vo.pointBegin.x == 0 && vo.pointBegin.y == 0) ||
(vo.pointEnd.x == 0 && vo.pointEnd.y == 0)){
return;
}
CGContextBeginPath(cgContext);
CGContextSetLineWidth(cgContext, 2.0f);
// Convert UIColor to raw values
CGFloat red = 0.0;
CGFloat green = 0.0;
CGFloat blue = 0.0;
CGFloat alpha = 0.0;
[vo.color getRed:&red green:&green blue:&blue alpha:&alpha];
alpha = 1.0;
CGFloat color[4] = {red, green, blue, alpha};
CGContextSetBlendMode(cgContext, kCGBlendModeScreen);
CGRect r = CGRectMake(MIN(vo.pointBegin.x, vo.pointEnd.x),
MIN(vo.pointBegin.y, vo.pointEnd.y),
fabs(vo.pointBegin.x - vo.pointEnd.x),
fabs(vo.pointBegin.y - vo.pointEnd.y));
// Draw ellipse
CGContextSetFillColor(cgContext, color);
CGContextFillEllipseInRect(cgContext, r);
// Draw outline of ellipse
CGContextSetStrokeColor(cgContext, color);
CGContextStrokeEllipseInRect(cgContext, r);
}

Erase line drawing with UIBezierPath

Did a simple application for line drawing with UIBezierPath, but now need a way to erase the line drawn with UIBezierPath. Is there a way to implement eraser feature for removing the line painting?
If you are using an image as background then you can set the same image as brush pattern to draw the bezierpath it will virtually give you the eraser effect. It works for me. :)
brushPattern=[[UIColor alloc]initWithPatternImage:[UIImage imageNamed:#"image.jpg"]];
// Here image.jpg is you background image
if(erase)
{
[myPath strokeWithBlendMode:kCGBlendModeClear alpha:1.0f];
}
else
{
[myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0f];
}
An eraser effectively draws a line that's the same color as the background atop every path that's been drawn thus far. You might need to note that it's an eraser line somewhere so that you can update the eraser line's stroke color if the background color changes, otherwise you lose the illusion of erasure.
Based on your comments on Jeremy's answer, it seems like you're trying to do dashed lines. Have you tried using setLineDash:count:phase:
UIBezierPath *path = [UIBezierPath new];
CGFloat dashArray[3];
dashArray[0] = 8;
dashArray[1] = 3;
dashArray[2] = 8;
[path setLineDash:dashArray count:dashCount phase: 0.0];
Apple has sample code here: http://developer.apple.com/library/mac/#samplecode/BezierPathLab/Introduction/Intro.html

query the color of the MKpolygon on where the user is

I was wondering if there was a way to query what color my MKPolygon layer is, if the users locations is on top of it.
Thank you
Nope. No way.I was on the same situation ten days ago and i searched in web all along and couldnt do that functionality. I think apple should come up with some delegates on MKOverlay in future iOS SDK's for touch events on polygons.
When your MKMapView delegate receives a user location update you can loop through your overlays and see if the users location is inside the bounding map rect for any of the overlays. On your overlay, just add a "color" property that you can use to find the color.
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
for (MyOverlayClass* overlay in mapView.overlays)
{
MKMapPoint userPoint = MKMapPointForCoordinate(userLocation.location.coordinate);
if ( MKMapRectContainsPoint(overlay.boundingMapRect, userPoint) )
{
UIColor* userInColor = overlay.color;
}
}
}

MKMapView ignores update of centerOffset in iOS 4

I previously created a custom callout bubble as a subview to the MKAnnotationView because the built in callout is so limited. This requires me to change to centerOffset of the MKAnnotationView when it is selected to account for the size of the callout bubble. This all worked perfectly before iOS 4 came out. Now, with iOS 4, it completely ignores my updating of the centerOffset property and therefore the pin and bubble appear to jump down and to the right (the top left corner of the callout bubble is now at the location where the pin point should be).
Does anyone know why this has changed in iOS 4? Is there something I can do to get the MKMapView to recognize the new centerOffset? Is this a bug that apple introduced?
Thanks for the help!
Make sure you are using MKAnnotationView and not MKPinAnnotationView! You can't set the centerOffset of a MKPinAnnotationView-object (except if you subclass of course).
I have the same problem - centerOffset seems to be taken into account only the first time.
It is changed internally, but the view is not moved - so what you need to do is move the view yourself.
You can move the view by adjusting its center with the required offset - the selected view remains aligned at the top-left corner with the unselected view, so you need to realign their centers. Here's my case:
Selected -> Unselected:
self.center = CGPointMake(self.center.x + 56.0, self.center.y + 130.0);
self.centerOffset = CGPointMake(5.0, -14.0);
Unselected -> Selected:
self.center = CGPointMake(self.center.x - 56.0, self.center.y - 130.0);
self.centerOffset = CGPointMake(64.0, -81.0);
Where 130 is the difference in height between the views(center point is at the bottom), and 56 is the difference between the X offsets of their centers.
Remember - you still need to change the center offset because it'll be taken into account when zooming.
Hope this helps, I've lost a few hours on this. Remember to submit a bug report to Apple.
I think instead of centerOffset you can use setRegion which works fine in all versions.
CGPoint point = [mapView convertCoordinate:selectedAnnotation.coordinate toPointToView:self.view];
CGRect frame = [customView frame];
frame.origin.y = point.y - frame.size.height;
frame.origin.x = point.x - frame.size.width / 2;
MKCoordinateRegion region = [mapView convertRect:frame toRegionFromView:self.view];
[mapView setRegion:region animated:YES];

Rotating only the MapView's content

I am trying to rotate a map view in my app according the the user's current route. (I don't like to use the built in compasse because only 3GS uses it and it suffers too much interference from other machines, i.e. your own car.).
the CGAffineTransformMakeRotation method will rotate the Whole Map View, so the Google Logo will not be in the lower right of the screen anymore. Also all Annotation Views will rotate and look weird on the App.
Does anyone knows how to rotate just the content (streets drwaings) of the MkMapView?
Thanks
Here is how I'm rotating the MapView (see Rotate MapView using Compass orientation):
[self.mapView setTransform:CGAffineTransformMakeRotation(-1 * currentHeading.magneticHeading * 3.14159 / 180)];
Then to keep the orientation of the annotation views with the top of the device:
for (MKAnnotation *annotation in self.mapView.annotations) {
MKAnnotationView *annotationView = [self.mapView viewForAnnotation:annotation];
[annotationView setTransform:CGAffineTransformMakeRotation(currentHeading.magneticHeading * 3.14159 / 180)];
}
If you want the point of rotation of the annotationViews to be say the bottom center, I believe you would set each view's anchorPoint as follows:
annotationView.layer.anchorPoint = CGPointMake(0.5, 1.0);
I'm still having some issues with the annotationView position changing when I do this though (probably same problem as stackoverflow question: changing-my-calayers-anchorpoint-moves-the-view).