LoginSignup
165
164

More than 5 years have passed since last update.

iOSで吹き出しを描こう

Last updated at Posted at 2012-08-10

完成品はこんな感じ

画像
メッセージアプリとかでよくあるやつなんだけど、画像でもいいんだけどセリフの長さによってサイズ変えたりしたいから、描いたほうが楽だなってことで簡単なんで描いちゃいましょう。

コードは主要部分はこんな感じ

//描画するぜ!
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBubblePath(context, CGRectMake(60.5, 40.5, 170, 70));
    CGContextStrokePath(context);
}

//角度→ラジアン変換
#if !defined(RADIANS)
#define RADIANS(D) (D * M_PI / 180)
#endif

//吹き出しを描く
void CGContextBubblePath(CGContextRef context, CGRect rect)
{
    CGFloat rad = 10;  //角の半径
    CGFloat qx = 10; // くちばしの長さ
    CGFloat qy = 20; // くちばしの高さ
    CGFloat cqy = 4; // 上くちばしカーブの基準点の高さ
    CGFloat lx = CGRectGetMinX(rect)+qx; //左
    CGFloat rx = CGRectGetMaxX(rect); //右
    CGFloat ty = CGRectGetMinY(rect); //上
    CGFloat by = CGRectGetMaxY(rect); //下

    CGContextBeginPath(context);

    CGContextMoveToPoint(context, lx, ty+rad); //左上
    CGContextAddArc(context, lx+rad, ty+rad, rad, RADIANS(180), RADIANS(270), 0); //左上のカーブ
    CGContextAddArc(context, rx-rad, ty+rad, rad, RADIANS(270), RADIANS(360), 0); //右上のカーブ
    CGContextAddArc(context, rx-rad, by-rad, rad, RADIANS(0), RADIANS(90), 0); //右下のカーブ
    CGContextAddArc(context, lx+rad, by-rad, rad, RADIANS(90), RADIANS(125), 0); //くちばしの付け根(下の凹み)
    CGContextAddQuadCurveToPoint(context, lx, by, lx-qx, by); //くちばしの先端
    CGContextAddQuadCurveToPoint(context, lx, by-cqy, lx, by-qy); //くちばしの付け根(上)

    CGContextClosePath(context); //左上の点まで閉じる
}

意外と短い。
でもこれで吹き出しの形が描けます。

ちょっとだけ説明。

まず、左上のカーブ。

CGContextAddArc(context, lx+rad, ty+rad, rad, RADIANS(180), RADIANS(270), 0);

点(lx+rad, ty+rad)を中心にして、半径radの円を180度から270度まで時計回りで描くよ。ってことです。
これで左上のカーブが描けます。

※ 注意
原点が左上なので、0度が右、90度が下になります。
180度から270度ってことは、左から上ってことです。

次の行で上の直線を描かずに、すぐに右上のカーブを描いてるのは勝手に間は直線で結ばれるからです。
勝手に結ばれるのが気になるなら、こんな感じで直線を描いてもいいです。

CGContextAddLineToPoint(context, rx-rad, ty);

左下のカーブは、円を下から35度だけ描いて止めてます。

次に、くちばしの先端。

CGContextAddQuadCurveToPoint(context, lx, by, lx-qx, by);

現在の点から、点(lx-qx, by)まで線を引くんだけど、点(lx, by)で線を引っ張って曲げる。ってことです。
厳密には違うかもしれないけど、まあそんなとこです。
だから、もっと強く曲げたかったら、点(lx, by)を点(lx+1, by+1)とかにしたらいいんです。

最後に、一番上。吹き出しの大きさを指定してるところ。

CGRectMake(60.5, 40.5, 170, 70)

0.5とか中途半端な座標を使ってるのは、よくあるTips。
1ptの線を描くとき座標の中心に描こうとして線がぼやっとするから。
Retinaだったら問題ないんだけどね。

はい。おわりです。
完成品では、Clipしてグラデーションで塗ったり、縁取りしたり、影つけたりしてるんだけど、
気になったらGitHubにあげてるんでみてねー。
BubbleDraw - GitHub

165
164
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
165
164