冥王生活

您现在的位置是:首页 > 科技生活 > 正文

科技生活

ios为什么需要绘图(ios图画)

admin2022-11-27科技生活102

iOS - Core Graphics

*Core Image:给图片提供各种滤镜处理,比如高斯模糊、锐化等

iOS在运行循环(run loop)中整合所有的绘图请求,并一次将它们绘制出来。

不能在主线程中进行复杂的操作,否则会造成主线程的卡顿。

不能在主线程之外的主视图上下文中绘制,只要不是在主视图上下文中绘制,一些UIKit方法是可以在后台线程中使用的。比如可以在任意线程上使用CGBitmapCreateContext创建CGBitmapContext对象并在里面绘图。

调用UIView中的drawRect方法。如果一个视图调用setNeedsDisplay方法,它就被标记为重新绘制,并且会在下一次绘图周期中重新绘制,也就是会自动调用drawRect方法。

调用UIView中的layoutSubviews方法。如果视图中的子视图布局发生变化,需要重新排列,UIKit会自动调用setNeedsLayout方法,也就是对于发生变化的视图逐层次调用layoutSubviews方法。比如frame发生变化、滚动视图等。

你不应该手动调用drawRect:方法!如果你想调用drawRect:方法更新视图,只需发送setNeedsDisplay方法。这将使得drawRect:方法会在下一个适当的时间调用。当然,不要覆盖drawRect:方法除非你知道这样做绝对合法。比方说,在UIImageView子类中覆盖drawRect:方法是不合法的,你将得不到你绘制的图形。

Core Graphics API所有的操作都在上下文中进行,获得一个图形上下文是我们完成绘图任务的第一步,你可以将图形上下文理解为一块画布

像UIImage、NSString(绘制文本)、UIBezierPath(绘制形状)、UIColor都知道如何绘制自己。这些类提供了功能有限但使用方便的方法来让我们完成绘图任务。一般情况下,UIKit就是我们所需要的。

使用UiKit,你只能在当前上下文中绘图,所以如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect:方法中,你就可以直接使用UIKit提供的方法进行绘图。如果你持有一个context:参数,那么使用UIKit提供的方法之前,必须将该上下文参数转化为当前上下文。幸运的是,调用UIGraphicsPushContext 函数可以方便的将context:参数转化为当前上下文,记住最后别忘了调用UIGraphicsPopContext函数恢复上下文环境。

这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。

使用Core Graphics之前需要指定一个用于绘图的图形上下文(CGContextRef),这个图形上下文会在每个绘图函数中都会被用到。如果你持有一个图形上下文context:参数,那么你等同于有了一个图形上下文,这个上下文也许就是你需要用来绘图的那个。如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect:方法中,并没有引用一个上下文。为了使用Core Graphics,你可以调用UIGraphicsGetCurrentContext函数获得当前的图形上下文。

视图上有三个比较容易混淆的属性:alpha(透明)、opaque(不透明)和hidden(隐藏)。下面就进行一下深入的区分。

alpha属性决定了视图会通过像素显示多少信息。alpha为1表示所有的视图信息都在像素上表现出来,而alpha为0表示没有视图信息能在像素上表示出来。

opaque,将视图标记为opaque,便是向绘图系统许诺即将绘制的每一个像素都要使用全不透明的颜色,这便允许绘图系统忽略被覆盖在下面的视图,这样可以改善性能,尤其是在进行变形的时候。与opaque紧密相关的是clearsContextBeforeDrawing。它的默认值是YES,会在调用drawRect之前将上下问设置为透明黑底。这样会避免视图中产生的任何垃圾数据。

hidden为YES的话,表示视图根本不会被绘制。

隐藏和透明视图不接受触摸事件,如果想创建一个透明视图并且接受触摸事件,可以这样来进行设置,设置它的alpha为1、opaque为NO且backgroundColor为你活[UIColor clearColor],来接手触摸事件。

iOS drawRect的作用和调用机制

一、重绘机制

