【Swift4】矢印を描画する
UIViewController上に矢印を描画したい。
幾つかの方法があるようだが、今回はUIBezierPathによる描画を試みた。
参考にしたのは以下のサイト:
qiita.com
i-app-tec.com
では本題。
構想としては、画面上にUIView()を生成し、その中に始点と終点を指定して矢印を描画していく。
動的に矢印を増やしたいため、1つのUIView()につき1つの矢印を描画する(静的な場合は1つのUIView()に複数の矢印を描画することも可能です)。
まず、UIViewのサブクラスとしてArrowViewクラスを作ります。
⌘Nで新しいファイルを作成 -> [Swift File] を選択。タイトルはArrowViewとします。
import UIKit class ArrowView: UIView { var fromPoint: CGPoint! var toPoint: CGPoint! init(frame: CGRect, from: CGPoint, to: CGPoint) { super.init(frame: frame) fromPoint = from toPoint = to self.isOpaque = false self.isUserInteractionEnabled = false } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(_ rect: CGRect) { let arrow = UIBezierPath.arrow ( from: fromPoint, to: toPoint, tailWidth: 0.5, headWidth: 8, headLength: 8 ) UIColor.black.setStroke() UIColor.black.setFill() arrow.lineWidth = 0.9 arrow.stroke() } } extension UIBezierPath { static func arrow(from start: CGPoint, to end: CGPoint, tailWidth: CGFloat, headWidth: CGFloat, headLength: CGFloat) -> UIBezierPath { let length = hypot(end.x - start.x, end.y - start.y) let tailLength = length - headLength func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint { return CGPoint(x: x, y: y) } let points: [CGPoint] = [ p(0, tailWidth / 2), p(tailLength, tailWidth / 2), p(tailLength, headWidth / 2), p(length, 0), p(tailLength, -headWidth / 2), p(tailLength, -tailWidth / 2), p(0, -tailWidth / 2) ] let cosine = (end.x - start.x) / length let sine = (end.y - start.y) / length let transform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: start.x, ty: start.y) let path = CGMutablePath() path.addLines(between: points, transform: transform) path.closeSubpath() return self.init(cgPath: path) } }
次に、表示したいView上で以下のコードでArrowViewを生成し、addSubViewします。
今回は ViewController: UIViewController 上に生成してみます。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //ArrowViewを生成 let arrow1 = ArrowView(frame: view.frame, from: CGPoint(x:100, y:100), to: CGPoint(x:10, y:10)) self.view.addSubview(arrow1) } }
これで矢印が描画できると思います。
各種プロパティは用途に応じて適宜変更してください。
isOpaque = false //背景色を黒にしない(デフォルトはtrue: 黒) isUserInteractionEnabled = false // タップを無効化する UIColor.black.setStroke() // 矢印の色を設定 UIColor.black.setFill() // 中抜きにしない arrow.lineWidth = 0.9 // 線の太さを設定