MKMapView के लिए ज़ूम स्तर सेट करना


118

मेरे पास एक नक्शा है जो सही ढंग से दिखाता है, केवल एक चीज जिसे मैं करना चाहता हूं वह लोड होने पर ज़ूम स्तर सेट करता है। क्या इसे करने का कोई तरीका है?

धन्यवाद

जवाबों:


199

मैंने अपने आप को एक समाधान पाया, जो बहुत सरल है और चाल है। MKCoordinateRegionMakeWithDistanceवांछित ज़ूम प्राप्त करने के लिए ऊर्ध्वाधर और क्षैतिज रूप से मीटर में दूरी निर्धारित करने के लिए उपयोग करें । और फिर निश्चित रूप से जब आप अपने स्थान को अपडेट करते हैं, तो आपको सही निर्देशांक मिलेंगे, या आप इसे सीधे CLLocationCoordinate2Dस्टार्टअप पर निर्दिष्ट कर सकते हैं , यदि आपको ऐसा करने की आवश्यकता है:

CLLocationCoordinate2D noLocation;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500);
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];          
[self.mapView setRegion:adjustedRegion animated:YES];
self.mapView.showsUserLocation = YES;

स्विफ्ट:

let location = ...
let region = MKCoordinateRegion( center: location.coordinate, latitudinalMeters: CLLocationDistance(exactly: 5000)!, longitudinalMeters: CLLocationDistance(exactly: 5000)!)
mapView.setRegion(mapView.regionThatFits(region), animated: true)

3
यह चयनित उत्तर होना चाहिए। मैंने अन्य प्रस्तावित समाधानों की बहुत कोशिश की लेकिन उनमें से किसी ने भी ठीक से काम नहीं किया। यह कोड सरल और प्रभावी है।
लेवी रॉबर्ट्स

1
अच्छा उत्तर। हालाँकि स्क्रीन के आकार के आधार पर ज़ूम अलग होगा, नहीं?
विन्जियस

1
दिलचस्प है, MKCoordinateRegionMakeWithDistanceस्विफ्ट में अभी भी चारों ओर है। यह समाधान काम करता है!
LinusGeffarth 10

47

इस तथ्य के आधार पर कि देशांतर रेखाएं मानचित्र के किसी भी बिंदु पर समान रूप से अलग-अलग हैं, केंद्रकॉर्डिनेट और ज़ूमवेल को सेट करने के लिए एक बहुत ही सरल कार्यान्वयन है:

@interface MKMapView (ZoomLevel)

@property (assign, nonatomic) NSUInteger zoomLevel;

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel
                   animated:(BOOL)animated;

@end


@implementation MKMapView (ZoomLevel)

- (void)setZoomLevel:(NSUInteger)zoomLevel {
    [self setCenterCoordinate:self.centerCoordinate zoomLevel:zoomLevel animated:NO];
}

- (NSUInteger)zoomLevel {
    return log2(360 * ((self.frame.size.width/256) / self.region.span.longitudeDelta)) + 1;
}

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated {
    MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256);
    [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated];
}

@end

मामूली सुधार:- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated { MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256); [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated]; }
मोनोबोनो

धन्यवाद! हाँ, आप सही हैं, मैंने वास्तव में अपने प्रोजेक्ट से कोड निकाल लिया जहाँ यह MKMapView के अतिरिक्त होने के बजाय एक फ़ंक्शन था। मैंने आपके सुधार को दर्शाने के लिए कोड को संपादित किया है।
क्वेंटिनाडैम

1
वर्तमान ज़ूम स्तर को पूरा करने के लिए उस फॉर्मूले का उल्टा क्या है?
निक

1
मुझे लगता है कि यह है:double z = log2(360 * ((self.mapView.frame.size.width/256) / self.mapView.region.span.longitudeDelta));
निक

1
@devios, ज़ूम स्तर 1 पर, पूरी दुनिया (360 °) 256px चौड़ी 1 टाइल में फिट होती है। ज़ूम स्तर 2 पर, पूरी दुनिया (360 °) 256px (512px) की 2 टाइलों में फिट होती है। ज़ूम स्तर 3 पर, पूरी दुनिया (360 °) 256px (1024px), आदि की 4 टाइलों में फिट होती है
क्वेंटिनाडैम

31

यह अंतर्निहित नहीं है, लेकिन मैंने इस कोड को देखा / उपयोग किया है । यह आपको इसका उपयोग करने की अनुमति देता है:

[mapView setCenterCoordinate:myCoord zoomLevel:13 animated:YES];

