1

我看到GMSPolyline协议已经color为其描边颜色定义了一个属性,但是有没有办法对其多边形内部进行着色(最好是透明的)?我正在寻找相当于MKPolygon和朋友的谷歌地图。

4

2 回答 2

2

There is a way, you can get something like this:

Polygons example

The approach is rather simple:

  • Add transparent noninteracting UIView with overriden drawing code and pass it CGPoints for drawing polygons
  • Get your CLLocationCoordinate2D coordinates for polygons and convert them to CGPoints for drawing
  • Update those CGPoints every time map moves so you can redraw them in the right position and make that UIView redraw itself.

So, what you want to do is add an UIView on top of your mapview, which is transparent and non-userinteractive, which has overridden drawRect method. It is provided with a double array of CGPoints, like CGpoint **points, acccessed with points[i][j] where i is each of closed polygons and j are individual points of each polygon. The class would be, let's call it OverView:

#import "OverView.h"

@interface OverView ()
{
    CGPoint **points;
    int *pointsForPolygon;
    int count;
}

@end

@implementation OverView

- (id)initWithFrame:(CGRect)frame andNumberOfPoints:(int)numpoints andPoints:(CGPoint **)passedPoints andPointsForPolygon:(int *)passedPointsForPolygon;{
    self = [super initWithFrame:frame];
    if (self) {

        // You want this to be transparent and non-user-interactive

        self.userInteractionEnabled = NO;
        self.backgroundColor = [UIColor clearColor];

        // Passed data

        points = passedPoints; // all CGPoints
        pointsForPolygon = passedPointsForPolygon; // number of cgpoints for each polygon
        count = numpoints; // Number of polygons
    }
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.

- (void)drawRect:(CGRect)rect
{

    for(int i=0; i<count; i++) // For each of polygons, like blue ones in picture above
    {
        if (pointsForPolygon[i] < 2) // Require at least 3 points
            continue;

        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
        CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);

        CGContextSetLineWidth(context, 2.0);

        for(int j = 0; j < pointsForPolygon[i]; j++)
        {
            CGPoint point = points[i][j];

            if(j == 0)
            {
                // Move to the first point
                CGContextMoveToPoint(context, point.x, point.y);
            }
            else
            {
                // Line to others
                CGContextAddLineToPoint(context, point.x, point.y);
            }
        }

        CGContextClosePath(context); // And close the path
        CGContextFillPath(context);
        CGContextStrokePath(context);
    }
}


@end

Now, in original UIViewController with mapview, you need to have access to all coordinates that make all the polygons (same array as points, but consisting of CLLocationCoordinate2D, and several others:

@interface ViewController () <GMSMapViewDelegate>
{
    CGPoint **points;
    int howmanypoints;
    int *pointsForPolygon;
    CLLocationCoordinate2D **acoordinates;
}

acoordinates is populated wherever you get your coordinates for polygons, I parse the response string from Fusion Tables, part of my parser method

- (void)parseResponse2
{
    NSMutableArray *fullArray = [[self.fusionStringBeaches componentsSeparatedByString:@"\n"] mutableCopy];

    howmanypoints = fullArray.count; // This is number of polygons

    pointsForPolygon = (int *)calloc(howmanypoints, sizeof(int)); // Number of points for each of the polygons
    points = (CGPoint **)calloc(howmanypoints, sizeof(CGPoint *));
    acoordinates = (CLLocationCoordinate2D **)calloc(howmanypoints, sizeof(CLLocationCoordinate2D *));

    for(int i=0; i<fullArray.count; i++)
    {

        // Some parsing skipped here

        points[i] = (CGPoint *)calloc(koji, sizeof(CGPoint));
        acoordinates[i] = (CLLocationCoordinate2D *)calloc(koji, sizeof(CLLocationCoordinate2D));
        pointsForPolygon[i] = koji;

        if (koji > 2)
        {
            // Parsing skipped                
            for (int j=0; j<koji; j++)
            {
                CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(coordinates[j].latitude, coordinates[j].longitude);

                // Here, you convert coordinate and add it to points array to be passed to overview
                points[i][j] = [self.mapView.projection pointForCoordinate:coordinate];
                // and added that coordinate to array for future access
                acoordinates[i][j] = coordinate;
            }
        }
    }

    // Finally, allocate OverView passing points array and polygon and coordinate counts
    self.overView = [[OverView alloc] initWithFrame:self.view.bounds
                                  andNumberOfPoints:howmanypoints
                                          andPoints:points
                                andPointsForPolygon:pointsForPolygon];

     // And add it to view
    [self.view addSubview:self.overView];

}

Now, you have Polygons where you want them, but must observe - (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position delegate method as drawn polygons won't move with map. The trick is that you have your 2D array of coordinates acoordinates and you can user helper function (CGPoint *)[self.mapview.projection pointForCoordinate:(CLLocationCoordinate2D)coordinate] to recalculate the positions, like:

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position
{    
    if (points != nil)
    {
        // Determine new points to pass
        for (int i=0; i<howmanypoints; i++)
        {
            for(int j=0; j<pointsForPolygon[i]; j++)
            {
                // Call method to determine new CGPoint for each coordinate
                points[i][j] = [self.mapView.projection pointForCoordinate:acoordinates[i][j]];
            }
        }

        // No need to pass points again as they were passed as pointers, just refresh te view    
        [self.overView setNeedsDisplay];
    }

}

And that's it. Hope you got the gist of it. Please, comment if I need to clarify something. I can also make a small complete project and upload it to github so you can research it better.

于 2013-03-08T19:54:38.443 回答
2

折线不同于多边形。折线没有填充颜色的概念。提交将多边形添加到 SDK的功能请求。

于 2013-03-05T23:34:59.197 回答