UIBezierPath をコード生成された UIView 上に描画する。
質問
私は
UIView
が実行時にコードで追加されます。
を描画したい。
UIBezierPath
を描画したいのですが、この場合は
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
}
注:上記のコードのいくつかは、1つのコマンドで線と弧を追加することで削減できます(弧は暗黙のうちに始点を持つため)。以下参照 を参照してください。 を参照してください。
パスを描く
パスの描画は、レイヤー内または
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
}
}
そして、ビューコントローラーに以下のようなビューを作成します。
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 本当に 以下の資料を見ることをお勧めします。これらの資料によって、私はようやくBézier pathsを理解できるようになりました。(そして /ˈ bɛ zi e↪Ll_26A/ という発音の仕方も教えてくれました)。
- ベジエパスのように考える (この著者のものはすべて良く、上の例のインスピレーションもここから得たものです)
- 数学のコーディング 第19話「ベジェ曲線 (楽しいし、視覚的な図解も良い)
- ベジェ曲線 (グラフィック アプリケーションでの使用方法)
- ベジェ曲線 (数学的な公式がどのように導き出されるかの良い説明)
関連
-
[解決済み] Xcodeにおけるバージョンとビルドの比較
-
[解決済み] UIViewに角丸をつける
-
[解決済み] UINavigationBarの1px下の行を非表示にする方法
-
[解決済み] UIButtonのタイトルを左揃えにするにはどうしたらよいですか?
-
[解決済み] UITextFieldの最大文字数を設定します。
-
[解決済み] SwiftでURLから画像を読み込む/ダウンロードする
-
[解決済み] UILabelで複数行のテキストを表示する
-
[解決済み] インポート vs #インポート - iOS 7
-
[解決済み] UITableView - トップにスクロールする
-
[解決済み] 円形のカスタムUIViewの描き方 - iPhoneアプリ
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
IOS8 Development Guide Error Thread 1: signal SIGABRT
-
[解決済み] UITextViewのプレースホルダー
-
[解決済み] App Storeのアプリと連動させる方法
-
[解決済み] UIViewに角丸をつける
-
[解決済み] iOS - UITextFieldの外側をタッチするとキーボードが外れる。
-
[解決済み] アプリのプレビュー用にiOSシミュレータのビデオをキャプチャー
-
[解決済み] CocoaPodsの最新バージョンにアップデートしますか?
-
[解決済み] UILabelで複数行のテキストを表示する
-
[解決済み] iOSで現在のデバイスの言語を取得するには?
-
[解決済み] UILabelの周りにボーダーを描画するには?