नोट: यह मेरा कोड नहीं है, मैंने इसे नहीं लिखा है, इसलिए मैं इसका श्रेय नहीं ले सकता


1
वाह, इसके बहुत सारे कोड, यू को लगता है कि इसे अंदर बनाया जाना चाहिए। धन्यवाद एक नज़र होगा कि यह कैसे किया जाता है।
सिस्टम

1
आप .m और .h फ़ाइल प्राप्त कर सकते हैं, इसे अपनी परियोजना में जोड़ सकते हैं, फिर अपने मानचित्र दृश्य नियंत्रक में इसे संदर्भित कर सकते हैं और इसका उपयोग कर सकते हैं जैसे कि यह MKMapView पर एक विधि थी, ओह श्रेणियों की खुशियाँ!
पोस्टमैन

2
मेरे लिए काम नहीं किया, यह पहले की तरह ही ज़ूम स्तर प्रदर्शित करता है। मुझसे कुछ गलत हो रहा होगा।
प्रणाली

17

आप MKCoordinateRegion का उपयोग करके और इसकी अवधि अक्षांश और देशांतर डेल्टा सेट करके भी ज़ूम कर सकते हैं। नीचे एक त्वरित संदर्भ है और यहां iOS संदर्भ है। यह कुछ भी फैंसी नहीं करेगा, लेकिन जब यह नक्शा खींचता है तो आपको ज़ूम सेट करने की अनुमति देनी चाहिए।


MKCoordinateRegion region;
region.center.latitude = {desired lat};
region.center.longitude = {desired lng};
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
mapView.region = region;

1 संपादित करें:

MKCoordinateRegion region;
region.center.latitude = {desired lat};
region.center.longitude = {desired lng};
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:TRUE];

1
इससे मुझे कोई फर्क नहीं पड़ा, जब मैंने कुछ मान बदले, तो यह सिर्फ नक्शे को लोड नहीं करता।
सिस्टम

क्या आप इसे सेट कर रहे हैं जब नक्शा लोड हो रहा है या आप लोड होने के बाद हेरफेर करने की कोशिश कर रहे हैं? क्या आप अपने डेल्टास के रूप में 1 या एक छोटी संख्या का उपयोग कर रहे हैं? बस आवश्यकताओं को समझने की कोशिश कर रहा है।
DerekH

मैंने इसे रनटाइम से पहले सेट किया। मैंने 1 से ऊपर और नीचे के मानों का परीक्षण किया
सिस्टम

1
अच्छा उत्तर लेकिन अक्षांश को बदलने की कोशिश करें, देशांतर डेल्टा को 0.1 - यह अधिक ज़ूम किया गया है।
डैनियल क्रिज़्ज़कोव्स्की

12

एक सरल स्विफ्ट कार्यान्वयन, यदि आप आउटलेट का उपयोग करते हैं।

@IBOutlet weak var mapView: MKMapView! {
    didSet {
        let noLocation = CLLocationCoordinate2D()
        let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 500, 500)
        self.mapView.setRegion(viewRegion, animated: false)
    }
}

@ करनाल के उत्तर के आधार पर।


12

स्विफ्ट कार्यान्वयन

import Foundation
import MapKit

class MapViewWithZoom: MKMapView {

    var zoomLevel: Int {
        get {
            return Int(log2(360 * (Double(self.frame.size.width/256) / self.region.span.longitudeDelta)) + 1);
        }

        set (newZoomLevel){
            setCenterCoordinate(coordinate:self.centerCoordinate, zoomLevel: newZoomLevel, animated: false)
        }
    }

    private func setCenterCoordinate(coordinate: CLLocationCoordinate2D, zoomLevel: Int, animated: Bool) {
        let span = MKCoordinateSpan(latitudeDelta: 0, longitudeDelta: 360 / pow(2, Double(zoomLevel)) * Double(self.frame.size.width) / 256)
        setRegion(MKCoordinateRegion(center: coordinate, span: span), animated: animated)
    }
}

1
मैं 100% निश्चित नहीं हूं, लेकिन मुझे लगता है कि जब आप अपना निर्माण IBOutletकरते हैं map, तो आप इसे MapViewWithZoomएक साधारण के बजाय परिभाषित करते हैं MKMapView। उसके बाद, आप बस ज़ूम स्तर को map.zoomLevel = 1या इसके साथ सेट कर सकते हैंmap.zoomLevel = 0.5
Zonker.in.Geneva

1
इस पर कुछ टिप्पणी अधिक सहायक होगी। यह स्विफ्ट 3 में काम कर रही है।
nyxee