iOS的绘图操作是在UIView类的drawRect方法中完成的,所以如果我们要想在一个UIView中绘图,需要写一个扩展UIView 的类,并重写drawRect方法,在这里进行绘图操作,程序会自动调用此方法进行绘图。

重绘操作仍然在drawRect方法中完成,但是苹果不建议直接调用drawRect方法,当然如果你强直直接调用此方法,当然是没有效果的。苹果要求我们调用UIView类中的setNeedsDisplay方法,则程序会自动调用drawRect方法进行重绘。(调用setNeedsDisplay会自动调用drawRect)。

在UIView中,重写drawRect: (CGRect) aRect方法,可以自己定义想要画的图案.且此方法一般情况下只会画一次.也就是说这个drawRect方法一般情况下只会被掉用一次. 当某些情况下想要手动重画这个View,只需要掉用[self setNeedsDisplay]方法即可.

二、方法定义

①、- (void)drawRect:(CGRect)rect;

重写此方法,执行重绘任务

②、- (void)setNeedsDisplay;

标记为需要重绘,异步调用drawRect

③、- (void)setNeedsDisplayInRect:(CGRect)rect;

标记为需要局部重绘

三、drawRect调用机制

drawRect调用是在Controller-loadView,,Controller-viewDidLoad 两方法之后调用的。所以不用担心在控制器中,这些View的drawRect就开始画了。这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量值).

1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。

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

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

4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0.

以上1,2推荐;而3,4不提倡

四、绘图

1、若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或者 setNeedsDisplayInRect ,让系统自动调该方法。

2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法。

3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

五、比较

layoutSubviews对subviews重新布局;

layoutSubviews方法调用先于drawRect;

setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews;

layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的

layoutIfNeeded遍历的不是superview链,应该是subviews链

drawRect是对receiver的重绘,能获得context;

setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘。

为什么绘图一般都用APPLE电脑??

1、相同配置下

苹果对图像协同处理更快,这是苹果整机本身设计的优势

2、苹果显示器色彩还原性更好,所以常用于平面设计

IOS 学习之绘图( Core Graphics 教学)

IOS中绘图的三种方式

定义: Core Graphics 是一套基于C语言的API框架.使用 Quartz绘图引擎.

基本概念: 图形上下文 CGContentRef

考虑到效率方面上的问题,通常我们不会创建。直接获取

通过

获取图形上下文

默认情况下返回值为 nil.在调用这个方法之前调用

方法,视图将创建一个绘图上下文,并且设置为 the current context(当前上下文,也就是绘图图层栈栈顶的上下文).这个上下文context只会在 drawRect: 方法中存在.一旦调用此方法调用完成,这个上下文 context 将会被销毁.

如果你不是使用UIView去绘制,这时候你需要手动往栈顶入一个。使用下面的方法

这个方法可以在app中的任何线程中调用.

CGPath 也就是路径信息。CGPath可以确定 绘制边框的各种属性(颜色 粗细 拐点),边框内部区域的绘图属性, 绘制边框还是绘制边框内部

创建路径

在绘制路径时

需要指定绘制路径时模式

CGAffineTransform 是一个结构体

系统已经帮我封装好了一下方法

用于绘制虚线

IOS基础视图:绘图

位图( Bitmap ),又称点阵图,是使用像素阵列来表示的图像。位图的像素都分配有特定的位置和颜色值。每个像素的颜色信息由 RGB 组合或者灰度值表示。根据位深度可将位图分为1、4、8、16、24及32位图像等。每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就越逼真,相应的数据量越大。例如,位深度为 1 的像素位图只有两个可能的值(黑色和白色),所以又称为二值位图。位深度为 8 的图像有 2⁸(即 256)个可能的值。位深度为 8 的灰度模式图像有 256 个可能的灰色值。 RGB 图像由三个颜色通道组成。8 位通道的 RGB 图像中的每个通道有 256 个可能的值,这意味着该图像有 1600 万个以上可能的颜色值。有时将带有 8 位通道 (bpc) 的 RGB 图像称作 24 位图像。通常将使用24位 RGB 组合数据位表示的的位图称为真彩色位图。

