欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS绘图总结

程序员文章站 2023-01-22 19:50:47
前言 开发中有项目用到ios绘图,去年一直很忙,没抽出时间来总结,现在算是对去年项目里绘图的一个总结,效果图 一、画圆的几种方式 前言 ios支持两套图形api族:core graphics...

前言

开发中有项目用到ios绘图,去年一直很忙,没抽出时间来总结,现在算是对去年项目里绘图的一个总结,效果图
iOS绘图总结
iOS绘图总结
iOS绘图总结
iOS绘图总结

一、画圆的几种方式

前言

ios支持两套图形api族:core graphics/quartz 2d 和opengl es。opengl es是跨平台的图形api,属于opengl的一个简化版本。quartz 2d是苹果公司开发的一套api,它是core graphics framework的一部分。需要注意的是:opengl es是应用程序接口,该接口描述了方法、结构、函数应具有的行为以及应该如何被使用的语义。也就是说它只定义了一套规范,具体的实现由设备制造商根据规范去做。而往往很多人对接口和实现存在误解。举一个不恰当的比喻:上发条的时钟和装电池的时钟都有相同的可视行为,但两者的内部实现截然不同。因为制造商可以*的实现open gl es,所以不同实现的opengl es也存在着巨大的性能差异。 ios系统自身提供了两套绘图的框架,即uibezierpath 和 core graphics。而前者所属uikit,其实是对core graphics框架关于path的进一步封装,所以使用起来比较简单。但是毕竟core graphics更接近底层,所以它更加强大。

core graphics

core graphics api所有的操作都在一个上下文中进行。所以在绘图之前需要获取该上下文并传入执行渲染的函数中。如果你正在渲染一副在内存中的图片,此时就需要传入图片所属的上下文。获得一个图形上下文是我们完成绘图任务的第一步,你可以将图形上下文理解为一块画布。如果你没有得到这块画布,那么你就无法完成任何绘图操作。当然,有许多方式获得一个图形上下文,这里我介绍两种最为常用的获取方法。

myview1

- (void) drawrect: (cgrect) rect {
    uibezierpath* p = [uibezierpath bezierpathwithovalinrect:cgrectmake(0,0,100,100)];
    [[uicolor bluecolor] setfill];
    [p fill];
}

myview2

- (void) drawrect: (cgrect) rect {
    cgcontextref con = uigraphicsgetcurrentcontext();
    cgcontextaddellipseinrect(con, cgrectmake(0,0,100,100));
    cgcontextsetfillcolorwithcolor(con, [uicolor bluecolor].cgcolor);
    cgcontextfillpath(con);
}

在uiview子类的drawlayer:incontext:方法中实现绘图任务。drawlayer:incontext:方法是一个绘制图层内容的代理方法。为了能够调用drawlayer:incontext:方法,我们需要设定图层的代理对象。但要注意,不应该将uiview对象设置为显示层的委托对象,这是因为uiview对象已经是隐式层的代理对象,再将它设置为另一个层的委托对象就会出问题。轻量级的做法是:编写负责绘图形的代理类

myview3

- (void)drawlayer:(calayer*)lay incontext:(cgcontextref)con {
    uigraphicspushcontext(con);
    uibezierpath* p = [uibezierpath bezierpathwithovalinrect:cgrectmake(0,0,100,100)];
    [[uicolor orangecolor] setfill];
    [p fill];
    uigraphicspopcontext();
}

myview4

- (void)drawlayer:(calayer*)lay incontext:(cgcontextref)con {
    cgcontextaddellipseinrect(con, cgrectmake(0,0,100,100));
    cgcontextsetfillcolorwithcolor(con, [uicolor orangecolor].cgcolor);
    cgcontextfillpath(con);
}

创建一个图片类型的上下文。调用uigraphicsbeginimagecontextwithoptions函数就可获得用来处理图片的图形上下文。利用该上下文,你就可以在其上进行绘图,并生成图片。调用uigraphicsgetimagefromcurrentimagecontext函数可从当前上下文中获取一个uiimage对象。记住在你所有的绘图操作后别忘了调用uigraphicsendimagecontext函数关闭图形上下文。

myimageview1

- (void) awakefromnib {
    [super awakefromnib];
    uigraphicsbeginimagecontextwithoptions(cgsizemake(100,100), no, 0);
    cgcontextref con = uigraphicsgetcurrentcontext();
    cgcontextaddellipseinrect(con, cgrectmake(0,0,100,100));
    cgcontextsetfillcolorwithcolor(con, [uicolor yellowcolor].cgcolor);
    cgcontextfillpath(con);
    uiimage* im = uigraphicsgetimagefromcurrentimagecontext();
    uigraphicsendimagecontext();
    self.image = im;
}

myimageview2

- (void) awakefromnib {
    [super awakefromnib];
    uigraphicsbeginimagecontextwithoptions(cgsizemake(100,100), no, 0);
    uibezierpath* p = [uibezierpath bezierpathwithovalinrect:cgrectmake(0,0,100,100)];
    [[uicolor yellowcolor] setfill];
    [p fill];
    uiimage* im = uigraphicsgetimagefromcurrentimagecontext();
    uigraphicsendimagecontext();
    self.image = im;
}

iOS绘图总结

iOS绘图总结

绘图的步骤总结:

1、 获取上下文 2、 创建路径(描述路径) 3、把路径添加到上下文 4、 渲染上下文

关于drawrect方法

1、通常在drawrect里面绘图,只有在这个方法里面才能获取到跟 view的layer相关联的图形上下文

2、drawrect在以下情况下会被调用:

1、如果在uiview初始化时没有设置rect大小,将直接导致drawrect不被自动调用。drawrect调用是在controller->loadview, controller->viewdidload 两方法之后掉用的.所以不用担心在控制器中,这些view的drawrect就开始画了.这样可以在控制器中设置一些值给view(如果这些view draw的时候需要用到某些变量值).

2、该方法在调用sizetofit后被调用,所以可以先调用sizetofit计算出size。然后系统自动调用drawrect: 方法。

3、通过设置contentmode属性值为uiviewcontentmoderedraw。那么将在每次设置或更改frame的时候自动调用drawrect:。

4、直接调用setneedsdisplay,或者setneedsdisplayinrect:触发drawrect:,但是有个前提条件是rect不能为0。
以上1,2推荐;而3,4不提倡

3、drawrect方法使用注意点:

1、若使用uiview绘图,只能在drawrect:方法中获取相应的contextref并绘图。如果在其他方法中获取将获取到一个invalidate的ref并且不能用于画图。drawrect:方法不能手动显示调用,必须通过调用setneedsdisplay 或者 setneedsdisplayinrect,让系统自动调该方法。 2、若使用calayer绘图,只能在drawincontext: 中(类似于drawrect)绘制,或者在delegate中的相应方法绘制。同样也是调用setneeddisplay等间接调用以上方法 3、若要实时画图,不能使用gesturerecognizer,只能使用touchbegan等方法来掉用setneedsdisplay实时刷新屏幕