見出し画像

【徒然iOS】気ままにUIKit61〜地図でお絵描き MKOverlay 地図に円や多角形を描く〜

概要

このマガジンは四十を過ぎたおっさんが、

を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。

今回

をハイ、レッツゴ🕺

前準備

念の為、

  1. バックアップ

  2. 新しいクラス

  3. ビューコントローラの追加

  4. イニシャルビューの変更

をいつも通りやってから本題へ💃

てな感じかな💦

本題

そもそも、Overlayとは何ぞ?

マップビューには直線以外の円や多角形も描くことができる機能

みたいだね🤔
使う時があるのか?🤔
とりあえず、レッツゴ🕺

⒈いつもどおり、MapKitを配置して、アウトレット接続

ハイ、完了

⒉Long Press Gestureをアクション接続

てな感じかな💦

⒊コードを組み込む

//
//  ViewController.swift
//
import UIKit
import MapKit
class ViewController: UIViewController,MKMapViewDelegate{
    @IBOutlet weak var testMapView: MKMapView!
    //ピンのリスト
    var coordinateList = [CLLocationCoordinate2D]()
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //デリゲート先を自分に設定する。
        testMapView.delegate = self
        //中心座標
        let center = CLLocationCoordinate2DMake(35.690553, 139.699579)
        //表示範囲
        let span = MKCoordinateSpanMake(0.005, 0.005)
        //中心座標と表示範囲をマップに登録する。
        let region = MKCoordinateRegionMake(center, span)
        testMapView.setRegion(region, animated:true)
    }
    //マップビュー長押し時の呼び出しメソッド
    @IBAction func pressMap(sender: UILongPressGestureRecognizer) {
        //マップビュー内のタップした位置を取得する。
        let location:CGPoint = sender.locationInView(testMapView)
        if (sender.state == UIGestureRecognizerState.Ended){
            //タップした位置を緯度、経度の座標に変換する。
            let mapPoint:CLLocationCoordinate2D = testMapView.convertPoint(location, toCoordinateFromView: testMapView)
            //ピンを作成してマップビューに追加する。
            let annotation = MKPointAnnotation()
            annotation.coordinate = CLLocationCoordinate2DMake(mapPoint.latitude, mapPoint.longitude)
            testMapView.addAnnotation(annotation)
            //追加したピンをリストに追加する。
            coordinateList.append(CLLocationCoordinate2D(latitude: mapPoint.latitude, longitude: mapPoint.longitude))
        }
    }
    //ピンタップ時の呼び出しメソッド
    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
        //ピンの数で場合分け
        if(coordinateList.count == 1) {
            //ピンを中心に半径100mの円をマップビューに追加する。
            let overlay = MKCircle(centerCoordinate: CLLocationCoordinate2D(latitude:coordinateList[0].latitude, longitude: coordinateList[0].longitude), radius:100)
            testMapView.addOverlay(overlay)
        } else if(coordinateList.count == 2) {
            //2点間の中心座標を求める。
            let centerX = (coordinateList[0].longitude + coordinateList[1].longitude)/2
            let centerY = (coordinateList[0].latitude + coordinateList[1].latitude)/2
            //2点間の距離から円の半径を求める。
            let aaa:CLLocation = CLLocation(latitude: coordinateList[0].latitude, longitude: coordinateList[0].longitude)
            let bbb:CLLocation = CLLocation(latitude: coordinateList[1].latitude, longitude: coordinateList[1].longitude)
            let radius = aaa.distanceFromLocation(bbb)/2
            //2点間の直線を直径とした縁をマップビューに追加する。
            let overlay = MKCircle(centerCoordinate: CLLocationCoordinate2D(latitude: centerY, longitude: centerX), radius:radius)
            testMapView.addOverlay(overlay)
        } else {
            //ピンを頂点にした多角形をマップビューに追加する。
            let overlay = MKPolygon(coordinates: &coordinateList, count: coordinateList.count)
            testMapView.addOverlay(overlay)
        }
    }
    //描画前の呼び出しメソッド
    func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
        //円と多角形の場合でインスタンスのクラスを分ける。
        let renderer:MKOverlayPathRenderer
        if overlay is MKCircle {
            renderer = MKCircleRenderer(overlay:overlay)
        } else {
            renderer = MKPolygonRenderer(overlay:overlay)
        }
        //図形の色をランダム生成する。
        renderer.fillColor = UIColor(red: CGFloat(drand48()),
            green: CGFloat(drand48()),
            blue: CGFloat(drand48()),
            alpha: 0.5)
        //ピンのリストをすべて削除する。
        coordinateList.removeAll()
        return renderer;
    }
}

を参考に、コードを書き換えて実行〜〜〜🕺

出来たけども、ピンの表示が旧型でないので〜〜〜