महान समाधान! लेकिन मैं इसे एक एक्सटेंशन के रूप में अधिक पसंद करता हूं, और एक अजीब बात है: वास्तव में ज़ूम आउट करने के लिए, 2 की तरह गिरावट की आवश्यकता हैmapView.zoomLevel -= 2
अलेक्जेंडर

7

के लिए स्विफ्ट 3 यह बहुत तेजी से आगे बताया गया है:

private func setMapRegion(for location: CLLocationCoordinate2D, animated: Bool)
{
    let viewRegion = MKCoordinateRegionMakeWithDistance(location, <#T##latitudinalMeters: CLLocationDistance##CLLocationDistance#>, <#T##longitudinalMeters: CLLocationDistance##CLLocationDistance#>)
    MapView.setRegion(viewRegion, animated: animated)
}

बस लेट को परिभाषित करें- लॉन्ग- <CLLocationDistance>मेटर्स और मैपव्यू आपके मूल्यों के लिए जूम स्तर को फिट करेंगे।


"मैपव्यू आपके मानों के लिए ज़ूम स्तर फिट होगा" से आपका क्या मतलब है? मुझे लगता है कि ओपी ज़ूम स्तर को स्वयं निर्धारित करना चाहता है या आप जो सुझाव देते हैं, आप उसे कैसे करेंगे?
रपर

6

@ आदिलसूमरो के शानदार जवाब पर आधारित । मैं इसे लेकर आया हूं:

@interface MKMapView (ZoomLevel)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel
                   animated:(BOOL)animated;

-(double) getZoomLevel;
@end



@implementation MKMapView (ZoomLevel)

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
                  zoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated {
    MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.frame.size.width/256);
    [self setRegion:MKCoordinateRegionMake(centerCoordinate, span) animated:animated];
}


-(double) getZoomLevel {
    return log2(360 * ((self.frame.size.width/256) / self.region.span.longitudeDelta));
}

@end

3

मुझे आशा है कि कोड टुकड़ा के बाद आपको मदद मिलेगी।

- (void)handleZoomOutAction:(id)sender {
    MKCoordinateRegion newRegion=MKCoordinateRegionMake(mapView.region.center,MKCoordinateSpanMake(mapView.region.s       pan.latitudeDelta/0.5, mapView.region.span.longitudeDelta/0.5));
    [mapView setRegion:newRegion];
}


- (void)handleZoomInAction:(id)sender {
    MKCoordinateRegion newRegion=MKCoordinateRegionMake(mapView.region.center,MKCoordinateSpanMake(mapView.region.span.latitudeDelta*0.5, mapView.region.span.longitudeDelta*0.5));
    [mapView setRegion:newRegion];
}

ज़ूम स्तर को कम करने या बढ़ाने के लिए आप 0.5 के आधार पर कोई भी मूल्य चुन सकते हैं। मैंने दो बटन क्लिक करने पर इन विधियों का उपयोग किया है।


2

मानचित्र के ज़ूम और स्थिति को बचाने और पुनर्स्थापित करने के लिए NSUserDefaults का उपयोग करते हुए एक स्विफ्ट 2.0 उत्तर।

मानचित्र की स्थिति को बचाने और ज़ूम करने का कार्य:

func saveMapRegion() {
    let mapRegion = [
        "latitude" : mapView.region.center.latitude,
        "longitude" : mapView.region.center.longitude,
        "latitudeDelta" : mapView.region.span.latitudeDelta,
        "longitudeDelta" : mapView.region.span.longitudeDelta
    ]
    NSUserDefaults.standardUserDefaults().setObject(mapRegion, forKey: "mapRegion")
}

हर बार जब नक्शा ले जाया जाता है तो फ़ंक्शन को चलाएं:

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) 
{
        saveMapRegion();
}

नक्शा ज़ूम और स्थिति को बचाने के लिए कार्य:

func restoreMapRegion() 
{
    if let mapRegion = NSUserDefaults.standardUserDefaults().objectForKey("mapRegion") 
    {

        let longitude = mapRegion["longitude"] as! CLLocationDegrees
        let latitude = mapRegion["latitude"] as! CLLocationDegrees
        let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)

        let longitudeDelta = mapRegion["latitudeDelta"] as! CLLocationDegrees
        let latitudeDelta = mapRegion["longitudeDelta"] as! CLLocationDegrees
        let span = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)

        let savedRegion = MKCoordinateRegion(center: center, span: span)

        self.mapView.setRegion(savedRegion, animated: false)
    }
}

इसे व्यूडीडलड में जोड़ें:

restoreMapRegion()

1

