投稿

ラベル(iOSアプリ開発(Graphics))が付いた投稿を表示しています

SwiftでのdrawRect()

UIViewのdrawRec()メソッド内で線を描いたり円を描いたりするやり方について。 CGContextなんとかという関数を用いる方法が広く紹介されているが、実はUIBezierPathというクラスもある。これはCGContextなんとかを機能的にラッパーしたクラス。Appleの資料によるとこちらの方がおすすめらしいのでこれを中心に紹介していく。Bezierというとややこしい数式を用いた描画というイメージがあって名前で少し敬遠してしまうが、線を引いたり丸を描いたりといった単純な描画でもこのクラスをメインにするといい。UIPathのようなシンプルな名前にしておけばもっと人気(?)が出たかもしれない。 描くときの大まかな流れは 1 線の太さや使用する色を指定 2 パス(線要素)を必要なだけ足していく。 3 描画指令を出す となる。 UIBezierPathを使った描画 //色の設定 UIColor.redColor().setFill() UIColor.blueColor().setStroke() UIColorに色設定メソッドがあります。UIBezierPathというのはPathに関するものなので色は専門外なんでしょう。 でここからUIBezierPathのメソッドです。 //空インスタンス作成 let line = UIBezierPath() //線の太さ line.lineWidth = 2 //開始点 line.moveToPoint(CGPointMake(10, 10)) //追加点 line.addLineToPoint(CGPointMake(20,20)) //パスを描く line.stroke() //パスを閉じる line.closePath() //円や楕円 let daen = UIBezierPath(ovalInRect: CGRectMake(100, 100, 100, 100)) //四角 let shikaku = UIBezierPath(rect: CGRectMake(100, 100, 100, 100)) //中を塗る daen.fill() shikaku.fill() //角が丸い四角 let kadomaruSHi...

Affine行列の適用順序

イメージ
しょっちゅう忘れてしまうので… 基本 CGではAffine行列は3x3の行列で a b 0 c d 0 tx ty 1 で表される。 この行列は元データである個々の座標に対して後ろから掛かり、適用後の座標を出す。 これは行列の中の移動を表すtx,tyの位置から明らか。 前から掛けると(行列)(縦表現座標)となり、結果は(ax+by,cx+dy,tx+ty+1)。これは求めたい結果ではない。 後ろから掛けると(横表現座標)(行列)となり、結果は(ax+cy+tx,bx+dy+ty,1)。こちらが求めたい結果。 ちなみに座標は(x,y,1)となる。最後の1は必要。 ということで 個々の座標データに行列を適用させるというのが行列の使われ方 座標に対して後ろから掛かる という前程で進める。 複数の行列の適用順序 CGAffineTransform t = CGAffineTransformIdentity; t = CGAffineTransformScale(t, 0.5, 2.0); t = CGAffineTransformTranslate(t, 100.0, 100.0); t = CGAffineTransformRotate(t, 1.0); とプログラムを書いた場合、最終的な行列tは (Rotate演算行列)(Translate演算行列)(Scale演算行列) の結果となる。 つまり、行列追加関数は既存の行列の前に新しい行列を挿入する。 これが座標に後ろから掛かるので、個々の座標データにRotate演算、Translate演算、Scale演算の順に実行されたことと同じ結果(実際には先に適用行列の積が計算されていて、その結果を座標データに適用すると思う)。この順番は関数が書かれている順番と反対。 上のはCGAffineTransformの場合だが、 drawRect内でCGContextRefに行列を与える関数 CGContextScaleCTM(context, 0.5, 2.0); CGContextTranslateCTM(context, 100,100); CGContextRotateCTM(context, 1.0); も同様の法則。 また、view.layerに与え...

clearsContextBeforeDrawing

これはdrawRect実行前に領域を塗り潰すかどうかのパラメータですが、調べれば調べるほど他にもいろいろな設定項目が出てくる、代表的な 芋づるパラメータ です。 他に出てくるパラーメタはopaque(不透明)とbackgroundColorの2つで、 clearsContextBeforeDrawingが2通り opaqueが2通り backgroundColorがnil、transparent(alphaが1未満)、opaque(alphaが1)の3通りありますので 合計12パターンの設定があります。 ややこしいですが、各パラメータの説明のまえに王道をいうと 何かの色で塗りつぶすなら、backgroundColorにベース色を指定します。 透明にしたいならview.backgroundColor = [UIColor clearColor]に指定します。 ただしパフォーマンスを上げたい場合や、仕組みが気になる場合は、各パラメータの意味を理解して対応することになります。 drawRectメソッドの内で領域をすべて塗る場合には効果があります。[UIColor clearColor]は色値とアルファ値が全部0.0のUIColorインスタンス。いわゆる透明な黒というやつである。 詳しく見ていくと backgroundColorが指定され、alphaが1.0の時 その色で塗る opaqueとclearsContextBeforeDrawingの設定による違いはない その色で塗られているので下の画像が塗られているかと前もって領域が透明な黒でクリアされているかは見た目ではわからないがリファレンスによるとクリアされているようだ。 backgroundColorが指定され、alphaが0.0<=alpha<1.0の時 その色を塗りながら下の画像を表示 opaqueとclearsContextBeforeDrawingの設定による違いはない 下の画像が塗られているのでopaqueの設定が無視されるようだ 前もって領域が透明な黒でクリアされているかは見た目からはわからないがこれもリファレンスによるとクリアされているようだ。 上で出した[UIColor clearColor]の場合、全部0.0であろうと指定されているということで、その色(というか...

CGContextDrawPathに与えるパラメータについて

イメージ
CGContextDrawPathに与える2つめの引数について調べました。 2つの角丸四角形のパスを書いてからCGContextDrawPathを実行してます。 名前に出てくるEOというのはEven-Oddの略です。Even-Oddというのは偶数・奇数のことです。重なった部分はいくつのパスが囲っているかを調べ、奇数の時は塗る、偶数の時は塗りません。 kCGPathFill 内部を塗ります。 kCGPathStroke 輪郭を書きます。 kCGPathFillStroke 内部を塗って、輪郭を書きます。 kCGPathEOFill 内部を塗るが重なった所は奇数遇数ルールに従う。 kCGPathEOFillStroke 内部を塗って、輪郭を書くが、重なった所は輪郭は書いて内部は奇数遇数ルールに従う。 (追記) SwiftではCGPathDrawingModeになりました。