実行時にコードにUIView
を追加しました。
UIBezierPath
を描画したいのですが、これはUIViewのdrawRect
をオーバーライドする必要があるということですか?
または、カスタムUIView
に描画する別の方法がありますか?
UIView
を生成するコードは次のとおりです。
UIView* shapeView = [[UIView alloc]initWithFrame:CGRectMake(xOrigin,yOrigin+(i*MENU_BLOCK_FRAME_HEIGHT), self.shapeScroll.frame.size.width, MENU_BLOCK_FRAME_HEIGHT)];
shapeView.clipsToBounds = YES;
そして、これはUIBezierPath
を作成して返す関数です:
- (UIBezierPath*)createPath
{
UIBezierPath* path = [[UIBezierPath alloc]init];
[path moveToPoint:CGPointMake(100.0, 50.0)];
[path addLineToPoint:CGPointMake(200.0,50.0)];
[path addLineToPoint:CGPointMake(200.0, 200.0)];
[path addLineToPoint:CGPointMake(100.0, 200.0)];
[path closePath];
return path;
}
ベジエのパスを使用してカスタムシェイプを作成する方法は言うまでもなく、ベジエの発音方法すら知らなかったのは、少し前のことです。以下は私が学んだことです。彼らは最初に見えるほど怖くないことが判明しました。
主な手順は次のとおりです。
drawRect
で、またはCAShapeLayer
を使用してパスを描画します。あなたは何でもできますが、例として以下の形を選択しました。キーボードのポップアップキーである可能性があります。
シェイプデザインを振り返り、直線(直線の場合)、円弧(円および丸い角の場合)、曲線(その他の場合)の単純な要素に分解します。
サンプルデザインは次のようになります。
任意に左下隅から開始し、時計回りに作業します。画像のグリッドを使用して、ポイントのx値とy値を取得します。ここではすべてをハードコーディングしますが、もちろん実際のプロジェクトではそうしません。
基本的なプロセスは次のとおりです。
UIBezierPath
を作成しますmoveToPoint
を使用してパス上の開始点を選択しますaddLineToPoint
addArcWithCenter
addCurveToPoint
closePath
でパスを閉じます上の画像のパスを作成するコードは次のとおりです。
func createBezierPath() -> UIBezierPath {
// create a new path
let path = UIBezierPath()
// starting point for the path (bottom left)
path.move(to: CGPoint(x: 2, y: 26))
// *********************
// ***** Left side *****
// *********************
// segment 1: line
path.addLine(to: CGPoint(x: 2, y: 15))
// segment 2: curve
path.addCurve(to: CGPoint(x: 0, y: 12), // ending point
controlPoint1: CGPoint(x: 2, y: 14),
controlPoint2: CGPoint(x: 0, y: 14))
// segment 3: line
path.addLine(to: CGPoint(x: 0, y: 2))
// *********************
// ****** Top side *****
// *********************
// segment 4: arc
path.addArc(withCenter: CGPoint(x: 2, y: 2), // center point of circle
radius: 2, // this will make it meet our path line
startAngle: CGFloat(M_PI), // π radians = 180 degrees = straight left
endAngle: CGFloat(3*M_PI_2), // 3π/2 radians = 270 degrees = straight up
clockwise: true) // startAngle to endAngle goes in a clockwise direction
// segment 5: line
path.addLine(to: CGPoint(x: 8, y: 0))
// segment 6: arc
path.addArc(withCenter: CGPoint(x: 8, y: 2),
radius: 2,
startAngle: CGFloat(3*M_PI_2), // straight up
endAngle: CGFloat(0), // 0 radians = straight right
clockwise: true)
// *********************
// ***** Right side ****
// *********************
// segment 7: line
path.addLine(to: CGPoint(x: 10, y: 12))
// segment 8: curve
path.addCurve(to: CGPoint(x: 8, y: 15), // ending point
controlPoint1: CGPoint(x: 10, y: 14),
controlPoint2: CGPoint(x: 8, y: 14))
// segment 9: line
path.addLine(to: CGPoint(x: 8, y: 26))
// *********************
// **** Bottom side ****
// *********************
// segment 10: line
path.close() // draws the final line to close the path
return path
}
注:上記のコードの一部は、単一のコマンドに線と円弧を追加することで削減できます(円弧には暗黙の開始点があるため)。詳細については here を参照してください。
レイヤーまたはdrawRect
のいずれかにパスを描画できます。
方法1:レイヤーにパスを描く
カスタムクラスは次のようになります。ビューの初期化時に、ベジエパスを新しいCAShapeLayer
に追加します。
import UIKit
class MyCustomView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
// Create a CAShapeLayer
let shapeLayer = CAShapeLayer()
// The Bezier path that we made needs to be converted to
// a CGPath before it can be used on a layer.
shapeLayer.path = createBezierPath().cgPath
// apply other properties related to the path
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.lineWidth = 1.0
shapeLayer.position = CGPoint(x: 10, y: 10)
// add the new layer to our custom view
self.layer.addSublayer(shapeLayer)
}
func createBezierPath() -> UIBezierPath {
// see previous code for creating the Bezier path
}
}
そして、このようにView Controllerでビューを作成します
override func viewDidLoad() {
super.viewDidLoad()
// create a new UIView and add it to the view controller
let myView = MyCustomView()
myView.frame = CGRect(x: 100, y: 100, width: 50, height: 50)
myView.backgroundColor = UIColor.yellow
view.addSubview(myView)
}
我々が得る...
うーん、私はすべての数値をハードコーディングしているため、少し小さいです。しかし、次のようにパスのサイズを拡大できます。
let path = createBezierPath()
let scale = CGAffineTransform(scaleX: 2, y: 2)
path.apply(scale)
shapeLayer.path = path.cgPath
方法2:draw
にパスを描く
draw
の使用は、レイヤーへの描画よりも遅いため、必要ない場合は推奨されません。
カスタムビューの修正されたコードは次のとおりです。
import UIKit
class MyCustomView: UIView {
override func draw(_ rect: CGRect) {
// create path (see previous code)
let path = createBezierPath()
// fill
let fillColor = UIColor.white
fillColor.setFill()
// stroke
path.lineWidth = 1.0
let strokeColor = UIColor.blue
strokeColor.setStroke()
// Move the path to a new location
path.apply(CGAffineTransform(translationX: 10, y: 10))
// fill and stroke the path (always do these last)
path.fill()
path.stroke()
}
func createBezierPath() -> UIBezierPath {
// see previous code for creating the Bezier path
}
}
同じ結果が得られます...
I really recommend looking at the following materials. They are what finally made Bézier paths understandable for me. (And taught me how to pronounce it: /ˈbɛ zi eɪ/.)
次のようにCAShapeLayer
を使用すると簡単です。
CAShapeLayer *shapeView = [[CAShapeLayer alloc] init];
path
を設定します:
[shapeView setPath:[self createPath].CGPath];
最後に追加します:
[[self.view layer] addSublayer:shapeView];
これを行うには、CAShapeLayer
を使用できます。
このような...
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [self createPath].CGPath;
shapeLayer.strokeColor = [UIColor redColor].CGColor; //etc...
shapeLayer.lineWidth = 2.0; //etc...
shapeLayer.position = CGPointMake(100, 100); //etc...
[self.layer addSublayer:shapeLayer];
これにより、drawRect
をオーバーライドすることなく、パスが追加および描画されます。
希望することを達成する方法は複数あります。私が最も見たものは:drawRectをオーバーライドし、シェイプを CAShapeLayer に描画し、それをサブレイヤーとしてビューに追加するか、 パスを別のコンテキストに描画する です。 、それを画像として保存し、ビューに追加します。
これらはすべて妥当な選択であり、どれが最適かは、シェイプを継続的に追加するかどうか、呼び出される頻度など、他の多くの要因に依存します。
他のポスターが指摘したように、シェイプレイヤーを使用することは良い方法です。
シェイプレイヤーaはdrawRectをオーバーライドするよりもパフォーマンスが向上する可能性があります。
自分でパスを描画する場合は、はい、カスタムビュークラスのdrawRectをオーバーライドする必要があります。
はい、何かを描画する場合はdrawrectをオーバーライドする必要があります。UIBezierPathの作成はどこでもできますが、何かを描画するにはdrawrect
メソッド内で行う必要があります
UIViewのサブクラスでdrawRectをオーバーライドする場合は、setNeedsDisplay
を呼び出す必要があります。UIViewは、ライン、イメージ、長方形など、画面上に何かを描画するカスタムビューです。