12

(iOS 5 および Xcode 4.2 を使用。)

ここの指示に従いました: http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/AnnotatingMaps/AnnotatingMaps.html#//apple_ref/doc/uid/TP40009497-CH6-SW15 MKCircleおよびMKCircleViewクラスを使用して、MKMapViewに円のオーバーレイを追加しました。

ただし、実際に必要なのは、下のスケッチの左の地図のような逆円のオーバーレイです (現在、右のような円のオーバーレイがあります)。

反転した円と反転していない円のオーバーレイ スケッチ

逆の円の場合、オーバーレイは、表示されている円を除いて、マップ全体をカバーする必要があります。

MKCircle/MKCircleView クラスを使用してこれを達成する簡単な方法はありますか? それとも、さらに深く掘り下げて、カスタム オーバーレイ オブジェクト/ビューを定義する必要がありますか?

ご協力ありがとうございました :)

4

4 に答える 4

7

私は同じ仕事をしていましたが、これを解決する方法は次のとおりです。

注: このコードは 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;
}

MyMapOverlay 自体は次のようになります。

@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

そして MyMapOverlayRenderer:

@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);
}

その結果、質問に投稿された左の画像とまったく同じビューが表示されます。

于 2015-06-25T12:15:39.520 に答える
5

これを行う最善の方法は、メソッド呼び出し superをサブクラス化MKMapViewしてオーバーライドし、必要な色でマップをペイントすることです。drawRect次に、ユーザーが移動するたびに、drawRect適切に描画して応答する必要があります。

于 2012-01-31T10:22:19.883 に答える
1

ここでは Swift バージョンです。ありがとうヴァレリー。

https://github.com/dariopellegrini/MKInvertedCircle

于 2017-01-12T16:29:51.600 に答える