मुझे पता है कि यह एक देर से उत्तर है, लेकिन मैं अभी ज़ूम स्तर सेट करने के मुद्दे को स्वयं हल करना चाहता हूं। गोल्डमाइन का जवाब बहुत अच्छा है लेकिन मैंने पाया कि यह मेरे आवेदन में पर्याप्त रूप से अच्छी तरह से काम नहीं कर रहा है।

करीब से निरीक्षण करने पर गोल्डमाइन कहती है कि "देशांतर रेखाएं मानचित्र के किसी भी बिंदु पर समान रूप से अलग-अलग फैली हुई हैं"। यह सच नहीं है, यह वास्तव में अक्षांश रेखाएं हैं जो -90 (दक्षिणी ध्रुव) से +90 (उत्तरी ध्रुव) तक समान रूप से फैली हुई हैं। ध्रुवों पर एक बिंदु में परिवर्तित, भूमध्य रेखा पर देशांतर रेखाएं उनके सबसे चौड़े स्थान पर होती हैं।

इसलिए मैंने जो कार्यान्वयन अपनाया है वह अक्षांश गणना का उपयोग इस प्रकार है:

@implementation MKMapView (ZoomLevel)

- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate
    zoomLevel:(NSUInteger)zoom animated:(BOOL)animated
{
    MKCoordinateSpan span = MKCoordinateSpanMake(180 / pow(2, zoom) * 
        self.frame.size.height / 256, 0);
    [self setRegion:MKCoordinateRegionMake(coordinate, span) animated:animated];
}

@end

आशा है कि यह इस देर से चरण में मदद करता है।


ठीक है ऊपर की अनदेखी। गोल्डमाइन सही है देशांतर रेखाएं समान रूप से फैली हुई हैं, क्योंकि मानचित्रों के लिए मर्केटर प्रक्षेपण का उपयोग किया जाता है। नए iOS 7 MKTileOverlay वर्ग को उप-वर्ग के साथ करने के लिए मेरे आवेदन में एक और मामूली बग से उत्पन्न समाधान के साथ मेरी समस्याएं।
gektron

आप अपनी टिप्पणी में शामिल जानकारी को प्रतिबिंबित करने के लिए अपने पोस्ट को अपडेट करने पर विचार करना चाह सकते हैं।
डेरेक ली

1

स्विफ्ट:

Map.setRegion(MKCoordinateRegion(center: locValue, latitudinalMeters: 200, longitudinalMeters: 200), animated: true)

locValue अपने समन्वय है।


1

यहाँ, मैंने अपना जवाब दिया और इसके तेज ४.२ के लिए काम किया ।

MKMapView केंद्र और ज़ूम इन करें


यदि मैं यहां क्लिक करता हूं और नीचे स्क्रॉल करता हूं, और वहां आपके लिंक पर क्लिक करता हूं, तो मैं खुद को यहां फिर से ढूंढूंगा और फिर मैं यहां क्लिक करूंगा और अब मैं एक अनंत लूप में फंस गया हूं th
Matthijs

@Matthijs मैंने लिंक को सही कर दिया है। कृपया जाँचें और उत्तर दें।
आशु

0

क्वेंटिनाडम के उत्तर के आधार पर

स्विफ्ट 5.1

// size refers to the width/height of your tile images, by default is 256.0
// Seems to get better results using round()
// frame.width is the width of the MKMapView

let zoom = round(log2(360 * Double(frame.width) / size / region.span.longitudeDelta))

धन्यवाद, अच्छा लग रहा है जब नक्शा उत्तर का सामना कर रहा है। लेकिन क्या होगा अगर आप नक्शे को घुमा रहे हैं? क्या होगा अगर चुटकी कोण 0 से अलग है?
पियर 23

0

MKMapViewइस उत्तर के आधार पर विस्तार (+ फ़्लोटिंग-पॉइंट ज़ूम स्तर सटीकता):

import Foundation
import MapKit

extension MKMapView {
    var zoomLevel: Double {
        get {
            return log2(360 * (Double(self.frame.size.width / 256) / self.region.span.longitudeDelta)) + 1
        }

        set (newZoomLevel){
            setCenterCoordinate(coordinate:self.centerCoordinate, zoomLevel: newZoomLevel, animated: false)
        }
    }

    private func setCenterCoordinate(coordinate: CLLocationCoordinate2D, zoomLevel: Double, animated: Bool) {
        let span = MKCoordinateSpan(latitudeDelta: 0, longitudeDelta: 360 / pow(2, zoomLevel) * Double(self.frame.size.width) / 256)
        setRegion(MKCoordinateRegion(center: coordinate, span: span), animated: animated)
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.