Ios 将倒圆覆盖添加到地图视图
(使用iOS 5和Xcode 4.2。) 我按照这里的说明进行了操作:并使用和类在我的 然而,我真正想要的是一个倒圆覆盖,如下图中的左侧地图(目前我有一个像右侧一样的圆覆盖): 对于倒圆,覆盖应覆盖整个地图-除了可见圆 使用MKCircle/MKCircleView类是否有一种简单的方法来实现这一点?或者我需要更深入地定义自定义覆盖对象/视图吗Ios 将倒圆覆盖添加到地图视图,ios,ios5,mapkit,mkoverlay,Ios,Ios5,Mapkit,Mkoverlay,(使用iOS 5和Xcode 4.2。) 我按照这里的说明进行了操作:并使用和类在我的 然而,我真正想要的是一个倒圆覆盖,如下图中的左侧地图(目前我有一个像右侧一样的圆覆盖): 对于倒圆,覆盖应覆盖整个地图-除了可见圆 使用MKCircle/MKCircleView类是否有一种简单的方法来实现这一点?或者我需要更深入地定义自定义覆盖对象/视图吗 感谢您的帮助:)最好的方法是子类化MKMapView并重写drawRect方法调用super,然后用您想要的颜色在地图上绘制。 然后,每次用户移动时,
感谢您的帮助:)最好的方法是子类化
MKMapView
并重写drawRect
方法调用super,然后用您想要的颜色在地图上绘制。
然后,每次用户移动时,
drawRect
都应该通过适当地绘制来响应。我有同样的任务,下面是我如何解决它的:
注意:此代码仅从iOS7开始工作
在视图控制器中的某个位置向地图添加覆盖:
MyMapOverlay *overlay = [[MyMapOverlay alloc] initWithCoordinate:coordinate];
[self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels];
在MKMapViewDelegate方法中,编写下一步:
- (MKOverlayRenderer *)mapView:(MKMapView *)map rendererForOverlay:(id<MKOverlay>)overlay {
/// we need to draw overlay on the map in a way when everything except the area in radius of 500 should be grayed
/// to do that there is special renderer implemented - NearbyMapOverlay
if ([overlay isKindOfClass:[NearbyMapOverlay class]]) {
MyMapOverlayRenderer *renderer = [[MyMapOverlayRenderer alloc] initWithOverlay:overlay];
renderer.fillColor = [UIColor whateverColor];/// specify color which you want to use for gray out everything out of radius
renderer.diameterInMeters = 1000;/// choose whatever diameter you need
return renderer;
}
return nil;
}
因此,您将获得与问题中发布的左图完全相同的视图。这里是Swift版本。谢谢你,瓦莱丽
我尝试使用这个swift版本,但没有成功,所以我发布了我的实现(在iOS 12上测试)
你能建议一下你用drawRect方法写了什么吗?在整个地图上画画也会使中间区域被画出来,但他不想要。答案如何被接受?
@interface MyMapOverlay : NSObject<MKOverlay>
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end
@implementation MyMapOverlay
@synthesize coordinate = _coordinate;
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
self = [super init];
if (self) {
_coordinate = coordinate;
}
return self;
}
- (MKMapRect)boundingMapRect {
return MKMapRectWorld;
}
@end
@interface MyMapOverlayRenderer : MKOverlayRenderer
@property (nonatomic, assign) double diameterInMeters;
@property (nonatomic, copy) UIColor *fillColor;
@end
@implementation MyMapOverlayRenderer
/// this method is called as a part of rendering the map, and it draws the overlay polygon by polygon
/// which means that it renders overlay by square pieces
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context {
/// main path - whole area
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(mapRect.origin.x, mapRect.origin.y, mapRect.size.width, mapRect.size.height)];
/// converting to the 'world' coordinates
double radiusInMapPoints = self.diameterInMeters * MKMapPointsPerMeterAtLatitude(self.overlay.coordinate.latitude);
MKMapSize radiusSquared = {radiusInMapPoints, radiusInMapPoints};
MKMapPoint regionOrigin = MKMapPointForCoordinate(self.overlay.coordinate);
MKMapRect regionRect = (MKMapRect){regionOrigin, radiusSquared}; //origin is the top-left corner
regionRect = MKMapRectOffset(regionRect, -radiusInMapPoints/2, -radiusInMapPoints/2);
// clamp the rect to be within the world
regionRect = MKMapRectIntersection(regionRect, MKMapRectWorld);
/// next path is used for excluding the area within the specific radius from current user location, so it will not be filled by overlay fill color
UIBezierPath *excludePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(regionRect.origin.x, regionRect.origin.y, regionRect.size.width, regionRect.size.height) cornerRadius:regionRect.size.width / 2];
[path appendPath:excludePath];
/// setting overlay fill color
CGContextSetFillColorWithColor(context, self.fillColor.CGColor);
/// adding main path. NOTE that exclusionPath was appended to main path, so we should only add 'path'
CGContextAddPath(context, path.CGPath);
/// tells the context to fill the path but with regards to even odd rule
CGContextEOFillPath(context);
}
import Foundation
import UIKit
import MapKit
class MKInvertedCircleOverlayRenderer: MKOverlayRenderer {
var fillColor: UIColor = UIColor.red
var strokeColor: UIColor = UIColor.blue
var lineWidth: CGFloat = 3
var circle: MKCircle
init(circle: MKCircle) {
self.circle = circle
super.init(overlay: circle)
}
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
let path = UIBezierPath(rect: rect(for: MKMapRectWorld))
let excludePath: UIBezierPath = UIBezierPath(roundedRect: CGRect(x: circle.coordinate.latitude,
y: circle.coordinate.longitude,
width: circle.boundingMapRect.size.width,
height: circle.boundingMapRect.size.height),
cornerRadius: CGFloat(circle.boundingMapRect.size.width))
context.setFillColor(fillColor.cgColor)
path.append(excludePath)
context.addPath(path.cgPath)
context.fillPath(using: .evenOdd)
context.addPath(excludePath.cgPath)
context.setLineWidth(9 / zoomScale)
context.setStrokeColor(strokeColor.cgColor)
context.strokePath()
//line showing circle radius
let lineBeginPoint = CGPoint(x: excludePath.bounds.midX, y: excludePath.bounds.midY)
let lineEndPoint = CGPoint(x: excludePath.bounds.maxX, y: excludePath.bounds.midY)
let linePath: UIBezierPath = UIBezierPath()
linePath.move(to: lineBeginPoint)
linePath.addLine(to: lineEndPoint)
context.addPath(linePath.cgPath)
context.setLineWidth(6/zoomScale)
context.setStrokeColor(UIColor.black.cgColor)
context.setLineDash(phase: 1, lengths: [20 / zoomScale, 10 / zoomScale])
context.strokePath()
// circle at the end of the line above
let circleSize: CGFloat = 30/zoomScale
let circleRect = CGRect(origin: CGPoint(x: lineEndPoint.x - (circleSize/2), y: lineEndPoint.y - (circleSize/2)),
size: CGSize(width: circleSize, height: circleSize))
let circlePath: UIBezierPath =
UIBezierPath(roundedRect: circleRect, cornerRadius: circleSize)
context.addPath(circlePath.cgPath)
context.setFillColor(UIColor.black.cgColor)
context.fillPath()
}