由上面的描述可知,我们可以将 bitmap 理解为一个点阵图或者是一个数组,其中的每个元素都是一个像素信息,假设对于一个32位 RGBA 图像来说,则每个元素包含着三个颜色组件 (R,G,B) 和一个 Alpha 组件,每一个组件占8位 (8bite = 1byte = 32 / 4) 。这些像素集合起来就可以表示出一张图片。

Bitmap 的数据由 CGImageRef 封装。由以下几个函数可以创建 CGImageRef 对象。

如果要使用 bitmap 对图片进行各种处理,则需要先创建位图上下文。先看一下初始化方法的一个例子。

它是高级别的图形接口,它的API都是基于 Objective-C 的。它能够访问绘图、动画、字体、图片等内容。 UIkit 中坐标系的原点在左上角,而 Quartz 2D 的坐标系的原点在左下角。

它是一个二维(二维即平面)绘图引擎(封装的一套用于绘图的函数库),同时支持iOS和Mac系统(可以跨平台开发)。 API (应用程序界面)是纯C语言的,来自于 Core Graphics 框架,其数据类型和函数基本都以CG作为前缀。

它是用来设置当前的 layer 在父控件当中的位置的,默认以父控件左上角的(0.0)点为它的坐标原点。

它决点 CALayer 身上哪一个点会在 position 属性所指的位置。 anchorPoint 是以当前的 layer 左上角为原点(0.0),取值范围是0~1,默认在中间也就是(0.5,0.5)的位置。

调用会重新绘制整个视图,此时系统会自动帮你调用 drawRect 方法。

重新绘制视图的部分区域。最好不要绘制视图的全部,以减少绘制带来开销。

标记为需要重新布局,会异步调用 layoutIfNeeded 刷新布局。不会立即刷新,而是在下一轮 runloop 结束前刷新,对于这一轮 runloop 之内的所有布局和UI上的更新只会刷新一次。

修改了当前视图的 size 、设置了不同的 frame 或者调用了 addsubViews ,都是会被系统自动给你标记为 setNeedsLayout 的,然后调用 layoutSubviews 进行重新布局。

如果发现有需要刷新的标记,立即调用 layoutSubviews 进行布局。如果想在当前 runloop 中立即刷新,调用顺序应该是:

将继承于 UIView 的子类进行布局更新来刷新视图。如果某个视图自身的 bounds 或者子视图的 bounds 发生改变,那么这个方法会在当前 runloop 结束的时候被调用。为什么不是立即调用呢?因为渲染毕竟比较消耗性能,特别是视图层级复杂的时候。在这种机制下任何UI控件布局上的变动不会立即生效,而是每次间隔一个周期,所有UI控件在布局上的变动统一生效再在视图上一起更新,苹果通过这种高性能的机制保障了视图渲染的流畅性。

runloop 的 observer 回调= CoreAnimation 渲染引擎一次事务的提交= CoreAnimation 递归查询图层是否有布局上的更新= CALayer layoutSublayers = UIView layoutSubviews 。从这里调用的流程也可以看出 UIView 其实就是相当于 CALayer 的代理。

用四种方法的目的是说明绘制图形有很多种方法。绘制图形实际上就是设置 path ,底层的用的都是 CGMutablePathRef 。使用贝塞尔曲线画图的好处在于,每一个贝塞尔底层都有一个图形上下文,如果是用 CGContextMoveToPoint 画图,实际上就是一个图形上下文,不好去控制,所以建议多条线可以使用贝塞尔曲线。不推荐使用第4种方式,两个东西杂糅,不太好。

实现图片的水印、裁剪、截屏、压缩等效果,这里以压缩图片为例,其余步骤类似。

CAShapeLayer 是 CALayer 的子类,多用于处理复杂的边缘涂层和边缘动画,虽然该对象也有 frame 属性,但其

iOS中几种绘图的方式

第一种绘图形式:在UIView的子类方法drawRect:中绘制一个蓝色圆,使用UIKit在Cocoa为我们提供的当前上下文中完成绘图任务。

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~