#1.はじめに
Swiftで線を引きたいけどUIBezierPath?CAShapeLayer??なんて方のために、直感的に線を引けるクラスを作ってみました。
基本的な部分しか実装していないのでお好みで改変してもらえばいいかなと思います。
#2.ソースコード
今回のソースコードはこんな感じ。
LineView.swift
class LineView: UIView {
var pointList : [CGPoint]!
var lineWidth : CGFloat! = 1
var lineColor : UIColor! = UIColor.white
var fillColor : UIColor! = UIColor.clear
var isClose :Bool = true
var isAnimate :Bool = false
var animateDuretion : CFTimeInterval = 2
var shapeLayer :CAShapeLayer!
var path :UIBezierPath! = UIBezierPath()
func setPoint(points:CGPoint...){
pointList = []
for point in points{
self.pointList.append(point)
}
}
func setWidth(width:CGFloat){
self.lineWidth = width
}
func setFillColor(color:UIColor){
self.fillColor = color
}
func open(){
self.isClose = false
}
func close(){
self.isClose = true
}
func Animate(duration:CFTimeInterval = 2){
isAnimate = true
self.animateDuretion = duration
}
func setLineColor(color:UIColor){
self.lineColor = color;
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createAnimateLayer(){
drawPath()
shapeLayer = CAShapeLayer()
shapeLayer.frame = self.frame
shapeLayer.fillColor = self.fillColor.cgColor
shapeLayer.strokeColor = self.lineColor.cgColor
shapeLayer.lineWidth = self.lineWidth
shapeLayer.path = path.cgPath
self.layer.addSublayer(shapeLayer)
}
func drawPath(){
path = UIBezierPath()
path.move(to: pointList[0])
for i in 1 ..< pointList.count{
path.addLine(to: pointList[i])
}
if(self.isClose){
path.close()
}
}
override func draw(_ rect: CGRect) {
createAnimateLayer()
if(isAnimate){
strokeAnimation()
}
}
func strokeAnimation(){
let strokeAnimation = CABasicAnimation(keyPath: "strokeEnd")
strokeAnimation.fromValue = 0.0
strokeAnimation.toValue = 1.0
strokeAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
strokeAnimation.duration = self.animateDuretion
strokeAnimation.fillMode = CAMediaTimingFillMode.forwards
shapeLayer.add(strokeAnimation, forKey: nil)
}
}
#3.解説
各関数のざっくりとした説明は以下になります。
変数の初期値などは必要に応じて変更していただけるといいと思います。
関数 | 型 | 説明 |
---|---|---|
setPoint(points:CGPoint...) | - | 線を引く対象となる点を設定します。可変長引数のため、複数のCGPointを指定することが可能です。 |
setWidth(width:CGFloat) | - | 線の太さを設定します。 |
setFillColor(color:UIColor) | - | 塗りつぶしの色を設定します。colorに「UIColor.clear」を指定した場合には塗りつぶしは行われません。 |
open() | - | Pathを開かれた状態にします。始点と終点がパスで結ばれません。 |
close() | - | Pathを閉じた状態にします。始点と終点がパスで結ばれます。 |
Animate(duration:CFTimeInterval = 2) | - | ViewにaddSubviewされたタイミングで線を描画するアニメーションを行います。durationにCFTimeInterval(Double)型を与えることで、アニメーションの長さを変更します。 |
setLineColor(color:UIColor) | - | 線の色を設定します。 |
createAnimateLayer() | - | 線を描画するShapeLayerを生成します。 |
drawPath() | - | 線を描画するためのパスを生成します。 |
draw(_ rect: CGRect) | - | addSubview時などに呼ばれるメソッドです。詳細は調べてみてください。 |
#4.使用例
試しに星を描くサンプルを作成しました。
ViewController.swift
import UIKit
class LineView: UIView {
...
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let line = LineView(frame: self.view.bounds)
line.setPoint(points: CGPoint(x: view.frame.midX, y: view.frame.minY),CGPoint(x: view.frame.minX, y: view.frame.maxY),CGPoint(x: view.frame.maxX, y: view.frame.midY),CGPoint(x: view.frame.minX, y: view.frame.midY),CGPoint(x: view.frame.maxX, y: view.frame.maxY))
line.setFillColor(color: UIColor.init(red: 0/255, green: 0/255, blue: 255/255, alpha: 1))
line.setLineColor(color: UIColor.init(red: 255/255, green: 255/255, blue: 0/255, alpha: 1))
line.setWidth(width: 5)
line.Animate(duration: 5)
view.addSubview(line)
}
}
#5.おわりに
こういった汎用的なクラスをもっておくと作業効率が上がるような気がしますね。
趣味程度であれば言語を自分好みに拡張していくのが楽しくプログラミングを勉強する近道になると考えています。