Add blur effect on a Mapbox - ios

I want to add blur effect in mapbox.when first time load map that time only display current location in map other map is blue.see screenshot
when i move the userlocation to another location than other location is clear on the map.also display annotation in specific location
see screenshot
help me how can implement this
here i will some implement code
- (CGPoint)convertLatLongCoord:(CGPoint)latLong {
CGSize screenSize = [UIScreen mainScreen].applicationFrame.size];
CGFloat SCALE = MIN(screenSize.width, screenSize.height) / (2.0 * EARTH_RADIUS);
CGFloat OFFSET = MIN(screenSize.width, screenSize.height) / 2.0;
CGFloat x = EARTH_RADIUS * cos(latLong.x) * cos(latLong.y) * SCALE + OFFSET;
CGFloat y = EARTH_RADIUS * cos(latLong.x) * sin(latLong.y) * SCALE + OFFSET;
return CGPointMake(x, y);
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
NSLog(#"data=%f",self.mapview.userLocation.coordinate.latitude);
CLLocation *currentLoc=[locations objectAtIndex:0];
_coordinate=currentLoc.coordinate;
CGPoint latLong = {_coordinate.latitude, _coordinate.longitude};
oldcord = [self convertLatLongCoord:latLong];
NSLog(#"Cartesian Coordinate: (%f, %f)",oldcord.x, oldcord.y);
}
in this code i will get perfect view pixel point of UserLocation coordinate.after i want to clear blur in view using CGPoint but i can not get it.i think i will create array of CGPoint and than clear using line to blur of view but i can not got it pls suggest me.
i also use this lib but i can not get idea to much https://github.com/DenHeadless/Shapes

as per Logic I have added in my comment here I have made a sample for you download it here, check the result below
The sample contains following logic.
Using iOS Map, added a Custom UIView above the Map the class for the
UIView is DrawView which actually handles all the drawing and
erasing part.
We are having CLLocationManager of course to determine user's movement.
As soon as CLLocationManager start giving locations, we convert the coordinates with respect of MapView pin location using following code
CGPoint pt=[self.map convertCoordinate:location.coordinate toPointToView:self.view];
and we pass the CGPoint which is the converted value for the UIView to clear the area in drawing as
[self.drawView eraseAtPoint:pt];
When CGPoint from user's coordinate is passed to the DrawView eraseAtPoint function we erase an area of defined radius, and it clears out the area as wanted.
I have added a sample directions.gpx file to simulate GPS location, the sample GIF shows the movement.
Note: Link for the project will expire after 14 March,2017, so keep it downloaded, in any case if you want the sample again ping in comment. Feel free to do modifications as you need.
Update:
Adding capability to erase area in circles instead of squares, just replace the drawRect function in DrawView with the code below
- (void)drawRect:(CGRect)rect {
// Drawing code
UIColor *backgroundColor=[UIColor colorWithRed:0.85 green:0.85 blue:0.85 alpha:1.0f];//Grey
[backgroundColor setFill];
UIRectFill(rect);
if(!self.initialLoad){//If the view has been loaded from next time we will try to clear area where required..
// clear the background in the given rectangles
for (NSValue *holeRectValue in _rectArray) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect holeRect = [holeRectValue CGRectValue];
[[UIColor clearColor] setFill];
CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextFillEllipseInRect( context, holeRectIntersection );
}
}
self.initialLoad=NO;
}
Cheers.

Related

How to LIGHTLY erase drawn path in cgcontext?

I managed to implement erase drawings on CGContext
UIImageView *maskImgView = [self.view viewWithTag:K_MASKIMG];
UIGraphicsBeginImageContext(maskImgView.image.size);
[maskImgView.image drawAtPoint:CGPointMake(0,0)];
float alp = 0.5;
UIImage *oriBrush = [UIImage imageNamed:_brushName];
//sets the style for the endpoints of lines drawn in a graphics context
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat eraseSize = oriBrush.size.width*_brushSize/_zoomCurrentFactor;
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineWidth(ctx,eraseSize);
CGContextSetRGBStrokeColor(ctx, 1, 1, 1, alp);
CGContextSetBlendMode(ctx, kCGBlendModeClear);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, lastPoint.x,lastPoint.y);
CGPoint vector = CGPointMake(currentPoint.x - lastPoint.x, currentPoint.y - lastPoint.y);
CGFloat distance = hypotf(vector.x, vector.y);
vector.x /= distance;
vector.y /= distance;
for (CGFloat i = 0; i < distance; i += 1.0f) {
CGPoint p = CGPointMake(lastPoint.x + i * vector.x, lastPoint.y + i * vector.y);
CGContextAddLineToPoint(ctx, p.x, p.y);
}
CGContextStrokePath(ctx);
maskImgView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
Problem is, this TOTALLY erase anything. The alpha set in this function ( CGContextSetRGBStrokeColor(ctx, 1, 1, 1, alp);) seems to be ignored totally.
I want to erase just lightly and repeated erasing will then totally removes the drawing.
Any ideas?
EDIT: As per request, I add more details about this code:
alp=_brushAlpha is a property delcared in this ViewController class. It ranges from 0.1 to 1.0. At testing I set it to 0.5. This drawing code is triggered by pan gesture recognizer (change state). It is basically following the finger (draw/erase by finger).
You've set the blending mode to clear. That ignores stroke color. You should play with the various modes a bit, but I suspect you want something like sourceAtop or maybe screen. See the CGBlendMode docs for full details.
You have a flag named clearsContextBeforeDrawing in UIView. if you set it to YES it will clear it before every draw.
according to documentation
A Boolean value that determines whether the view’s bounds should be automatically cleared before drawing.
When set to YES, the drawing buffer is automatically cleared to transparent black before the drawRect: method is called. This behavior ensures that there are no visual artifacts left over when the view’s contents are redrawn. If the view’s opaque property is also set to YES, the backgroundColor property of the view must not be nil or drawing errors may occur. The default value of this property is YES.
If you set the value of this property to NO, you are responsible for ensuring the contents of the view are drawn properly in your drawRect: method. If your drawing code is already heavily optimized, setting this property is NO can improve performance, especially during scrolling when only a portion of the view might need to be redrawn.

