質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.64%

swift3 マップ上に画面から動かない円と線を描画したい

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,039

harima

score 18

MKMapView上に画面の中心から動かない円と線を描きたい。
現在、MKPolylineで描くとスクロールをして場面から見えなくなってしまう。
その他のarcCircleは、扇型の領域を描き、中心部を透明にできない。地図はスクロールして、円、線はスクロールしない方法はありませんか?宜しくお願い致します。

//  ViewController.swift
import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
    var myMapView : MKMapView!
    var myLocationManager : CLLocationManager!
    var imHearBtn : UIButton!
    // 縮尺.
    var myLatDist : CLLocationDistance = 10
    var myLonDist : CLLocationDistance = 10
    let DEFAULT_DISTANCE : CLLocationDistance = 10

    private var addedLayers = [CAShapeLayer]()
    var center: CLLocationCoordinate2D!
    var rendere = 0
    let LINE_1 = 1
    let CIRCLE = 3

    override func viewDidLoad() {
        super.viewDidLoad()

        let maxWidth : CGFloat = self.view.bounds.width
        let maxHeight: CGFloat = self.view.bounds.height

        myMapView = MKMapView()
        myMapView.frame = self.view.frame(forAlignmentRect: CGRect(x: 0.0, y: 20.0 + 50.0, width: maxWidth, height: maxHeight - 20.0 - 50.0 - 50.0))
        myMapView.delegate = self
        myMapView.setCenter(self.myMapView.userLocation.coordinate, animated: true)
        myMapView.setUserTrackingMode(.none, animated: true)
        myMapView.showsUserLocation = true
        view.addSubview(self.myMapView)

        imHearBtn = UIButton()
        imHearBtn.frame = CGRect(x: maxWidth / 5.0 * 1.0, y: maxHeight - 50.0, width: maxWidth / 5.0, height: 50.0)
        imHearBtn.backgroundColor = UIColor.green
        imHearBtn.layer.cornerRadius = 10.0
        imHearBtn.setTitle("現在地", for: .normal)
        imHearBtn.tag = 3
        imHearBtn.addTarget(self, action: #selector(ViewController.onClickMyButton(sender:)), for: .touchUpInside)
        self.view.addSubview(imHearBtn)

        myLocationManager = CLLocationManager()
        myLocationManager.delegate = self
        myLocationManager.distanceFilter = 100.0
        myLocationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters

        myLocationManager.startUpdatingLocation()

        let status = CLLocationManager.authorizationStatus()

        if(status != CLAuthorizationStatus.authorizedWhenInUse){
            print("not determined")
            myLocationManager.requestWhenInUseAuthorization()

       }

        arcCircle(startRagian: 0.0, endRagian: 90.0, radius: 50, red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0, lineWidth: 20.0)
        arcCircle(startRagian: 0.0, endRagian: 90.0, radius: 40, red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0, lineWidth: 18.0)

    }

    func arcCircle(startRagian:CGFloat, endRagian:CGFloat, radius:CGFloat, red:CGFloat, green:CGFloat, blue:CGFloat, alpha:CGFloat, lineWidth:CGFloat){

        let pi = CGFloat(Double.pi)
        let start:CGFloat = pi / 180.0 * startRagian // 開始の角度
        let end : CGFloat = pi / 180.0 * endRagian// 終了の角度

        let center = CGPoint(x: self.view.frame.width / 2.0, y: self.view.frame.height / 2.0 + 10)
        let path: UIBezierPath = UIBezierPath();
        path.move(to: center)
        path.addArc(withCenter: CGPoint(x: self.view.frame.width/2, y:self.view.frame.height/2 + 10.0), radius: radius, startAngle: start, endAngle: end, clockwise: true) // 円弧

        let layer = CAShapeLayer()
        layer.fillColor = UIColor(red: red, green: green, blue: blue, alpha: alpha).cgColor
        layer.path = path.cgPath
        layer.lineWidth = lineWidth
        self.view.layer.addSublayer(layer)

        self.addedLayers.append(layer)
    }

    // GPSから値を取得した際に呼び出されるメソッド.
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        // 配列から現在座標を取得.
        let myLocations: NSArray = locations as NSArray
        let myLastLocation: CLLocation = myLocations.lastObject as! CLLocation
        let myLocation:CLLocationCoordinate2D = myLastLocation.coordinate

               // Regionを作成.
        let myRegion: MKCoordinateRegion = MKCoordinateRegionMakeWithDistance(myLocation, myLatDist, myLonDist);

        // MapViewに反映.
        myMapView.setRegion(myRegion, animated: true)

        // 直線を引く座標を作成
        let coordinate1 = CLLocationCoordinate2D(latitude: myLocation.latitude, longitude: myLocation.longitude)
        let coordinate2 = CLLocationCoordinate2D(latitude: myLocation.latitude, longitude: 0.0)
        let coordinate3 = CLLocationCoordinate2D(latitude: myLocation.latitude, longitude: -180.0)
        let coordinate4 = CLLocationCoordinate2D(latitude: 0.0,                 longitude: myLocation.longitude)
        let coordinate5 = CLLocationCoordinate2D(latitude: 90.0,                longitude: myLocation.longitude)

        // 座標を配列に格納
        var coordinates_1 = [coordinate1, coordinate2]
        var coordinates_2 = [coordinate1, coordinate3]
        var coordinates_3 = [coordinate1, coordinate4]
        var coordinates_4 = [coordinate1, coordinate5]

        //polyline作成
        let myPolyLine_1:MKPolyline = MKPolyline(coordinates: &coordinates_1, count: coordinates_1.count)
        let myPolyLine_2:MKPolyline = MKPolyline(coordinates: &coordinates_2, count: coordinates_2.count)
        let myPolyLine_3:MKPolyline = MKPolyline(coordinates: &coordinates_3, count: coordinates_3.count)
        let myPolyLine_4:MKPolyline = MKPolyline(coordinates: &coordinates_4, count: coordinates_4.count)

        // 円を描く
        // 地図の中心の座標.
        center = CLLocationCoordinate2DMake(myLocation.latitude, myLocation.longitude)
//        var center2 : CLLocationCoordinate2D!
//        center2 = CLLocationCoordinate2D(latitude: myLocation.latitude , longitude: myLocation.longitude)

        // 縮尺を設定.
        let mySpan: MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
        let myRegions: MKCoordinateRegion = MKCoordinateRegion(center: center, span: mySpan)

        // regionをmapViewに追加.
        myMapView.region = myRegions

        // 円を描画する(半径1000m).
        let myCircle_1: MKCircle = MKCircle(center: center, radius: CLLocationDistance(1000))

        // mapViewにlineを追加.

        rendere = LINE_1
        myMapView.add(myPolyLine_1)
        myMapView.add(myPolyLine_2)
        myMapView.add(myPolyLine_3)
        myMapView.add(myPolyLine_4)

        // myMapViewにcircleを追加
        rendere = CIRCLE
        myMapView.add(myCircle_1)
        myMapView.setRegion(myRegions, animated: true)
    }

    // Regionが変更された時に呼び出されるメソッド.
    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    }


    // addした際に呼ばれるデリゲートメソッド
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if (rendere == LINE_1) {
            // rendererを生成.
            let myPolyLineRendere: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)

            // 線の太さを指定.
            myPolyLineRendere.lineWidth = 2.0

            // 線の色を指定.
            myPolyLineRendere.strokeColor = UIColor.red

            return myPolyLineRendere

        } else { //if (rendere == CIRCLE) {

            // rendererを生成.
            let myCircleView: MKCircleRenderer = MKCircleRenderer(overlay: overlay)

            // 円の内部を赤色で塗りつぶす.
//            myCircleView.fillColor = UIColor(red: 0.0, green:1.0, blue: 1.0, alpha: 0.3)

            // 円周の線の色を黒色に設定.
            myCircleView.strokeColor = UIColor.darkGray

            // 円を透過させる.
            myCircleView.alpha = 1.0

            // 円周の線の太さ.
            myCircleView.lineWidth = 2.0

            return myCircleView
        }
    }

    func removeAllSubviews(parentView: UIView){
        let subviews = parentView.subviews
        for subview in subviews {
            subview.removeFromSuperview()
        }
    }

    func onClickMyButton(sender: UIButton) {

        if (sender.tag == 3){

            myLatDist = CLLocationDistance(DEFAULT_DISTANCE)
            myLonDist = CLLocationDistance(DEFAULT_DISTANCE)
            var cr:MKCoordinateRegion = myMapView.region
            cr.span.latitudeDelta = cr.center.latitude
            cr.span.longitudeDelta = cr.center.longitude
            let myCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(cr.span.latitudeDelta, cr.span.longitudeDelta)
            let myRegion: MKCoordinateRegion = MKCoordinateRegionMakeWithDistance(myCoordinate, CLLocationDistance(myLatDist), CLLocationDistance(myLonDist))
            myMapView.setRegion(myRegion, animated: true)

            myMapView.userTrackingMode = MKUserTrackingMode.follow
            myMapView.userTrackingMode = MKUserTrackingMode.none
            myMapView.setCenter(myMapView.userLocation.coordinate, animated: true)

            removeAllSubviews(parentView: myMapView)

            self.addedLayers.forEach {
                $0.removeFromSuperlayer()
            }
            viewDidLoad()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


長いリストになりますが、お願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

単に上にUIViewを重ねて、そこに描画するのはどうでしょうか。userIntaractionEnabledをfalseにしておけばタッチイベントが吸収されてしまうこともないはずです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる