zoukankan      html  css  js  c++  java
  • Set the Zoom Level of an MKMapView

    If you have ever built a web application using the Google Maps API, you are likely intimately familiar with this line of code:

    map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);

    The setCenter JavaScript method takes in the center coordinate and a zoom level. The zoom level, as you might expect, determines how far the map should zoom in. The zoom level ranges from 0 (all the way zoomed out) to some upper value (all the way zoomed in). The max zoom level for a particular area depends on the location (for instance, you can’t zoom in too far on North Korea) and the map type (default, satellite, hybrid, terrain, etc). Typically, the max zoom level for an area is somewhere between 15 – 21.

    Unfortunately, MapKit on the iPhone does not include a way to set the zoom level. Instead, the zoom level is set implicitly by defining the MKCoordinateRegion of the map’s viewport. When initializing the region, you specify the amount of distance the map displays in the horizontal and vertical directions. The zoom level is set implicitly based on these distance values.

    Instead of dealing with this region business, I wrote a category that adds support for setting the zoom level of an MKMapView explicitly. In this post, I’ll give you code you can drop into your own projects and start using immediately. My next post will detail exactly how it works.

    The Code

    Instead of force-feeding you everything I learned while working on this mini-project, I’ll give you the goods up front. The code below defines a category on MKMapView that gives you the ability to set the zoom level for your map:

    // MKMapView+ZoomLevel.h
    #import <MapKit/MapKit.h>
    
    @interface MKMapView (ZoomLevel)
    
    - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
        zoomLevel:(NSUInteger)zoomLevel
        animated:(BOOL)animated;
    
    @end
    // MKMapView+ZoomLevel.m
    #import "MKMapView+ZoomLevel.h"
    
    #define MERCATOR_OFFSET 268435456
    #define MERCATOR_RADIUS 85445659.44705395
    
    @implementation MKMapView (ZoomLevel)
    
    #pragma mark -
    #pragma mark Map conversion methods
    
    - (double)longitudeToPixelSpaceX:(double)longitude
    {
        return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
    }
    
    - (double)latitudeToPixelSpaceY:(double)latitude
    {
        return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
    }
    
    - (double)pixelSpaceXToLongitude:(double)pixelX
    {
        return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
    }
    
    - (double)pixelSpaceYToLatitude:(double)pixelY
    {
        return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
    }
    
    #pragma mark -
    #pragma mark Helper methods
    
    - (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
        centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
        andZoomLevel:(NSUInteger)zoomLevel
    {
        // convert center coordiate to pixel space
        double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
        double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
        
        // determine the scale value from the zoom level
        NSInteger zoomExponent = 20 - zoomLevel;
        double zoomScale = pow(2, zoomExponent);
        
        // scale the map’s size in pixel space
        CGSize mapSizeInPixels = mapView.bounds.size;
        double scaledMapWidth = mapSizeInPixels.width * zoomScale;
        double scaledMapHeight = mapSizeInPixels.height * zoomScale;
        
        // figure out the position of the top-left pixel
        double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
        double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
        
        // find delta between left and right longitudes
        CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
        CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
        CLLocationDegrees longitudeDelta = maxLng - minLng;
        
        // find delta between top and bottom latitudes
        CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
        CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
        CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
        
        // create and return the lat/lng span
        MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
        return span;
    }
    
    #pragma mark -
    #pragma mark Public methods
    
    - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
        zoomLevel:(NSUInteger)zoomLevel
        animated:(BOOL)animated
    {
        // clamp large numbers to 28
        zoomLevel = MIN(zoomLevel, 28);
        
        // use the zoom level to compute the region
        MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
        MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
        
        // set the region like normal
        [self setRegion:region animated:animated];
    }
    
    @end

    If you’re wondering why this works, check out my next post where I describe in gruesome detail the math behind the code.

    On the other hand, if you don’t really care how it works, just that it does work, copy and paste away, my friend.

     

    Test the Code

    To test the category, assuming you have a view controller with an MKMapView instance, you can use the following code:

    // ZoomLevelTestViewController.m
    #import "MKMapView+ZoomLevel.h"
    
    #define GEORGIA_TECH_LATITUDE 33.777328
    #define GEORGIA_TECH_LONGITUDE -84.397348
    
    #define ZOOM_LEVEL 14
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        
        CLLocationCoordinate2D centerCoord = { GEORGIA_TECH_LATITUDE, GEORGIA_TECH_LONGITUDE };
        [mapView setCenterCoordinate:centerCoord zoomLevel:ZOOM_LEVEL animated:NO];
    }

    And, viola! Your map should zoom in to where you can see the Georgia Tech campus.

    原文地址:http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/

  • 相关阅读:
    mina之小小总结(标准的菜鸟级别,行家勿入)
    tomcat(就一句话,自己的日记性质)
    MINA转自itoyo
    java web(没含量的,百科上的)
    解决VS.NET 2008中aspx文件没有设计界面
    正则表达式教程
    [VB] Option Explicit
    sql自定義函數 包含遊標
    sql 中 null+others=?
    实用手机号、IP、身份证号、歌曲查询接口
  • 原文地址:https://www.cnblogs.com/solitary/p/2744920.html
Copyright © 2011-2022 走看看