现在的位置: 首页 > 综合 > 正文

iOS的绘图机制

2013年03月08日 ⁄ 综合 ⁄ 共 4251字 ⁄ 字号 评论关闭

嘿!我又回来了。(如果觉得喜欢,请关注这个微薄:http://weibo.com/javaplatform,很有用!哪里有更多的内容和资讯)

在前面我介绍了iOS的视图机制,我也提到了iOS的视图框框可以通过drawRect自己绘图,我也说过每个view的layer(CALayer)就像一个视图的投影,其实我们也可以来操作它定制一个视图,例如半透明圆角背景的视图。

要完成自己在视图上绘图,大家一定要了解一下iOS的绘图机制了。今天我试图也通俗地说一下iOS的绘图。

在iOS中绘图可以有两种方式:

1,采用iOS的核心图形库。

2,采用OpenGL ES。

这两个库的不同我简单介绍一下:

前者主要是通过核心图形库和UIKit进行封装,其更加贴近我们经常操作的视图(UIView)或者窗体(UIWindow)。例如我们前面提到的drawRect,我们只负责在drawRect里进行绘图即可,我们没有必要去关注界面的刷新频率,至于什么时候调drawRect都有iOS的视图绘制来管理。

那么OpenGL ES经常用在游戏等需要对界面进行高频刷新和自由控制。通俗理解一下就是其更加切近直接对屏幕的操控。在很多游戏编程中可能我们不需要一层一层的框框,直接在界面上绘制,并且通过多个的内存缓存绘制来让画面更加流畅。

那换句话来说,OpenGL ES完全可以作为视图机制的底层图形引擎。他们就这个关系了。

大概了解这个就行了。OpenGL和Direct X 等我们到处能看到的。我们不再累赘了,今天我们的主题主要侧重前者,并且侧重如何通过绘图机制来定制我们的视图。先来看看我们最熟悉的Windows自带画图器(我觉得它就是对原始画图工具的最直接体现):

如果你会用绘图器绘制线条,形状,文字,选择颜色,并且和可以填充,那么iOS中的绘图机制也可以做得到,只是你用程序绘制的时候,整个画图板你要装载脑子里。

那我们开始:

如果你要绘图,你最起码得有个面板吧?无论它是墙,纸还是内存,都是这样了。那在iOS绘图中是个什么呢?就是个画图板(Graphics Contexts)。所有画图板首先要规定一下了,否则,计算机的画图都是需要我们用数字告诉人家的,那坐标体系就先要明确一下了。

在iOS的2D绘图中采用的就是我们熟知的直角坐标系,即原点在左下方,右上为正轴,这里要注意的是和我们在视图(UIView)中布局的坐标系是不一样的,他的圆点在左上,右下为正轴。当我们在视图的drawRect中工作的时候拿到的画板已经是左上坐标的了,那这时候你要去把一个有自己坐标体系的内容直接绘制,就会出现坐标不一致问题,例如直接绘制图片就会倒立。(后面我们会说坐标变换的一些内容,这里不要急)。

前面我们也说了Windows画图板里面我们至少还看到个画图板,那在iOS绘图中其实我们也有个"虚拟"的画图板(Graphics Contexts),所有的绘图操作都在这个画图板里面操作。

在视图(UIView)的drawRect中操作时,其实视图引擎已经帮我们准备好了画板(记着windows画图板啊,这样我说什么你就明白了),甚至连当前线条的粗细,当前绘制的颜色等都给你传递过来了。你只需要“接”到这个画板,然后拿起各种绘图工具绘就可以了。

光说不练不行啊,我给个简单例子说明一下绘图过程:

-(void)drawRect:(CGRect)rect{

         CGContextRef ref=UIGraphicsGetCurrentContext();//拿到当前被准备好的画板。在这个画板上画就是在当前视图上画

         CGContextBeginPath(ref);//这里提到一个很重要的概念叫路径(path),其实就是告诉画板环境,我们要开始画了,你记下。

         CGContextMoveToPoint(ref,0,
0);//画线需要我解释吗?不用了吧?就是两点确定一条直线了。

         CGContextAddLineToPoint(ref,300,300);

         CGFloat redColor[4]={1.0,0,0,1.0};

         CGContextSetStrokeColor(ref, redColor);//设置了一下当前那个画笔的颜色。画笔啊!你记着我前面说的windows画图板吗?

         CGContextStrokePath(ref);//告诉画板,对我移动的路径用画笔画一下。

}

无论你画圈圈,还是画什么都少不了如下几步:

1,拿到当前面板

2,开始画声明

3,画

4,提交画

这篇文章被我罗索的太长,我再增加一篇吧。累死我了。请看 iOS的绘图机制二。

 

在iOS的绘图机制那篇文章中,我说了很多大道理,现在我觉得应该摆上台来说程序本身的主题了。当说完程序本身的主题,我再引入绘图如何去定制我们的视图(UIView),估计大家就会和我一样收获很多。

我们说过iOS的基本绘图机制用的是它的CGxxxx系列函数,CG就是Core Graphics,我叫核心图形库。那我们按照主题一个一个来聊吧(我这里提出来的主题就是苹果官方提出来的主题,我试图通俗一点介绍)。

不对,我还要介绍一些概念,否则,怕大家还是乱,一个一个来:

坐标和坐标变换:坐标我不说了,坐标变换我想说一下。在iOS应用中,把视图进行缩放、旋转等都是常见的事情。所以我们每次拿到一个画板,就不能直接在上面操作起来,说不定这个画板已经被放大了1000倍。那在数学的角度来说就是坐标变了。在直角坐标系中左边变换无非就是平移,缩放,旋转,当然你是比较“独”的人,那你可以用任何变换矩阵,总之我管不了你。但无论你怎么变,我们都能抽象成一个3X3的矩阵。(你不熟悉矩阵吗?我也不熟悉。没关系,你知道这回事就可以了,更何况一个3X3的矩阵复杂不到哪里去,至于为什么对直觉坐标系采用3X3的矩阵,你自己想去了,我怎么知道呢?)。在iOS中有个概念叫CTM(当前变换矩阵),其实它就是告诉你,你工作之前要先明白当前的坐标特点了。否则,你怎么在上面画图啊。你告诉个数字大家理解都不一样。例如第一篇文章中的图片倒立绘制问题就是这个原因了。

路径:在第一篇文章中我也提过,但还是觉得应该拿出来解释一下。其实这个东西没有什么大不了的,只是在现实中我们拿个刷子的动作是那么的自然,以至于我们忽略了它,但计算机需要把这个过程数字化,所以就提出来了这个概念。但这里我要强调的是既然是计算机,那么对路径的操作就期望比我们人更加不厌其烦,例如,我们在墙上画了很多东西,我们要察掉部分多于,那就要慢慢来,但计算机可以通过其计算能力帮你,例如它可以计算你画的路径是否闭合,不闭合可以给你补一下,然后对闭合外进行裁剪等。ok!我们在这里提到了裁剪,例如你可以贴一张图片(方方正正的),然后用一个五星形状的路径去裁剪。好玩吧?哦!这里好像把裁剪也介绍了。后面就略了。

裁剪:路径那块好像提了一下,就那么回事了。

颜色和阴影相关:大家一定不陌生透明,CMYK,RGB这些破玩艺吧。如果陌生,那我就简单说说了。从颜色开始啊。首先让我们去区分CMYK和RGB的意义不是很大,就看你获取的原始设计颜色是怎么描述了。通常情况下大家知道RGB就够了。但在很多图形软件里面还提供RGBA模式,最后面加了一个透明值。大家需要注意一下,例如css3中,在iOS中也可以加入透明值。说起透明,我们一定要明白几个层面的意思:颜色透明度;当前画板的透明度以及工作透明层(估计大家还糊里糊涂,后面我会专门用例子谈这几个东东的)。我们在说一下阴影:Shadow。阴影有什么好说的?郁闷。

底纹和循环图:这个我不用说了吧?做网页大家都做循环背景的,那么iOS的绘图机制也是支持的。我只说一下底纹吧,底纹说白了也就是一个循环绘制的机制。这块你明白我为什么把底纹和循环图放到一块了吧。至于如何循环后面我们会说。

OK!进入我们的主题(我觉得画线什么的我就不用画了,我这里主要冲着实用去,给大家一些技巧)。

1、渐变背景

先看看效果图,我们经常需要渐变背景,大家只要会绘制上面的,那就有或多好玩的。例如棱角什么的。

CGContextRef context=UIGraphicsGetCurrentContext();
    //建立一个颜色梯度对象
    CGGradientRef myGradient;
    CGColorSpaceRef myColorSpace;
    size_t locationCount = 3;
    CGFloat locationList[] = {0.0, 0.1, 1.0};
    CGFloat colorList[] = {
        1.0, 0.0, 0.5, 1.0, //red, green, blue, alpha
        1.0, 0.0, 1.0, 1.0,
        0.3, 0.5, 1.0, 1.0
    };
    myColorSpace = CGColorSpaceCreateDeviceRGB();
    myGradient = CGGradientCreateWithColorComponents(myColorSpace, colorList,
                                                    locationList, locationCount);//核心的函数就是这个,要搞清渐变一些量化的东西了。
   
    CGPoint startPoint, endPoint;
    startPoint.x = 0;
    startPoint.y = 0;
    endPoint.x = CGRectGetMaxX(self.bounds);
    endPoint.y = CGRectGetMaxY(self.bounds);
    CGContextDrawLinearGradient(context, myGradient, startPoint, endPoint,0);//这是绘制的,你可以通过裁剪来完成特定形状的过渡。
    CGColorSpaceRelease(myColorSpace);
    CGGradientRelease(myGradient);

 

http://hi.baidu.com/janins/blog/item/d9a7e422b6038f0e8b82a148.html

抱歉!评论已关闭.