以下のコードを追加

//アノテーションビューを返すメソッド
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  let myView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil)
  //吹き出しを表示可能にする。
   myView.canShowCallout = true
  return myView
}
ハイ、完成🕺

何に使うんだろうと、冒頭で思ってたけど、、、


地図上でお絵描きできる〜〜〜〜〜🕺
空き地とかでどういう矩形になるかなんて時に使えるかもね💃

皇居みたいな広大な場所に新しい建物を作ろうとかね、、、💦
(皇居は恐れ多いけど、国会議事堂の近くで広大な空き地が一番近かったのよ😭)

今回のコード(まとめ)

class MapOverlayViewController: UIViewController, MKMapViewDelegate {
    
    @IBOutlet weak var myMapKitVIew: MKMapView!
    
    let x = 139.744858
    let y = 35.675888
    let latitudeDelta = 0.01
    let longitudeDelta = 0.01
    //ピンのリスト
    var coordinateList = [CLLocationCoordinate2D]()

    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //デリゲート先を自分に設定する。
        myMapKitVIew.delegate = self
        //中心座標
        let center = CLLocationCoordinate2DMake(y, x)
        //表示範囲
        let span = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)
        //中心座標と表示範囲をマップに登録する。
        let region = MKCoordinateRegion(center: center, span: span)
        myMapKitVIew.setRegion(region, animated:true)
    }
    //マップビュー長押し時の呼び出しメソッド
    @IBAction func myLongTap(_ sender: UILongPressGestureRecognizer) {
        //マップビュー内のタップした位置を取得する。
        let location:CGPoint = sender.location(in: myMapKitVIew)
        if (sender.state == UIGestureRecognizer.State.ended){
            //タップした位置を緯度、経度の座標に変換する。
            let mapPoint:CLLocationCoordinate2D = myMapKitVIew.convert(location, toCoordinateFrom: myMapKitVIew)
            //ピンを作成してマップビューに追加する。
            let annotation = MKPointAnnotation()
            annotation.coordinate = CLLocationCoordinate2DMake(mapPoint.latitude, mapPoint.longitude)
            myMapKitVIew.addAnnotation(annotation)
            //追加したピンをリストに追加する。
            coordinateList.append(CLLocationCoordinate2D(latitude: mapPoint.latitude, longitude: mapPoint.longitude))
        }
    }
    //ピンタップ時の呼び出しメソッド
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        //ピンの数で場合分け
        if(coordinateList.count == 1) {
            //ピンを中心に半径100mの円をマップビューに追加する。
            let overlay = MKCircle(center: CLLocationCoordinate2D(latitude:coordinateList[0].latitude, longitude: coordinateList[0].longitude), radius:100)
            myMapKitVIew.addOverlay(overlay)
        } else if(coordinateList.count == 2) {
            //2点間の中心座標を求める。
            let centerX = (coordinateList[0].longitude + coordinateList[1].longitude)/2
            let centerY = (coordinateList[0].latitude + coordinateList[1].latitude)/2
            //2点間の距離から円の半径を求める。
            let aaa:CLLocation = CLLocation(latitude: coordinateList[0].latitude, longitude: coordinateList[0].longitude)
            let bbb:CLLocation = CLLocation(latitude: coordinateList[1].latitude, longitude: coordinateList[1].longitude)
            let radius = aaa.distance(from: bbb)/2
            //2点間の直線を直径とした縁をマップビューに追加する。
            let overlay = MKCircle(center: CLLocationCoordinate2D(latitude: centerY, longitude: centerX), radius:radius)
            myMapKitVIew.addOverlay(overlay)
        } else {
            //ピンを頂点にした多角形をマップビューに追加する。
            let overlay = MKPolygon(coordinates: &coordinateList, count: coordinateList.count)
            myMapKitVIew.addOverlay(overlay)
        }
    }
    //描画前の呼び出しメソッド
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        //円と多角形の場合でインスタンスのクラスを分ける。
        let renderer:MKOverlayPathRenderer
        if overlay is MKCircle {
            renderer = MKCircleRenderer(overlay:overlay)
        } else {
            renderer = MKPolygonRenderer(overlay:overlay)
        }
        //図形の色をランダム生成する。
        renderer.fillColor = UIColor(
            red: CGFloat(drand48()),
            green: CGFloat(drand48()),
            blue: CGFloat(drand48()),
            alpha: 0.5)
        //ピンのリストをすべて削除する。
        coordinateList.removeAll()
        return renderer;
    }
    //アノテーションビューを返すメソッド
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
      let myView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil)
      //吹き出しを表示可能にする。
       myView.canShowCallout = true
      return myView
    }
}

Apple公式

さて、次回は

をレッツゴする🕺

この記事が気に入ったらサポートをしてみませんか?