如何在ViewController中ios 调用drawrectt方法绘制视图

iOS重绘机制drawRect
iOS的绘图操作是在UIView类的drawRect方法中完成的,所以如果我们要想在一个UIView中绘图,需要写一个扩展UIView 的类,并重写drawRect方法,在这里进行绘图操作,程序会自动调用此方法进行绘图。下面先说明一下绘图,比如,你想绘制一个方块,你需要写一个类来扩展UIView并在drawRect方法中填入如下代码:- (void)drawRect:(CGRect)rect { &&&&&// Drawing code. &&&&&//获得处理的上下文 &&&&&&&CGContextRef context = UIGraphicsGetCurrentContext(); &&&&&&&//设置线条样式 &&&&&&&CGContextSetLineCap(context, kCGLineCapSquare); &&&&&&&&//设置线条粗细宽度 &&&&&&&CGContextSetLineWidth(context, 1.0); &&&&&&&&&&&&//设置颜色 &&&&&&&CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); &&&&&&&&//开始一个起始路径 &&&&&&&CGContextBeginPath(context); &&&&&&&&//起始点设置为(0,0):注意这是上下文对应区域中的相对坐标, &&&&&&&CGContextMoveToPoint(context, 0, 0); &&&&&&&&//设置下一个坐标点 &&&&&&&CGContextAddLineToPoint(context, 100, 100); &&&&&&&&//设置下一个坐标点 &&&&&&&CGContextAddLineToPoint(context, 0, 150); &&&&&&&//设置下一个坐标点 &&&&&&&CGContextAddLineToPoint(context, 50, 180); &&&&&&&//连接上面定义的坐标点 &&&&&&&CGContextStrokePath(context); &&} &再说明一下重绘,重绘操作仍然在drawRect方法中完成,但是苹果不建议直接调用drawRect方法,当然如果你强直直接调用此方法,当然是没有效果的。苹果要求我们调用UIView类中的setNeedsDisplay方法,则程序会自动调用drawRect方法进行重绘。(调用setNeedsDisplay会自动调用drawRect)在UIView中,重写drawRect: (CGRect) aRect方法,可以自己定义想要画的图案.且此方法一般情况下只会画一次.也就是说这个drawRect方法一般情况下只会被掉用一次.&当某些情况下想要手动重画这个View,只需要掉用[self setNeedsDisplay]方法即可.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实时刷新屏幕
上一篇: 原文: /jhzhu/p/3404518.html 如果你刚刚开始接触IOS编程, 刚刚接触UIKit, 肯定会被frame, bounds, center, layer.anchorPoint, layer.position这些乱七八糟得属性折腾得心烦意乱. 并且,聪明的你肯定早就发现,这些属性并不是独立的,
下一篇: 我们可以用代码编写界面,同样也可以在项目中扩展名为xib的文件中设计(图中选中的) 打开后,在Xcode的右下角有一些常用的控件 可以直接把这些控件用鼠标拖到界面里使用: 如下用了7个Label和一个Button组成的简单界面 然后编写定义这个界面内控件的类文件iPhone开发入门_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
iPhone开发入门
上传于||文档简介
&&i​P​h​o​n​e​开​发​入​门
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩17页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢Core Graphics是Cocoa和Cocoa Touch所共有的API。它允许你在画布上绘制图形对象。在此篇教程中,我们会绘制一些标准的图形,比如三角形或者圆形。教程运行在 iOS 9 和 Xcode 7 下。
打开 Xcode 并创建一个new Single View Application项目。项目名称为IOS9DrawShapesTutorial,接着填上你的Organization Name和Organization Identifier,选择 Swift 语言,确保在设备一栏只选择了 IPhone。
打开故事板,在主视图中拖入三个按钮,使他们水平对齐,并分别设置title为”Lines, Rectangle, Circle”。之后你的故事板内容应该像下面这样:
选中所有按钮,打开Attributes Inspector(属性检测器)。在View部分给从左到右的按钮添上”0,1,2”的tag。tag是我们后面才需要的,我们可以通过tag的值得知哪个按钮被按下了。
打开Assistant Editor(关联面板),并确保ViewController.swift文件是打开着的。按住 Ctrl键,把Lines按钮拖出到ViewController.swift文件中,并创建下面的Action
选中其它的按钮,按住Ctrl键并拖到ViewController类的IBAction方法里(刚刚创建的那个Action)。之后我们点击每一个按钮就会触发这里的IBAction方法。绘制的图形会呈现在一个自定义的视图中。接下来,我们为项目添加一个新文件。选中File -&New File -&iOS -&Source -&Cocoa Touch Class。类名称为”ShapeView”,确保父类为UIView。
打开ShapeView.swift文件,添加下面的属性。
var currentShapeType: Int = 0
currentShapeType属性是用于选择正确的方法画出对应的对象。接着添加初始化方法:
init(frame: CGRect, shape: Int) {
super.init(frame: frame)
self.currentShapeType = shape}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")}
当自定义视图被初始化的时候,tag的值会决定绘制的图形类型。drawRect方法会在自定义视图绘制的过程中调用。
override func drawRect(rect: CGRect) {
switch currentShapeType {
case 0: drawLines()
case 1: drawRectangle()
case 2: drawCircle()
default: print("default")
接下来,实现绘图的方法:
func drawLines() {
let ctx = UIGraphicsGetCurrentContext()
CGContextBeginPath(ctx)
CGContextMoveToPoint(ctx, 20.0, 20.0)
CGContextAddLineToPoint(ctx, 250.0, 100.0)
CGContextAddLineToPoint(ctx, 100.0, 200.0)
CGContextSetLineWidth(ctx, 5)
CGContextClosePath(ctx)
CGContextStrokePath(ctx)}
func drawRectangle() {
let center = CGPointMake(self.frame.size.width / 2.0, self.frame.size.height / 2.0)
let rectangleWidth:CGFloat = 100.0
let rectangleHeight:CGFloat = 100.0
let ctx = UIGraphicsGetCurrentContext()
CGContextAddRect(ctx, CGRectMake(center.x - (0.5 * rectangleWidth), center.y - (0.5 * rectangleHeight), rectangleWidth, rectangleHeight))
CGContextSetLineWidth(ctx, 10)
CGContextSetStrokeColorWithColor(ctx, UIColor.grayColor().CGColor)
CGContextStrokePath(ctx)
CGContextSetFillColorWithColor(ctx, UIColor.greenColor().CGColor)
CGContextAddRect(ctx, CGRectMake(center.x - (0.5 * rectangleWidth), center.y - (0.5 * rectangleHeight), rectangleWidth, rectangleHeight))
CGContextFillPath(ctx)}
func drawCircle() {
let center = CGPointMake(self.frame.size.width / 2.0, self.frame.size.height / 2.0)
let ctx = UIGraphicsGetCurrentContext()
CGContextBeginPath(ctx)
CGContextSetLineWidth(ctx, 5)
let x:CGFloat = center.x
let y:CGFloat = center.y
let radius: CGFloat = 100.0
let endAngle: CGFloat = CGFloat(2 * M_PI)
CGContextAddArc(ctx, x, y, radius, 0, endAngle, 0)
CGContextStrokePath(ctx)}
这里的Graphic Context就是你绘图的画布。如果你想在一个视图上绘图,那么view就是你的画布。这里我们需要得到一个Graphic Context的引用。
path就是一些线条,弧线和曲线的集合,你可以在当前画布使用它们来构建的复杂对象。这里我们绘制了一些线条并设置了线条的宽度为 5。
此处关闭path,并绘制图像到画布上。
CGContextAddRect方法给我们绘制了一个长方形,并且外框的颜色为灰色。
这里定义了一个相同的长方形,并填充绿色到内部。
CGContextAddArc绘制了一个圆形。
接着,在ViewController.swift文件中实现buttonPressed方法
@IBAction func buttonPressed(sender: UIButton) {
let myView = ShapeView(frame: CGRectMake(50, 200, 280, 250), shape: sender.tag)
myView.backgroundColor = UIColor.cyanColor()
view.addSubview(myView)}
编译并运行程序,点击不同的按钮来绘制不同的图形。
你可以在上下载IOS9DrawShapesTutorial的代码。
本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 。2687人阅读
cocoa SDK(139)
首先两个方法都是异步执行。layoutSubviews方便数据计算,drawRect方便视图重绘。
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews。
2、addSubview会触发layoutSubviews。
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews事件。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
7、直接调用setLayoutSubviews。
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不提倡
drawRect方法使用注意点:
1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay&或 者&setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext:&中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来调用setNeedsDisplay实时刷新屏幕
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:620667次
积分:6387
积分:6387
排名:第2704名
原创:57篇
转载:220篇
评论:59条
(3)(1)(1)(1)(1)(6)(3)(1)(9)(4)(12)(8)(26)(4)(11)(21)(21)(30)(91)(1)(2)(1)(5)(14)今天看啥 热点:
图形编程总结,ios图形编程总结
& & & &IOS实现图形编程可以使用三种API(UIKIT、Core Graphics、OpenGL ES及GLKit)。& & & &这些api包含的绘制操作都在一个图形环境中进行绘制。一个图形环境包含绘制参数和所有的绘制需要的设备特定信息,包括屏幕图形环境、offscreen 位图环境 和PDF图形环境,用来在屏幕表面、一个位图或一个pdf 文件中进行图形和图像绘制。在屏幕图形环境中进行的绘制限定于在一个UIView 类或其子类的实例中绘制,并直接在屏幕显示,在offscreen 位图 或 PDF图形环境中进行的绘制不直接在屏幕上显示。1& 、UIKIT API& & & &&UIKIT是一组Objective-C API,为线条图形、Quartz图像和颜色操作提供Objective-C 封装,并提供2D绘制、图像处理及用户接口级别的动画。& & & & UIKIT包括UIBezierPath(绘制线、角度、椭圆及其它图形)、UIImage(显示图像)、UIColor(颜色操作)、UIFont和UIScreen(提供字体和屏幕信息)等类以及在位图图形环境、PDF图形环境上进行绘制和 操作的功能等, 也提供对标准视图的支持,也提供对打印功能的支持。& & & &在UIKIT中UIView类本身在绘制时自动创建一个图形环境(对应Core Graphics层的CGContext类型)作为当前的图形绘制环境。在绘制时可以调用UIGraphicsGetCurrentContext 函数获得当前的图形环境。2 、Core Graphics 与Quartz 2D API& & & & Core Graphics是一套C-based API, 支持向量图形,线、形状、图案、路径、剃度、位图图像和pdf 内容的绘制。& & & & Quartz 2D 是Core Graphics中的2D 绘制呈现引擎。Quartz是资源和设备无关的,提供路径绘制,anti-aliased呈现,剃度填充图案,图像,透明绘制和透明层、遮蔽和阴影、颜色管理,坐标转换,字体、offscreen呈现、pdf文档创建、显示和分析等功能。& & & & Quartz 2D能够与所有的图形和动画技术(如Core Animation, OpenGL ES, 和 UIKit 等)一起使用。& & & & Quartz采用paint模式进行绘制。& & & & Quartz 中使用的图形环境也由一个类CGContext表示。& & & &在Quartz 中可以把一个图形环境作为一个绘制目标。当使用Quartz 进行绘制时,所有设备特定的特性被包含在你使用的特定类型的图形环境中,因此通过给相同的图像操作函数提供不同的图像环境你就能够画相同的图像到不同的设备上,因此做到了图像绘制的设备无关性。& & & & &Quartz 为应用提供如下几个图形环境:1)位图图形环境,用来创建一个位图。使用函数CGBitmapContextCreate来创建。2)PDF图形环境,用来创建一个pdf文件。Quartz 2D API提供了两个函数来创建一个PDF图形环境:CGPDFContextCreateWithURL,带有一个作为pdf 输出的位置的Core Foundation URL来创建一个pdf 图形环境。CGPDFContextCreate, 当想PDF 输出到一个data consumer时使用该函数。3) 窗口图形环境,用来在一个窗口上进行绘制。4) 层环境(CGLayer) ,是一个与另一个图形环境关联的offscreen绘制目标,使用层环境的目的是为了优化绘制层到创建它的图形环境的性能。层环境能够比位图图形环境提供更好的offscreen绘制性能。Quartz提供的主要类包括:CGContext:表示一个图形环境;CGPath:使用向量图形来创建路径,并能够填充和stroke;CGImage:用来表示位图;CGLayer:用来表示一个能够用于重复绘制和offscreen绘制的绘制层;CGPattern:用来表示Pattern,用于重复绘制;CGShading和 CGGradient:用于绘制剃度;CGColor 和 CGColorSpace;用来进行颜色和颜色空间管理;CGFont, 用于绘制文本;CGPDFContentStream、CGPDFScanner、CGPDFPage、CGPDFObject,CGPDFStream, CGPDFString等用来进行pdf文件的创建、解析和显示。3、OpenGL ES和GLKit& & & & OpenGL ES是一套多功能开放标准的用于嵌入系统的C-based的图形库,用于2D和3D数据的可视化。OpenGL被设计用来转换一组图形调用功能到底层图形硬件(GPU),由GPU执行图形命令,用来实现复杂的图形操作和运算,从而能够高性能、高帧率利用GPU提供的2D和3D绘制能力。& & & & OpenGL ES规范本身不定义绘制表面和绘制窗口,因此ios为了使用它必须提供和创建一个OpenGL&ES 的呈现环境,创建和配置存储绘制命令结果的framebuffer 及创建和配置一个或多个呈现目标。& & & & 在 IOS中使用EAGL提供的EAGLContext类 来实现和提供一个呈现环境,用来保持OpenGL&ES使用到的硬件状态。 & EAGL是一个Objective-C API,提供使OpenGL ES与Core Animation和UIKIT集成的接口。&&& & & & 在调用任何OpenGL&ES 功能之前必须首先初始化一个EAGLContext 对象。& & & & 每一个IOS应用的每一个线程都有一个当前context,在调用OpenGL&ES函数时,使用或改变此context中的状态。& & & & EAGLContext 的类方法setCurrentContext:&用来设置当前线程的当前context。EAGLContext 的类方法currentContext 返回当前线程的当前context。在切换相同线程的两个上下文之前,必须调用glFlush函数来确保先前已提交的命令被提交到图形硬件中。& & & & 可以采用不同的方式使用OpenGL ES以便呈现OpenGL ES内容到不同的目标:GLKit和CAEAGLLayer。& & & & 为了创建全屏幕的视图或使OpenGL ES内容与UIKit视图集成,可以使用GLKit。在使用GLKit时,GLKit提供的类GLKView类本身实现呈现目标及创建和维护一个framebuffer。& & & & 为了使OpenGL ES内容作为一个Core Animation层的部分内容时,可以使用CAEAGLLayer 作为呈现目标,并需要另外创建framebuffer以及自己实现和控制整个绘制流程。& & & & GLKit是一组Objective-C 类,为使用OpenGL ES 提供一个面向对象接口,用来简化OpenGL ES应用的开发。GLKit支持四个3D应用开发的关键领域:& & & & 1) GLKView 和GLKViewController类提供一个标准的OpenGL&ES视图和相关联的呈现循环。GLKView可以作为OpenGL&ES内容的呈现目标,GLKViewController提供内容呈现的控制和动画。视图管理和维护一个framebuffer,应用只需在framebuffer进行绘画即可。& & & & 2)GLKTextureLoader 为应用提供从IOS支持的各种图像格式的源自动加载纹理图像到OpenGL&ES 图像环境的方式,并能够进行适当的转换,并支持同步和异步加载方式。& & & & 3)数学运算库,提供向量、矩阵、四元数的实现和矩阵堆栈操作等OpenGL ES 1.1功能。& & & & 4)Effect效果类提供标准的公共着色效果的实现。能够配置效果和相关的顶点数据,然后创建和加载适当的着色器。GLKit 包括三个可配置着色效果类:GLKBaseEffect实现OpenGL ES 1.1规范中的关键的灯光和材料模式, GLKSkyboxEffect提供一个skybox效果的实现, GLKReflectionMapEffect 在GLKBaseEffect基础上包括反射映射支持。& & & & 使用GLKView和OpenGL&ES进行绘制过程:& & & & 1)创建一个GLKView 对象& & & & GLKView 对象可以编程或使用Interface Builder来创建和配置。& & & & 在采用编程方式时,首先创建一个context然后调用initWithFrame:context:&方法。& & & & 使用Interface Builder方式时,在从storyboard加载一个GLKView后,创建一个context和设置它作为视图的context属性.& & & & 在iOS中GLKit的使用需要创建OpenGL ES 2.0以上的图形环境context。& & & & &GLKit视图自动创建和配置它所有的OpenGL&ES framebuffer对象和renderbuffers,可以通过修改视图的drawable属性来控制这些对象的属性。& & & & & 2)绘制OpenGL内容(发布绘制命令)& & & & & 使用GLKit视图绘制OpenGL内容需要三个子步骤:准备OpenGL&ES基础;发布绘制命令;呈现显示内容到Core Animation。 & & & & & & GLKit类本身已经实现了第一个和第三个步骤,用户只需实现第二个步骤,在视图的方法drawRect或视图的代理对象的glkView:drawInRect:中调用适当的OpenGL&ES绘制命令进行内容绘制。& & & & &GLKViewController类维护一个animation 呈现循环(包含两个方法update和display),用来实现连续的动画复杂的场景。& & & & &animation 呈现循环的交替速率由GLKViewController的属性framesPerSecond 指示,并使用preferredFramesPerSecond 属性来修改它。4、其它图形编程相关API1)、Core Animation& & & & &Core Animation是一套Objective-C API,实现了一个高性能的复合引擎,并提供一个简单易用的编程接口,给用户UI添加平滑运动和动态反馈能力。& & & & &Core Animation 是 UIKit实现动画和变换的基础,也负责视图的复合功能。使用Core Animation可以实现定制动画和细粒度的动画控制,创建复杂的、支持动画和变换的layered 2D视图。& & & & & Core Animation不属于绘制系统,但它是以硬件复合和操作显示内容的基础设施。这个基础设施的核心是layer对象,用来管理和操作显示内容。在ios 中每一个视图都对应Core Animation的一个层对象,与视图一样,层之间也组织为层关系树。一个层捕获视图内容为一个被图像硬件容易操作的位图。在多数应用中层作为管理视图的方式使用,但也可以创建独立的层到一个层关系树中来显示视图不够支持的显示内容。& & & & &OpenGL ES的内容也可以与Core Animation内容进行集成。& & & & &为了使用Core Animation实现动画,可以修改层的属性值来触发一个action对象的执行,不同的action对象实现不同的动画。& & & & &Core Animation 提供了一下一组应用可以采用的类来提供对不同动画类型的支持:& & & & &CAAnimation是一个抽象公共基类,CAAnimation采用CAMediaTiming 和CAAction协议为动画提供时间(如周期、速度、重复次数等)和action行为(启动、停止等)。& & & & &CAPropertyAnimation是& CAAnimation的抽象子类,为动画提供一个由一个key路径规定的层属性的支持;& & & & &CABasicAnimation 是CAPropertyAnimation的具体子类,为一个层属性提供简单插入能力。& & & & &CAKeyframeAnimation也是CAPropertyAnimation的具体子类,提供key帧动画支持。CATransition是CAAnimation的具体子类,提供影响整个层内容的事物效果。CAAnimationGroup也是CAAnimation的子类,允许动画对象组合到一起并同时运行。2)Image I/O& & & & &Image I/O 提供读写多数格式图像文件的数据的接口。主要包括图像源CGImageSourceRef和图像目标CGImageDestinationRef两个类。3)Sprite Kit& & & & Sprite Kit建立于OpenGL ES之上,Sprite Kit使用图形硬件来有效的呈现动画帧,因此可以高帧率地动画和呈现任意的2D纹理图像或游戏sprite,呈现的内容包括sprites、文本、CGPath形状、视频等。& & & &在Sprite Kit中动画和呈现由一个SKView 视图对象执行。游戏的内容组织为以SKScene 对象表现的一个个场景。一个场景包含要呈现的sprites和其它内容,一个场景也实现每个帧关联的逻辑和内容处理。& & & & 在同一时刻,一个SKView视图只呈现一个场景,在场景呈现时,场景关联的动画和帧关联的逻辑被自动执行。在切换场景时使用SKTransition 类来执行两个场景间的动画。4)SceneKit& & & & SceneKit是一个使用3D图形技术实现的Objective-C 框架,包含一个高性能的呈现引擎和一个高级的描述性API。可以利用该框架创建简单的游戏和界面丰富的用户UI,使用SceneKit仅需要使用描述性API描述你的场景的内容(如几何形状、材料、灯光和摄像等)和你想在那些内容上要执行的行动或动画即可。& & & & SceneKit的内容组织为由节点组成的树形结构,称为scene graph。一个场景包含一个根节点,定义场景的坐标空间,其它节点定义场景的可视内容。SceneKit在GPU上呈现每一帧之前在一个视图上显示场景、处理scene graph和执行动画处理。& & & & SceneKit包含的主要类:& & & & SCNView & SCNSceneRenderer:SCNView是显示或呈现SceneKit内容的视图。SCNSceneRenderer是一个协议,定义用于视图的一些重要方法。& & & &SCNScene: 表现一个场景,是所有SceneKit内容的一个容器。场景可以从使用3D著作工具创建的一个文件中加载,也可以编程创建,场景需要在一个视图上显示。& & & &SCNNode:一个场景的基本构造块,表示scene graph树的一个节点。scene graph树定义了场景上节点之间的逻辑结构,通过为一个节点附属geometries、lights、cameras来提供场景的可视内容。& & & &SCNGeometry、SCNLight、SCNCamera:分别是geometries、lights、cameras对应的类。SCNGeometry为场景提供形状、文本或定制顶点数据,SCNLight为场景提供阴影效果,SCNCamera为场景提供可视点。& & & &SCNMaterial:为SCNGeometry对象定义表面外观属性,规定对象表面如何着色或纹理以及如何反应灯光。& & & &SceneKit内容的动画:& & & &SceneKit动画基于Core Animation 框架,可以隐式或显式创建。& & & & 隐式创建是实际是通过动画节点的一些动画属性来实现:SceneKit自动在run loop一次运行期间对一个场景包含节点属性的所有改变组合成一个原子操作,称为一个事务,由SCNTransaction 类表示;当设置SCNTransaction类的动画周期不为0时,所有对节点动画属性的改变自动执行动画。& & & & 如下代码片段所示:
func fallAndFade(sender:
a href=&& AnyObject /a ) {
SCNTransaction.setAnimationDuration(1.0)
textNode.position = SCNVector3(x: 0.0, y: -10.0, z: 0.0)
textNode.opacity = 0.0
}& & & & &显式创建动画时,可以选择CAAnimation一种类型的子类来创建特定类型的动画。使用key-value为动画规定属性及设置动画参数,然后把创建的动画附属到场景的一个或多个元素。可以使用不同的Core Animation动画类组合或序列化几个动画或创建动画在几个 keyframe值之间插入属性值。& & & & &如下代码片段为显式创建动画的例子:
let animation = CABasicAnimation(keyPath: &geometry.extrusionDepth&)
animation.fromValue = 0.0
animation.toValue = 100.0
animation.duration = 1.0
animation.autoreverses = true
animation.repeatCount = Float.infinity
textNode.addAnimation(animation, forKey: “extrude&)& & & & SceneKit也支持使用SCNSceneSource 类从一个场景文件中加载CAAnimation动画对象,然后附属它到SCNNode对象。5)Metal& & & & Metal框架是一个OpenGL ES类似的底层API,为GPU加速的先进的3D图形呈现或数据并行计算任务提供支持。Metal负责和3D绘图硬件交互,为图形和计算命令的组织、处理、提交和相关资源和数据的管理提供一个细粒度的、底层的支持流式计算的现代API。Metal的目标是在执行GPU任务时尽量减少CPU的负载,消除在GPU执行图形和数据并行计算操作时的性能瓶颈,能够有效的使用多线程并行创建和提交命令到GPU。& & & &Metal也提供了一个映射编程语言用来编写能够被Metal应用使用的图形映射或计算函数。Metal 映射语言编写的代码能够在编译时与应用代码一起被编译,然后在运行时被加载到GPU上执行;也支持运行时对Metal 映射语言代码进行编辑。& & & &在Metal架构中包括如下几个重要的类或协议:1、MTLDevice协议和对象& & & &一个MTLDevice代表一个执行命令的GPU设备,MTLDevice协议为其定义了相关接口,包括查询设备能力属性和创建其它设备特定的对象等接口,例如创建命令队列、从内存中分配缓冲区以及创建纹理等。& & & &应用通过调用MTLCreateSystemDefaultDevice 函数来获取一个系统能够使用的MTLDevice对象。2、命令和命令编码器& & & 在Metal框架中,3D图形呈现命令、计算命令和blitting命令在提交到特定设备GPU上执行前必须进行相应的格式编码,以便能够被GPU识别和执行。& & & Metal框架为每种命令提供了一种编码器协议:& & & MTLRenderCommandEncoder 协议:提供接口用来编码一个单次循环呈现期间要执行的3D图形呈现命令。MTLRenderCommandEncoder 对象用来代表一次图形呈现流程的呈现状态和绘制命令。& & & MTLComputeCommandEncoder协议:提供接口用来编码数据并行计算任务。& & & MTLBlitCommandEncoder协议:提供接口用来编码在缓冲和纹理之间的简单拷贝操作。& & & 在同一时刻,仅能有一个命令编码器激活来添加命令到一个命令缓冲空间上,即每一个命令编码器必须在另一个使用相同命令缓冲空间的命令编码器创建前结束。& & & &Metal为了支持多个不同任务的并行执行,提供了一个MTLParallelRenderCommandEncoder协议来支持多个MTLBlitCommandEncoder在不同线程同时运行提交不同的命令缓冲到同一个命令缓冲空间。每一个线程有一个它自己的命令缓冲对象,在同一时刻,该缓冲对象只能被该线程的一个命令编码器存取。& & & &MTLParallelRenderCommandEncoder对象允许一次呈现循环的命令编码分解到多个命令编码器进行编码,使用多线程进行并行处理来提高处理效率。& & & &一个命令编码器对象调用endEncoding&方法来结束。& & & & 命令编码器对象的创建:& & & & 命令编码器对象由MTLCommandBuffer对象负责创建。MTLCommandBuffer协议定义了如下方法用来创建相应类型的命令编码器对象:& & & & renderCommandEncoderWithDescriptor:&为执行图形呈现任务创建一个MTLRenderCommandEncoder 对象。方法的参数MTLRenderPassDescriptor表现一个编码呈现命令的目标(是一个附属点的集合,最多可以包括四个颜色点数据附属点、一个深度点数据附属点、一个图案点数据附属点),在MTLRenderPassDescriptor对象的附属点属性中指定要呈现的图形目标。& & & & computeCommandEncoder方法为数据并行计算任务创建一个MTLComputeCommandEncoder 对象。& & & & blitCommandEncoder 方法为内存Blit操作和纹理填充操及mipmaps的产生等操作创建一个MTLBlitCommandEncoder 对象。& & & & parallelRenderCommandEncoderWithDescriptor: 方法创建一个MTLParallelRenderCommandEncoder对象。呈现目标由 参数MTLRenderPassDescriptor规定。3、命令缓冲MTLCommandBuffer对象及协议& & & &在经过命令编码器编码后的命令被命令编码器添加到一个称为命令缓冲的MTLCommandBuffer对象上,然后该CommandBuffer对象被提交到GPU来执行其中包含的命令。& & & & MTLCommandBuffer协议为CommandBuffer对象定义接口以及提供命令编码器的创建、提交CommandBuffer到一个命令队列以及检查状态等操作方法。& & & & 一个CommandBuffer对象包含打算在特定设备(GPU)上执行的被编码的命令。一旦所有的编码完成,CommandBuffer本身必须提交到一个命令队列,并标记命令缓冲为准备好状态,以便能够被GPU 执行。& & & & 在标准标准应用中,通常一个呈现帧的呈现命令使用一个线程被编码进一个命令缓冲中。& & & &&MTLCommandBuffer对象的创建和相应方法:& & & & 一个MTLCommandBuffer对象由MTLCommandQueue的commandBuffer方法或commandBufferWithUnretainedReferences方法创建。& & & & 一个MTLCommandBuffer对象仅能提交到创建它的MTLCommandQueue 对象中。& & & & 一个MTLCommandBuffer对象还实现协议定义的如下方法:& & & & enqueue方法用来在命令队列中为该命令缓冲保留一个位置。& & & & commit 方法使MTLCommandBuffer对象被提交执行。& & & & addScheduledHandler:方法用来为一个命令缓冲对象登记一个在该命令缓冲被调度时被调用的代码执行块。可以为一个命令缓冲对象登记多个调度执行块。& & & & waitUntilScheduled 方法等待命令缓冲被调度及在为该命令缓冲登记的所有调度执行块已经执行完。& & & & addCompletedHandler:方法为一个命令缓冲对象登记一个在设备已经执行完该命令缓冲后被调用的代码执行块。也可以为一个命令缓冲对象登记多个完成执行代码块。& & & & waitUntilCompleted 方法等待命令缓冲中命令被设备执行完和为该命令缓冲登记的所有完成执行块都执行结束。& & & & presentDrawable:方法用来在命令缓冲对象被调度时呈现一个可显示资源(CAMetalDrawable 对象)的内容。4、MTLCommandQueue协议和命令队列对象& & & & MTLCommandQueue协议为包含命令缓冲的一个队列。命令队列用来组织其中包含的命令缓冲对象的执行次序和控制命令队列中的命令缓冲对象包含的命令什么时候被执行。& & & &MTLCommandQueue协议为命令队列定义了接口,主要的接口包括命令缓冲对象的创建。& & & &MTLCommandQueue对象的创建:& & & &使用MTLDevice对象的newCommandQueue方法或newCommandQueueWithMaxCommandBufferCount:方法来创建一个命令队列对象。下图为以上这些对象之间的关系图:& & &&& & & &如图中所示:必须为一个呈现命令编码器设置呈现相关的状态、设置和创建相关的呈现用到的缓冲区、纹理等Metal资源对象。& & & &为呈现命令编码器指定的状态包括一个呈现管道流水线状态(Render Pipeline State),一个深度和图案状态(Depth Stencil State),一个采样状态(Sampler State)。& & & &一个Blit命令编码器与一个缓冲区和一个纹理关联,用来在两者之间进行Blit操作。& & & &命令编码器指定图形或计算功能时可以分配三种类型的MTLResource Metal资源对象使用:& & & & MTLBuffer 表现一个能够包含任意类型数据的无格式内存。MTLBuffer通常用于多边形顶点vertex、着色器shader及计算状态数据。& & & & MTLTexture表现一个有着特定纹理类型和点格式的具有相应格式的图像数据。纹理对象可以作为多边形顶点vertex、片段fragment或计算功能的一个源,也可以在呈现描述符中作为图形呈现的输出目标。& & & & MTLSamplerState对象当一个图形或计算功能在一个MTLTexture上执行纹理采样操作时使用,用来定义地址、过滤和其它属性。& & & &图形呈现编码器MTLRenderCommandEncoder 可以使用setVertex*及setFragment* 方法组作为其参数来为相应的映射函数分配一个或多个资源。5、CAMetalLayer 对象和CAMetalDrawable 协议& & & Core Animation定义了一个CAMetalLayer类和一个CAMetalDrawable 协议用来提供一个Metal内容呈现的层后备视图。CAMetalLayer对象包含有关要呈现内容的位置、尺寸、可视属性(背景颜色、边界和阴影)及Metal呈现内容使用到的资源等。CAMetalDrawable 协议是MTLDrawable 的扩展,指定了可显示资源对象要符合的MTLTexture协议,使可显示资源对象可用作呈现命令的目标。& & & 为了实现Metal内容在一个CAMetalLayer对象的呈现,应为每次呈现流程创建一个CAMetalDrawable对象,从中得到它包含的MTLTexture 对象,然后在呈现流水线描述MTLRenderPipelineDescriptor 的颜色附属点属性中使用,指定其为图形呈现命令的目标。& & & 一个CAMetalLayer对象调用CAMetalLayer 对象的nextDrawable 方法来创建。& & & 在创建一个可显示资源作为图形命令的目标后,就可以调用如下步骤完成图形的绘制。1)、首先创建一个MTLCommandQueue 对象,然后使用它创建一个MTLCommandBuffer对象;2)、创建一个MTLRenderPassDescriptor对象,为其规定用作图形缓冲中的编码呈现命令目标的附属点集合;然后使用这个MTLRenderPassDescriptor 对象创建一个MTLRenderCommandEncoder对象;3) 创建相应的Metal资源对象,来存储绘制用到资源数据,如顶点坐标和顶点颜色数据;并调用MTLRenderCommandEncoder的setVertex*:offset:atIndex: 和setFragment* :offset:atIndex:方法来为呈现编码器指定用到的资源;4) 创建一个MTLRenderPipelineDescriptor 对象并为其指定vertexFunction和fragmentFunction 属性,这些属性使用Metal映射语言代码中读取的相应映射函数MTLFunction对象来设置。5)使用MTLDevice的newRenderPipelineStateWithDescriptor:error:方法或类似方法并根据MTLRenderPipelineDescriptor创建一个MTLRenderPipelineState对象;然后调用MTLRenderCommandEncoder 的setRenderPipelineState: 方法来为呈现编码器对象MTLRenderCommandEncoder设置管道流水线;6)调用MTLRenderCommandEncoder 的drawPrimitives:vertexStart:vertexCount: 方法来执行图形的呈现,然后调用MTLRenderCommandEncoder的endEncoding 方法来结束本次呈现流程的编码,最后调用MTLCommandBuffer 的commit方法来在GPU上执行整个绘制命令。
学习蓝图?cocos2d侧重2d开发,能够很好地处理贴图的动画、纹理以及物理碰撞、粒子等,也有比较简单的流程控制和节点关系。cocos2d-x的开发语言是c++,所以可以一次开发,多平台(ios,android)可编译。cocos2d只是一个SDK,仍然需要目标平台的开发环境和自己写代码的能力。unity3D侧重3d开发,本身就是一个整合的开发工具,支持多平台。几乎与其他各种游戏引擎一样,提供建模工具和各种编辑器,开发过程绝大多数是GUI下完成。unity3d开发的ios应用,在下载量超过一定后按盈利比例收费。unreal,我用的时候,还只是说刚刚支持ios、mac平台,开发环境只能是windows。同样是一个完善的IDE。开发工具有免费版本和收费版本。但所开发的应用只要发布,就要进行一次性的收费,不适合个人或小团队开发。总结:cocos2d是需要用objective-c(cocos2d-iphone)或c++(cocos2d-x)写相当的代码量。整个游戏的架构过程都是由代码完成,cocos2d概念较典型(对于ios应用来说),通过自己写代码、大到架构游戏流程、小到具体的精灵行为都是自己动手写代码。对于学习来说,是很有帮助的。unity3d、unreal等引擎,更适合小型、大中型团队开发商业项目。其游戏开发过程,更侧重于你所谓的“游戏美术”。实际编程量很少,都是在GUI下完成。所以如果你侧重于游戏编程的学习,这两种引擎并不适合。它们更像是作为独立技术存在。游戏美术,这个概念不大明白,但我个人理解就是游戏对象的建模和贴图的制作、UI设计、以及游戏整体风格的定位吧。都是手打,希望对你的选择有所帮助:)
如果楼主是自学的话,那么我有一个小小的意见,还是不建议楼主自学,虽然时候无师自通出来以后会很厉害,但是有几个无师自通的人是真正的编程高手,尤其是iOS开发这一方面,他不想android是开源的,哪些是重点,哪些需要多练,没有人带的话,都找不到重点,万一在“走火入魔”了,ios就彻底学杂了,我从“好程序员训练营”的网站上找到学习iOS开发的大纲图,希望能够帮助到你。第一阶段:MACOS X 平台介绍、C开发、数据结构和算法、初级OC语言开发第二阶段:iOS高级编程第三阶段:项目训练阶段第四阶段:就业指导、职业规划每一个阶段具体都有什么课程,楼主可以自己去他们的官网上看一下。希望楼主早日成为IOS开发界的大神。
相关搜索:
相关阅读:
相关频道:
Android教程最近更新}

我要回帖

更多关于 drawrect调用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信