LoginSignup
4
2

More than 3 years have passed since last update.

Swift5 フォーカスViewの設定

Last updated at Posted at 2018-06-30

こんにちは、アプリ開発エンジニアの 永田です。

Swift5~ フォーカスViewの設定を公開いたします。
自身の製作中のアプリで実装している一部です。

動作

Focus.gif

2018/6/30で審査待ちの状態です。GIF加工技術を実装しました。

TalkingRecord

次はAR技術の実装に挑戦しようと思います。 

参考サイト

カメラ実装のオープンソースです。実装はobjecの実装です。
まるっきり同じようにSwiftで実装挑戦する価値も大きかったのですが、
オリジナルの部分を作りたく、構造を読み解かせていただきました。

参考サイト

こちらはViewを切り抜くロジックです。Swift2系だと思います。
動的な実装にして、Blurの部分も追加して、最新言語にアップデートしました。

全体のソース

SampleFocus

フォーカスのデザイン部分

CALayer()メソッドで、座標、サイズの設定
CAShapeLayer()メソッドでくり抜く部分を作り、
UIBezierPathメソッドでくり抜く座標、サイズを作ります。

四角のデザイン部分は左上の座標変換メソッドと同じ計算で実装をしています。

//角のUI設定 左上の例
girdViewLeftTopWidth.backgroundColor = UIColor.white
girdViewLeftTopWidth.frame = CGRect(x: vc.lineDashView.frame.origin.x, y: vc.lineDashView.frame.origin.y-wide, width: width, height: wide)

スクリーンショット 2018-06-30 21.40.53.png

このサンプルでは、SEに合わせていますが、
アプリ内では全デバイス対応の計算式を実装しています。
スクリーンショット 2018-06-30 21.52.28.png

 override func draw(_ rect: CGRect) {
        //フォーカス内の罫線の設定
        var i: CGFloat = screenHeight
        i -= screenHeight / 3
        lineColor.move(to: CGPoint(x:screenWidth, y: i*0.5))
        lineColor.addLine(to: CGPoint(x: 0 , y: i*0.5))
        UIColor.white.setStroke()
        lineColor.stroke()

        lineColor2.move(to: CGPoint(x:screenWidth, y: i))
        lineColor2.addLine(to: CGPoint(x: 0 , y: i))
        UIColor.white.setStroke()
        lineColor2.stroke()

        var i3: CGFloat = screenWidth
        i3 = screenWidth / 3
        lineColor3.move(to: CGPoint(x:i3, y: 0))
        lineColor3.addLine(to: CGPoint(x: i3 , y: screenHeight))
        UIColor.white.setStroke()
        lineColor3.stroke()

        lineColor4.move(to: CGPoint(x:i3*2, y: 0))
        lineColor4.addLine(to: CGPoint(x: i3*2 , y: screenHeight))
        UIColor.white.setStroke()
        lineColor4.stroke()
    }

タップされた位置情報の認識

CGPoint()のcontainsメソッド

シーケンスに、指定された述語を満たす要素が含まれているかどうかを示すブール値を返します。
containsメソッドで画面をタップした場合に、タップされた位置がどの部分か、判定する際に実装しています。

左上だったら左上の座標変換メソッドの実行というアーキテクチャです。

        //タップした領域を取得
        let frame = views.lineDashView.frame
        frame.insetBy(dx: -CGFloat(32), dy: -CGFloat(32))
        var topLeftRect: CGRect = frame
        topLeftRect.size.height = CGFloat(64)
        topLeftRect.size.width = CGFloat(64)

        if topLeftRect.contains(point) {
            return TouchFlag.touchTopLeft
        }

左上の座標変換メソッド
左上の場合は、幅と高さが可変しますが、originのpointは変更しません。<-値の中身は変更していますが、プログラムの変数は可変させていません。

 case .touchTopLeft:
            if endPoint.y != 0 {
                views.lineDashView.frame.origin.x = point.x
                views.lineDashView.frame.size.width = -point.x + endFrame.maxX
                views.lineDashView.frame.origin.y = point.y
                views.lineDashView.frame.size.height =  -point.y + endFrame.maxY
            } else {
                views.lineDashView.frame.origin.x =  point.x
                views.lineDashView.frame.size.width =  -point.x + views.imageView.frame.width
                views.lineDashView.frame.origin.y = point.y
                views.lineDashView.frame.size.height = -point.y + views.lineDashView.screenWidth + 60
                break
            }
        }

同様に右上、右下、横、上、下等、計算をしたメソッドをケースで分岐させているアーキテクチャです。

フォーカスの計算後、ズーム機能

スクリーンショット 2018-06-30 21.42.37.png

ViewController内のUIPanGestureRecognizerから指が離れた3秒後にanimetionSetメソッドを発行して、gestureObject.matchGround(views: self, imageView: imageView)メソッドでズーム機能を実装しています。

この実装のズーム幅も自作で設定しています。
最後に画面から指が離れた際のフォーカスの形で、そのパターンからズーム域を算出しています。

 @objc func animetionSet() {
        if timerFlag == false {
            gestureObject.matchGround(views: self, imageView: imageView)
            timerFlag = true
            timer.invalidate()
        }
    }

まとめ

フォーカスを作るオリジナルロジックなので、一部を参考にする形でも良いかもしれません。
フォーカス内の罫線を全デバイスで合わせるロジックを抜いてみました。

プログラマーの方でしたら、その部分を自身のスキルで補えると思います。
仮に補えない場合は、その技術が足りないことになります。<-全デバイスに対応しました。18/7/22
シュミレーターですと罫線が見えないかも。

変更点 <-全デバイスに対応しました。

self.view.addSubview(self.lineDashView)を2番目から3番目にしました。

class ViewController
 DispatchQueue.main.async {
        self.cALayerView.effect(vc: self,bool: true, boolSecound: true)
        self.cALayerView.tori(vc: self, bool: false)
        self.view.addSubview(self.lineDashView)
        }
 タップ域がなくなるので、長さを調整しました。
 var screenHeight = UIScreen.main.bounds.height - 30

全デバイスに合う理由 <-全デバイスに対応しました。18/7/22

Viewのくり抜き後に罫線をaddSubするので、あとは汎用的に設定されるだけです。

最新の技術を実装する場合に、様々に補える技術があるのが前提です。

なので、何の技術が必要になるかを把握することが重要と考えています。
把握したうえで、勉強や研究するのも、実装をする近道かもしれません。

動画をGIF化する技術もARの進捗次第で公開していきたいと思います。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2