iOS - Quartz drawing issue with parent/child views

Scenario
I have two views. One is the "parent" view which contains a "child" view that does the drawing. I refer to the child as QuartzView in the code to follow. QuartzView knows how to draw a square to it's own context.
Issue
When I tell the QuartzView on it's self to draw a square it does so as expected. When I use the parent view to tell QuartsView to draw a square on it's self it draws the square in the lower left corner of the screen at about 1/5 the expected size.
Question
I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?
Parent ViewController
- (void)drawASquare {
// this code draws the "goofy" square that is smaller and off in the bottom left corner
x = qv.frame.size.width / 2;
y = qv.frame.size.height / 2;
CGPoint center = CGPointMake(x, y);
[qv drawRectWithCenter:center andWidth:50 andHeight:50 andFillColor:[UIColor blueColor]];
}
Child QuartzView
- (void)drawRect:(CGRect)rect
{
self.context = UIGraphicsGetCurrentContext();
UIColor *color = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];
// this code draws a square as expected
float w = self.frame.size.width / 2;
float h = self.frame.size.height / 2;
color = [UIColor blueColor];
CGPoint center = CGPointMake(w, h);
[self drawRectWithCenter:center andWidth:20 andHeight:20 andFillColor:color];
}
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
CGContextSetFillColorWithColor(self.context, color.CGColor);
CGContextSetRGBStrokeColor(self.context, 0.0, 1.0, 0.0, 1);
CGRect rectangle = CGRectMake(center.x - w / 2, center.x - w / 2, w, h);
CGContextFillRect(self.context, rectangle);
CGContextStrokeRect(self.context, rectangle);
}
Note
The opacities are the same for both squares
I turned off "Autoresize subviews" with no noticeable difference
view.contentScaleFactor = [[UIScreen mainScreen] scale]; has not helped
Edit
I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.
The return value from UIGraphicsGetCurrentContext() is only valid inside the drawRect method. You can not and must not use that context in any other method. So the self.context property should just be a local variable.
In the drawRectWithCenter method, you should store all of the parameters in properties, and then request a view update with [self setNeedsDisplay]. That way, the framework will call drawRect with the new information. The drawRectWithCenter method should look something like this
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
self.showCenter = center;
self.showWidth = w;
self.showHeight = h;
self.showFillColor = color;
[self setNeedsDisplay];
}
And of course, the drawRect function needs to take that information, and do the appropriate drawing.
I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?
You normally don't need to worry about the graphics context in your -drawRect: method because Cocoa Touch will set up the context for you before calling -drawRect:. But your -drawASquare method in the view controller calls -drawRectWithCenter:... to draw outside the normal drawing process, so the context isn't set up for your view. You should really have the view do its drawing in -drawRect:. If your view controller wants to make the view redraw, it should call -setNeedsDisplay, like:
[qv setNeedsDisplay];
That will add the view to the drawing list, and the graphics system will set up the graphics context and call the view's -drawRect: for you.
I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.
UIKit and Core Animation use an upper left origin, but Core Graphics (a.k.a. Quartz) normally uses a lower left origin. The docs say:
The default coordinate system used by Core Graphics framework is LLO-based.

iOS graphics appearing from upper left corner on custom control

I have been making a circular control and i am doing fine, except that the graphics appears from upper left corner when i do the render first time.
The whole control is subclassed UIControl, with custom CALayer which does rendering of a circle.
This is the code that renders the circle:
- (void) drawInContext:(CGContextRef)ctx{
id modelLayer = [self modelLayer];
CGFloat radius = [[modelLayer valueForKey:DXCircularControlLayerPropertyNameRadius] floatValue];
CGFloat lineWidth = [[modelLayer valueForKey:DXCircularControlLayerPropertyNameLineWidth] floatValue];
//NSLog(#"%s, angle: %6.2f, radius: %6.2f, angle_m: %6.2f, radius_m: %6.2f", __func__, self.circleAngle, self.circleRadius, [[modelLayer valueForKey:#"circleAngle"] floatValue], [[modelLayer valueForKey:#"circleRadius"] floatValue]);
// draw circle arc up to target angle
CGRect frame = self.frame;
CGContextRef context = ctx;
CGContextSetShouldAntialias(context, YES);
CGContextSetAllowsAntialiasing(context, YES);
// draw thin circle
//CGContextSetLineWidth(context, <#CGFloat width#>)
// draw selection circle
CGContextSetLineWidth(context, lineWidth);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextAddArc(context, frame.size.width / 2.0f, frame.size.height / 2.0f, radius, 0.0f, self.circleAngle, 0);
CGContextStrokePath(context);
CGContextSetShouldAntialias(context, NO);
}
Here is the video of a problem.
If you watch carefully, you'll notice that rendering of circle somehow doesnt start centered. It skews itself from the upper left corner.
This only happens when doing the animation for the first time.
I know this can happen if one mistakes begin and end of animation commit blocks, but i dont use them here.
Just in case here is the link to the bitbucket repo of this control:
There is nothing wrong with the drawing method - you messed up a little bit setting the layer's frame ;-)
You are setting the frame for the circularControlLayer within your - (void) setAngle:(CGFloat)angle method. That means the frame is set for the first time when you animate the angle property - so the frame will be animated too. Set the frame within the - (void) commonInitDXCircularControlView method.
If you are creating custom layers, have a look at the [UIView layerClass] method. Using it will save you from trouble with bounds/frame management.

How to set specific areas of uiimage to process touch gestures?

I'm making a photo hunt style app. I've got a number of X-Rays and I need to set specific areas of the uiimage to process touch events as correct and others as incorrect.
I understand that I can use the code below to get the tap location in the image view but how do I declare an area on the image view as correct and compare it to the tap location value?
CGPoint tapLocation = [gesture locationInView:self.imagePlateA];
Any help much appreciated!
So you have to programmatically create "regions" and test to see whether or not they're in that region after you get that point. For example:
//Get the tap location
CGPoint tapLocation = [gesture locationInView:self.imagePlateA];
if ([self checkIfTap:tapLocation inRegionWithCenter:CGPointMake(someX, someY) radius:radius]) {
//YAY WE'RE WITHIN THE BOUNDS OF A CIRCLE AT POINT (someX, someY)
//THAT HAS A RADIUS OF radius
}
and the method of checkIfTap: inRegionWithCenter: radius: can be defined like this:
- (BOOL)checkIfTap:(CGPoint)tapLocation inRegionWithCenter:(CGPoint)center radius:(CGFloat)radius {
CGFloat dx = tapLocation.x - center.x;
CGFloat dy = tapLocation.y - center.y;
//Pythagorean theorem
if (sqrt(dx * dx + dy * dy) < radius) {
return YES;
} else {
return NO;
}
}
If the correct locations of the image is a CGRect rather than points, you could use CGRectContainsPoint()
CGGeometry Reference

Pentagon with UISLiders as circumradii

I want to draw a pentagon in iOS with UISliders as the circumradii (a set of five UISliders going in different directions and originating from the center of a pentagon). Currently I have rotated five UISliders using a common anchorPoint (:setAnchorPoint), but they dont seem to originate from a common point.
How can I go about this? Do I need to start working on a custom control? What more from Quartz2D can I use?
Some specific indicators would be useful (please don't just say "Use Quartz2D")
Here is what I have achieved Imgur
And here is what I want to achieve Imgur
I defined the various sliders as an IBOutletCollection, so I can access them as an array in the controller. Then I run the following code in viewWillAppear:
CGPoint viewCenter = self.view.center;
for (NSInteger i = 0, count = self.sliders.count; i < count; ++i) {
UISlider *slider = self.sliders[i];
CGFloat angle = 2.0f * M_PI / count;
CALayer *layer = slider.layer;
layer.anchorPoint = CGPointMake(0.0f, 0.5f);
layer.position = viewCenter;
layer.transform = CATransform3DMakeRotation(i * angle - M_PI_2, 0.0f, 0.0f, 1.0f);
}
Here's a screenshot of the result:
Is this that you want?
I would try just to turn the sliders. The following code should help:
firstSlider.transform=CGAffineTransformRotate(firstSlider.transform,72.0/180*M_PI);
secondSlider.transform=CGAffineTransformRotate(secondSlider.transform,144.0/180*M_PI);
//and so on
The 72.0/180*M_PI is transformation of degrees to radians.
Hope it helps.
P.S. don't have a mac nearby to check if it works

Resources