Black and white overlay for an MKMapView

前端 未结 2 1068
臣服心动
臣服心动 2021-01-12 21:07

I have an MKMapView and am adding an overlay (MKOverlay) to it.

I would like the overlay to make the map view underneath to appear black & white (i.e. monochrom

2条回答
  •  别那么骄傲
    2021-01-12 22:07

    I needed same color manipulations on map, and I decided that making the whole map black and white may be better solution, here is how you can do this:

    1. created new imageCGcontex
    2. rendered map in new CGcontext
    3. got UIImage from current CGcontext
    4. applied CIFilter to UIImage and got CIImage as result
    5. rendered CIImage in CIContext and got CGImageRef as result
    6. created UIImage from CGImageRef
    7. added sub imageview to apple map view
    8. set result image to that imageView

    Here is some dirty code to do this:

      self.drawContext = [[CIContext alloc] init];
      [self.monochromeSubView removeFromSuperview];
    
      UIGraphicsBeginImageContext(self.appleMapView.bounds.size);
      UIImage *mySourceImage = UIGraphicsGetImageFromCurrentImageContext();
      CIImage *newMyCiImage = [[CIImage alloc] initWithImage:mySourceImage];
      CIFilter *newMyMonochromeFilter = [CIFilter filterWithName:@"CIPhotoEffectTonal"];
      [newMyMonochromeFilter setValue:newMyCiImage forKey:kCIInputImageKey];
      CIImage *newMyfilteredCIImage = newMyMonochromeFilter.outputImage;
      
      CGImageRef myOutputImageRef = [self.drawContext createCGImage:newMyfilteredCIImage
                                                           fromRect:newMyfilteredCIImage.extent];
      UIImage *newMyImage = [[UIImage alloc] initWithCGImage:myOutputImageRef];
    
      self.monochromeSubView.image = newMyImage;
      [self.appleMapView addSubview:self.monochromeSubView];
    
      CGImageRelease(myOutputImageRef);
      UIGraphicsEndImageContext();

    Here you go - the map is in black and white colors. To do this dynamically to move monochrome map along with user's gesture you can subclass gesture recognizer, add it directly to map view. Then on every touchesMoved call you can call this redraw function while reusing context you once created. I tried this with apple map taking about 1/3 of the screen and it resulted in extremely low performance (about 3 FPS on iPhone 5s) and there are couple bugs you have to fix, such as: flying map on swipe gesture while monochrome image is static, frequency of map pins redrawing, redraw or animate every pop up that displayed in response to tap. You can try to render map in CALayer, not in Context, Apple recommends it to improve performance, but considering all the above I suppose if you want to see dynamic filtered elements it is better to use other more customizable map: GoogleMap or MapBox.

提交回复
热议问题