Bezelボタンを作る[03]矩形の内側に影を落とす

2010年6月17日木曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: Bezelボタンを作る[02]影を描く

さて今回はいよいよ Bezel表現を完成させる。


矩形の内側に影を落とす


[サンプル]

矩形の内側に影を落とす、と書いたが何の影を落とすのか?矩形の左上に影ができるのだから...

こんな中を抜いた図形が作って描画すれば矩形の内側に影ができるだろう。
影ができればこの図形自体は不要なので(矩形の内側に)クリッピングして隠してしまえば良い。

コードはこんな感じ。
- (void)drawRect:(CGRect)rect {

 CGRect frame = CGRectInset([self bounds], INSET_SIZE, INSET_SIZE);
 CGContextRef context = UIGraphicsGetCurrentContext();

 CGContextSaveGState(context);

 // [1] clipping
 [self addRoundRectPath:context rect:frame];
 CGContextClip(context);

 // [2] fill background in round rect
 [[UIColor whiteColor] setFill];
 CGContextFillRect(context, frame);
 
 // [3] create a shape for shadow
 CGContextAddRect(context, [self bounds]);
 [self addRoundRectPath:context rect:frame];
 [[UIColor whiteColor] setFill];

 // [4] add shadow
 CGContextSetShadow(context, CGSizeMake(SHADOW_SIZE, -SHADOW_SIZE), SHADOW_BLUR);
 
 // [5] draw the shape
 CGContextEOFillPath(context);
}
実行するとこうなる。

コードの [3]と[5]の部分が影を作るための中抜き図形を描いている部分。CGContextEOFillPath() は、それまでに追加されたパスで重なる部分を描画しないという性質を持っているのでこれを使っている。[3]の部分で最初に外側の四角を描き、次にその内側に角丸矩形を描いているので、CGContextEOFillPath() を使うと内側の角丸矩形を抜いた形で塗りつぶされる。これはなかなか便利だ。
またこのままだとこの図形が描画されてしまうので、最初の[1]でクリッピングしておく。


なお若干縁の部分が白くなったりしているので、これを隠すために縁に線を引く。
[self addRoundRectPath:context rect:frame];
 [[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1.0f] setStroke];
 CGContextSetLineWidth(context, 0.5f);
 CGContextStrokePath(context);

これでできあがり。

Responses

  1. jarinosuke says:
    2011年8月25日 22:17

    いつもこのBlogを参考にさせて頂いています。
    ありがとうございます。

    [4]add shadow の処理のところで、 SHADOW_SIZE という定数をもとに CGContextSetShadow を実行しているのですが、引数の CGSize に

    CGSizeMake(SHADOW_SIZE, -SHADOW_SIZE)

    を与えてしまうと枠内にかかる影は左下に来てしまうと思います。両方とも正の値が正しいように思うのですが、何かのバージョンアップで座標系の変更などがあったりしたのかもしれないです…。

    iOS 4.3 の環境では
    CGSizeMake(SHADOW_SIZE, SHADOW_SIZE)
    を代入する事で左上に影を付ける事ができました。

  2. jarinosuke says:
    2011年8月25日 22:17

    いつもこのBlogを参考にさせて頂いています。
    ありがとうございます。

    [4]add shadow の処理のところで、 SHADOW_SIZE という定数をもとに CGContextSetShadow を実行しているのですが、引数の CGSize に

    CGSizeMake(SHADOW_SIZE, -SHADOW_SIZE)

    を与えてしまうと枠内にかかる影は左下に来てしまうと思います。両方とも正の値が正しいように思うのですが、何かのバージョンアップで座標系の変更などがあったりしたのかもしれないです…。

    iOS 4.3 の環境では
    CGSizeMake(SHADOW_SIZE, SHADOW_SIZE)
    を代入する事で左上に影を付ける事ができました。

  3. xcatsan says:
    2011年9月1日 0:00

    jarinosuke さん、こんばんは。
    なるほど。

    多分 iOS 3→4 になった時に座標系がひっくり返った件かもしれません。
    http://cocoadays.blogspot.com/2010/06/iphone3-4.html

    昨年のことなのでうる覚えなのですが、上記コードは 3.1系で確認をとっていたので、その場合は 4系だと指摘の通り逆になりますね。しかしバージョンアップで座標系が逆になるとは困ったものです。。

    情報ありがとうございました。

  4. xcatsan says:
    2011年9月1日 0:00

    jarinosuke さん、こんばんは。
    なるほど。

    多分 iOS 3→4 になった時に座標系がひっくり返った件かもしれません。
    http://cocoadays.blogspot.com/2010/06/iphone3-4.html

    昨年のことなのでうる覚えなのですが、上記コードは 3.1系で確認をとっていたので、その場合は 4系だと指摘の通り逆になりますね。しかしバージョンアップで座標系が逆になるとは困ったものです。。

    情報ありがとうございました。

Leave a Response

人気の投稿(過去 30日間)