NSBezierPath 赛贝尔曲线画聊天泡泡

来源:互联网 发布:海量数据上市 编辑:程序博客网 时间:2024/05/01 07:34

最近在搞一个MAC上的聊天气泡,一开始想着直接用一个小的图片进行拉伸,完事。但经拉伸后随着窗体的大小变化,绘制的比较卡,因此研究了一下图形处理。最后决定绘制一个泡泡。先上图看效果。觉得效果可以的,往下看思路,觉得效果差的,请走过。谢谢。



实现思路很简单,其实就是画个矩形,在矩形圆角的地方画出尖角。刚开始的想法是先画一个圆角矩形,再画一个三角形,然后是三角形和圆角矩形相交部分进行滤去,但没有实现,真可惜。。。。无意间,看到NSBezierPath 路径曲线,这个可以让字体或图形按该曲线进行绘制,呵呵,哪么自然的画东东就变得更简单了。起笔前需要注意几点。

1。绘制的起点。

2。绘制开始后的矢量点,即A到B,B到C,C到D,D到A这样一个闭合过程,切不可A到B,C到B,D到C这样(不是不可以,最好不要这样,这样会打乱你绘图的思路)

3。当绘到角度时,一定要确定在角度坐标系中起角和终角之间的关系,如顺序针为正,逆时针为负,这个一定要弄清楚,Mac和iOS的原点坐标不一样。

好吧,不哆嗦,绘泡泡。。。。。。


第一步:

角度坐标系的确定:

如图:


使用函数appendBezierPathWithArcWithCenter,从0到到60度的孤线,(四种情况)

a.如果是画出的图是一小段孤线,且在第一象限,说明角度逆时针偏向是正偏角,注此时画笔的绘制矢量方向也正好是逆时针方向,这对于你第二笔的连结点很重要。

b.如果是画出的图是一小段孤线,且在第四象限,说明角度顺时针偏向是正偏角,此时画笔的绘制矢量方向也正好是顺时针方向。

c.如果是画出的图是一大段孤线,即经过了第一,第二,第三,到第四象限里的60度,说明角度顺时针偏向是正偏角,此时画笔的绘制矢量方向为逆时针方向,两者相反。

d.如果是画出的图是一大段孤线,即经过了第四,第三,第二,到第一象限里的60度,说明角度逆时针偏向是正偏角,此时画笔的绘制矢量方向为顺时针方向。

                [bezierPath appendBezierPathWithArcWithCenter:leftBottomCenterradius:radius

                                                   startAngle:0

                                                     endAngle:60

                                                    clockwise:YES];


好第一步确定了偏角方向和画笔的矢量方向哪么就可以进行定制绘制泡泡的起始点了。

第二步,寻找起始点,我这里是从小尖角进行作为起始点,在绘制初,要确定你画的小尖角是在左上,右上,右下,左下,的那一个。这里我把四个都给大家介绍一下。

上图。


以左上角为例作讲解,要在圆角处挖出一个小洞来画小尖角,将一个90度解,分为定角和动角,所为的定角,即角度定好之后就不会进行偏移,对于动角,当我们绘制出来时如果觉得缺口角度太小,不好看,可以调节一下动角,以把缺口扩大。我这里的左上角里定角为A点到ltX这个点的40度为不动角,从A点向B点方向的为动角(左上角为例)。

把开口的角度定好之后,就来算A,B的坐标相对位置,这个不难吧,用三角函数,很容易求出来,如下:

    CGFloat Ax = radius * sin(baseAngle*M_PI/180);

    CGFloat Ay = radius * cos(baseAngle*M_PI/180);

    CGFloat Bx = radius * cos((90 - baseAngle - angle)*M_PI/180);

    CGFloat By = radius * sin((90 - baseAngle - angle)*M_PI/180);


其中baseAngle为定角 40度,angle为偏角10度。


好了,A,B点的坐标有了,哪么起始点就选A,B的交点作为起始点。

各个点的坐标图:(打红色斜线的为最终的文字区域)


第三步,开始会制了。(以尖角在左上角为例)

从第一步中,我们确定了画笔绘制矢量方向。(我的为顺时针方向)。

从第二步中,我们确定了起点。好,哪还等什么呢,画呗。

a.   [bezierPath moveToPoint:startpoint] ; //将画笔移到起点上。

b. 因画笔的绘制方向为顺时针方向,所以从起点绘一条直线到A点。

[bezierPath lineToPoint:Apoint];

c. 此时应该画一部分角度了,即定角的40度孤线。

[bezierPath appendBezierPathWithArcWithCenter:leftTopCenterradius:radius

                                                   startAngle:(90+baseAngle)   //我的为逆时针方向偏角为正,即0度角到A点的偏角为90+40 = 130度。

                                                     endAngle:90     //终点角

                                                    clockwise:YES];

此方法,即表示从starAngle起始角,到终点角endAngle绘制一段孤线。

d.此时可能有读者认为应该画一条直线了,即ltX到rtX,?真的吗?非也,这里这条我们可以不用绘,利用NSBezierPath 路径曲线 的闭合曲线原理,第二根线的起点与第一根线的终点进行连结。利用这个,我们只需要绘一个右上角即可,起点为rtX,终点角为rtY.即可。

[bezierPath appendBezierPathWithArcWithCenter:rightTopCenter radius:radius

                                       startAngle:90

                                         endAngle:0

                                        clockwise:YES];

同理的,再画右下角,其后画左下角。

e.此时又是一个关键了。还有左上的一小部份孤线到B点。同样的道里绘部分角。

[bezierPath appendBezierPathWithArcWithCenter:leftTopCenterradius:radius

                                                   startAngle:180

                                                     endAngle:(90+baseAngle+angle)

                                                    clockwise:YES];


OK ,此时绘到B点就OK了,不再再从B点绘一条直线到起点啦,因为曲线闭全原理,会自会从B点绘一条直线到起点的。


根据上面的原理,可以会出各种你想要的泡泡咯。

另附上我的源码程序,连接:http://download.csdn.net/detail/fengsh998/6874241




1 0
原创粉丝点击