Swift语言iOS开发:CALayer十则示例

上传人:xins****2008 文档编号:73232049 上传时间:2022-04-11 格式:DOC 页数:51 大小:71KB
返回 下载 相关 举报
Swift语言iOS开发:CALayer十则示例_第1页
第1页 / 共51页
Swift语言iOS开发:CALayer十则示例_第2页
第2页 / 共51页
Swift语言iOS开发:CALayer十则示例_第3页
第3页 / 共51页
亲,该文档总共51页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
作者:Scott Gardner 译者:TurtleFromMars原文:CALayer in iOS with Swift: 10 Examples如你所知,我们在iOS应用中看到的都是视图(view),包括按钮视图、表视图、滑动条视图,还有可以容纳其他视图的父视图等。但你或许不知道在iOS中支撑起每个视图的是一个叫做”图层(layer)”的类,确切地说是CALayer。本文中您会了解CALayer及其工作原理,还有应用CALayer打造酷炫效果的十则示例,比如绘制矢量图形、渐变色,甚至是粒子系统。本文要求读者熟悉iOS应用开发和Swift语言的基础知识,包括利用Storyboard构建用户界面。注:如果您尚未掌握这些基础,不必担心,我们有不少相关教程,例如使用Swift语言编写iOS应用和iOS学徒。准备开始要理解图层是什么,最简便的方式就是”实地考察”。我们这就创建一个简单的项目,从头开始玩转图层。准备好写代码了吗?好!启动Xcode,然后:1.选择FileNewProject菜单项。2.在对话框中选择iOSApplicationSingle View Application。3.点击Next,Product Name填写CALayerPlayground,然后输入你自己的Organization Name和Identifier。4.Language选Swift,Devices选Universal。5.取消选择Core Data,点击Next。6.把项目保存到合适的位置(个人习惯把项目放在用户目录下建立的Source文件夹),点击Create。好,文件准备就绪,接下来就是创建视图了:7.在项目导航栏(Project navigator)中选择Main.storyboard。8.选择ViewAssistant EditorShow Assistant Editor菜单项,如果没有显示对象库(Object Library),请选择ViewUtilitiesShow Object Library。9.然后选择EditorCanvasShow Bounds Rectangles,这样在向场景添加视图时就可以看到轮廓了。10.把一个视图(View)从对象库拖入视图控制器场景,保持选中状态,在尺寸检查器(ViewUtilitiesShow Size Inspector)中将x和y设为150,Width和Height设为300。11.视图保持选中,点击自动布局工具栏(Storyboard右下角)的Align按钮,选中Horizontal Center in Container和Vertical Center in Container,数值均为0,然后点击Add 2 Constraints。12.点击Pin按钮,选中Width和Height,数值均设为300,点击Add 2 Constraints。最后按住control从刚刚创建的视图拖到ViewController.swift文件中viewDidLoad()方法的上方,在弹框中将outlet命名为viewForLayer,如图:点击Connect创建outlet。将ViewController.swift中的代码改写为:importUIKitclassViewController:UIViewControllerIBOutletweakvarviewForLayer:UIView!varl:CALayerreturnviewForLayer.layeroverridefuncviewDidLoad()super.viewDidLoad()setUpLayer()funcsetUpLayer()l.backgroundColor=UIColor.blueColor().CGColorl.borderWidth=100.0l.borderColor=UIColor.redColor().CGColorl.shadowOpacity=0.7l.shadowRadius=10.0之前提到iOS中的每个视图都拥有一个关联的图层,你可以通过yourView.layer访问图层。这段代码首先创建了一个叫”l”(小写L)的计算属性,方便访问viewForLayer的图层,可让你少写一些代码。这段代码还调用了setUpLayer方法设置图层属性:阴影,蓝色背景,红色粗边框。你马上就可以了解这些东西,不过现在还是先构建App,在iOS模拟器中运行(我选了iPhone 6),看看自定义的图层如何。几行代码,效果还不错吧?还是那句话,每个视图都由图层支撑,所以你也可以对App中的任何视图做出类似修改。我们继续深入。CALayer基本属性CALayer有几个属性可以用来自定外观,想想刚才做的:把图层背景色从默认的无色改为蓝色通过把边框宽度从默认的0改为100来添加边框把边框颜色从默认的黑色改为红色最后把阴影透明度从0(全透明)改为0.7,产生阴影效果,此外还把阴影半径从默认的3改为10。以上只是CALayer中可以设置的部分属性。我们再试两个,在setUpLayer()中追加以下代码:l.contents=UIImage(named:”star”)?.CGImagel.contentsGravity=kCAGravityCenterCALayer的contents属性可以把图层的内容设为图片,这里我们要设置一张”星星”的图片,为此你需要把图片添加到项目中,请下载图片并添加到项目中。构建,运行,欣赏一下效果:注意星星居中,这是因为contentsGravity属性被设为kCAGravityCenter,如你所想,重心也可以设为上、右上、右、右下、下、左下、左、左上。更改图层外观仅供娱乐,我们来添加几个手势识别器来控制图层外观。在Xcode中,向viewForLayer对象上拖一个轻触手势识别器(tap gesture recognizer),见下图:注:如果你对手势识别器比较陌生,请参阅Using UIGestureRecognizer with Swift。以此类推,再添加一个捏合手势识别器(pinch gesture recognizer)。然后按住control依次将两个手势识别器从Storyboard场景停靠栏拖入ViewController.swift,放在setUpLayer()和类自身的闭合花括号之间。在弹框中修改连接为Action,命名轻触识别操作为tapGestureRecognized,捏合识别操作为pinchGestureRecognized,例如:如下改写tapGestureRecognized(_:):IBActionfunctapGestureRecognized(sender:UITapGestureRecognizer)l.shadowOpacity=l.shadowOpacity=0.7?0.0:0.7当令视图识别出轻触手势时,代码告知viewForLayer图层在0.7和0之间切换阴影透明度。你说视图?嗯,没错,重写CALayer的hitTest(_:)也可以实现相同效果,本文后面也会看到这个方法,不过我们这里用的方法也有道理:图层本身并不能响应手势识别,只能响应点击测试,所以我们在视图上设置了轻触手势识别器。然后如下修改pinchGestureRecognized(_:):IBActionfuncpinchGestureRecognized(sender:UIPinchGestureRecognizer)letoffset:CGFloat=sender.scale=100.0&newFrame.width此处基于用户的捏合手势创建正负偏移值,借此调整图层框架大小、边缘宽度和边角半径。图层的边角半径默认值为0,意即标准的90度直角。增大半径会产生圆角,如果想将图层变成圆形,可以设边角半径为宽度的一半。注意:调整边角半径并不会裁剪图层内容(星星图片),除非图层的masksToBounds属性被设为true。构建运行,尝试在视图中使用轻触和捏合手势:嘿,再好好装扮一下都能当头像用了! :CALayer体验CALayer中的属性和方法琳琅满目,此外还有几个包含特有属性和方法的子类。要遍历如此酷炫的API,R导游先生最好不过了。接下来,你需要以下材料:Layer Player AppLayer Player 源代码该App包含十种不同的CALayer示例,本文后面会依次介绍,十分方便。先来吊吊大家的胃口:下面在讲解每个示例的同时,我建议在CALayer演示应用中亲自动手试验,还可以读读代码。不用写,只要深呼吸,轻松阅读就可以了。 :我相信这些酷炫的示例会启发您利用不同的CALayer为自己的App锦上添花,希望大家喜欢!示例 #1:CALayer前面我们看过使用CALayer的示例,也就是设置各种属性。关于CALayer还有几点没提:图层可以包含子图层。就像视图可以包含子视图,图层也可以有子图层,稍加利用就能打造漂亮的效果!图层属性自带动画效果。修改图层属性时,存在默认的动画效果,你也可以自定义动画行为。图层是轻量概念。相对视图而言,图层更加轻量,因此图层可以帮助提升性能。图层有大量实用属性。前面你已经看过几条了,我们继续探索!刚刚说CALayer图层有很多属性,我们来看一批实用属性:有些属性你可能第一次见,但真的很方便!/1letlayer=CALayer()layer.frame=someView.bounds/2layer.contents=UIImage(named:”star”)?.CGImagelayer.contentsGravity=kCAGravityCenter/3layer.magnificationFilter=kCAFilterLinearlayer.geometryFlipped=false/4layer.backgroundColor=UIColor(red:11/255.0,green:86/255.0,blue:14/255.0,alpha:1.0).CGColorlayer.opacity=1.0layer.hidden=falselayer.masksToBounds=false/5layer.cornerRadius=100.0layer.borderWidth=12.0layer.borderColor=UIColor.whiteColor().CGColor/6layer.shadowOpacity=0.75layer.shadowOffset=CGSize(width:0,height:3)layer.shadowRadius=3.0someView.layer.addSublayer(layer)在以上代码中:创建一个CALayer实例,并把框架设为someView边框。将图层内容设为一张图片,并使其在图层内居中,注意赋值的类型是底层的Quartz图像数据(CGImage)。使用过滤器,过滤器在图像利用contentsGravity放大时发挥作用,可用于改变大小(缩放、比例缩放、填充比例缩放)和位置(中心、上、右上、右等等)。以上属性的改变没有动画效果,另外如果geometryFlipped未设为true,几何位置和阴影会上下颠倒。继续:把背景色设为Ray最爱的深绿色。: 然后让图层透明、可见。同时令图层不要遮罩内容,意思是如果图层尺寸小于内容(星星图片),图像不会被裁减。图层边角半径设为图层宽度的一半,使边缘变为圆形,注意图层颜色赋值类型为Quartz颜色引用(CGColor)。创建阴影,设shouldRasterize为true(后文还会提到),然后将图层加入视图结构树。结果如下:CALayer还有两个附加属性有助于改善性能:shouldRasterize和drawsAsynchronously。shouldRasterize默认为false,设为true可以改善性能,因为图层内容只需要一次渲染。相对画面中移动但自身外观不变的对象效果拔群。drawsAsynchronously默认值也是false。与shouldRasterize相对,该属性适用于图层内容需要反复重绘的情况,此时设成true可能会改善性能,比如需要反复绘制大量粒子的粒子发射器图层(可以参考后面的CAEmitterLayer示例)。谨记:如果想将已有图层的shouldRasterize或drawsAsynchronously属性设为true,一定要三思而后行,考虑可能造成的影响,对比true与false的性能差异,辨明属性设置是否有积极效果。设置不当甚至会导致性能大幅下降。无论如何还是先回到图层演示应用,其中有些控件可以用来调整CALayer的属性:调节试试看,感受一下,利用CALayer可以实现怎样的效果。注:图层不属于响应链(responder chain),无法像视图一样直接响应触摸和手势,我们在CALayerPlayground中见识过。不过图层有点击测试,后面的CATransformLayer会提到。你也可以向图层添加自定义动画,CAReplicatorLayer中会出现。示例 #2:CAScrollLayerCAScrollLayer显示一部分可滚动图层,该图层十分基础,无法直接响应用户的触摸操作,也不能直接检查可滚动图层的边界,故可避免越界无限滚动。UIScrollView用的不是CAScrollLayer,而是直接改动图层边界。CAScrollLayer的滚动模式可设为水平、垂直或者二维,你也可以用代码命令视图滚动到指定位置:/InScrollingView.swiftimportUIKitclassScrollingView:UIView/1overrideclassfunclayerClass()-AnyClassreturnCAScrollLayer.self/InCAScrollLayerViewController.swiftimportUIKitclassCAScrollLayerViewController:UIViewControllerIBOutletweakvarscrollingView:ScrollingView!/2varscrollingViewLayer:CAScrollLayerreturnscrollingView.layerasCAScrollLayeroverridefuncviewDidLoad()super.viewDidLoad()/3scrollingViewLayer.scrollMode=kCAScrollBothIBActionfunctapRecognized(sender:UITapGestureRecognizer)/4varnewPoint=CGPoint(x:250,y:250)UIView.animateWithDuration(0.3,delay:0,options:.CurveEaseInOut,animations:unownedselfinself.scrollingViewLayer.scrollToPoint(newPoint),completion:nil)以上代码:定义一个继承UIView的类,重写layerClass()返回CAScrollLayer,该方法等同于创建一个新图层作为子图层(CALayer示例中做过)。一个用以方便简化访问自定义视图滚动图层的计算属性。设滚动模式为二维滚动。识别出轻触手势时,让滚动图层在UIView动画中滚到新建的点。(注:scrollToPoint(_:)和scrollToRect(_:)不会自动使用动画效果。)案例研究:如果ScrollingView实例包含大于滚动视图边界的图片视图,在运行上述代码并点击视图时结果如下:图层演示应用中有可以锁定滚动方向(水平或垂直)的开关。以下经验规律用于决定是否使用CAScrollLayer:如果想使用轻量级的对象,只需用代码操作滚动:可以考虑CAScrollLayer。如果想让用户操作滚动,UIScrollView大概是更好的选择。要了解更多,请参考我们的视频教程。如果是滚动大型图片:考虑使用CATiledLayer(见后文)。示例 #3:CATextLayerCATextLayer能够对普通文本或属性字串进行简单快速的渲染。与UILabel不同,CATextLayer无法指定UIFont,只能使用CTFontRef或CGFontRef。像下面这样的代码完全可以掌控文本的字体、字体大小、颜色、对齐、折行(wrap)和截断(truncation)规则,也有动画效果:/1lettextLayer=CATextLayer()textLayer.frame=someView.bounds/2varstring=“for_in1.20string+=“Loremipsumdolorsitamet,consecteturadipiscingelit.Fusceauctorarcuquisvelitconguedictum.”textLayer.string=string/3letfontName:CFStringRef=“Noteworthy-Light”textLayer.font=CTFontCreateWithName(fontName,fontSize,nil)/4textLayer.foregroundColor=UIColor.darkGrayColor().CGColortextLayer.wrapped=truetextLayer.alignmentMode=kCAAlignmentLefttextLayer.contentsScale=UIScreen.mainScreen().scalesomeView.layer.addSublayer(textLayer)以上代码解释如下:创建一个CATextLayer实例,令边界与someView相同。重复一段文本,创建字符串并赋给文本图层。创建一个字体,赋给文本图层。将文本图层设为折行、左对齐,你也可以设自然对齐(natural)、右对齐(right)、居中对齐(center)或两端对齐(justified),按屏幕设置contentsScale属性,然后把图层添加到视图结构树。不仅是CATextLayer,所有图层类的渲染缩放系数都默认为1。在添加到视图时,图层自身的contentsScale缩放系数会自动调整,适应当前画面。你需要为手动创建的图层明确指定contentsScale属性,否则默认的缩放系数1会在Retina显示屏上产生部分模糊。如果创建的文本图层添加到了方形的someView,效果会像这样:你可以设置截断(Truncation)属性,生效时被截断的部分文本会由省略号代替显示。默认设定为无截断,位置可设为开头、末尾或中间截断:图层演示应用中,你可以随心所欲地修改很多CATextLayer属性:示例 #4:AVPlayerLayerAVPlayerLayer是建立在AVFoundation基础上的实用图层,持有一个AVPlayer,用来播放音视频媒体文件(AVPlayerItems),举例如下:overridefuncviewDidLoad()super.viewDidLoad()/1letplayerLayer=AVPlayerLayer()playerLayer.frame=someView.bounds/2leturl=NSBundle.mainBundle().URLForResource(“someVideo”,withExtension:”m4v”)letplayer=AVPlayer(URL:url)/3player.actionAtItemEnd=.NoneplayerLayer.player=playersomeView.layer.addSublayer(playerLayer)/4NSNotificationCenter.defaultCenter().addObserver(self,selector:”playerDidReachEndNotificationHandler:”,name:”AVPlayerItemDidPlayToEndTimeNotification”,object:player.currentItem)deinitNSNotificationCenter.defaultCenter().removeObserver(self)/5IBActionfuncplayButtonTapped(sender:UIButton)ifplayButton.titleLabel?.text=“Play”player.play()playButton.setTitle(“Pause”,forState:.Normal)elseplayer.pause()playButton.setTitle(“Play”,forState:.Normal)updatePlayButtonTitle()updateRateSegmentedControl()/6funcplayerDidReachEndNotificationHandler(notification:NSNotification)letplayerItem=notification.objectasAVPlayerItemplayerItem.seekToTime(kCMTimeZero)上述代码解释:新建一个播放器图层,设置框架。使用AV asset资源创建一个播放器。告知命令播放器在播放完成后停止。其他选项还有暂停或自动播放下一个媒体资源。注册AVPlayer通知,在一个文件播放完毕后发送通知,并在析构函数中删除作为观察者的控制器。点击播放按钮时,触发控件播放AV asset并设置按钮文字。注意这只是个入门示例,在实际项目中往往不会采用文字按钮控制播放。AVPlayerLayer和其中创建的AVPlayer会像这样显示为AVPlayerItem实例的第一帧:AVPlayerLayer还有一些附加属性:videoGravity设置视频显示的缩放行为。readyForDisplay检测是否准备好播放视频。另一方面,AVPlayer也有不少附加属性和方法,有一个值得注意的是rate属性,对于0到1之间的播放速率,0代表暂停,1代表常速播放(1x)。不过rate属性的设置是与播放行为联动的,也就是说调用pause()方法和把rate设为0是等价的,调用play()与把rate设为1也一样。那快进、慢动作和反向播放呢?交给AVPlayerLayer把。rate大于1时会令播放器以相应倍速进行播放,例如rate设为2就是二倍速。如你所想,rate为负时会让播放器以相应倍速反向播放。然而,在以非常规速率播放之前,AVPlayerItem上会调用适当方法,验证是否能够以相应速率进行播放:canPlayFastForward()对应大于1canPlaySlowForward()对应0到1之间canPlayReverse()对应-1canPlaySlowReverse()对应-1到0之间canPlayFastReverse()对应小于-1绝大多数视频都支持以不同速率正向播放,可以反向播放的视频相对少一些。演示应用也包含了播放控件:示例 #5:CAGradientLayerCAGradientLayer简化了混合两种或更多颜色的工作,尤其适用于背景。要配置渐变色,你需要分配一个CGColor数组,以及标识渐变图层起止点的startPoint和endPoint。注意:startPoint和endPoint并不是明确的点,而是用单位坐标空间定义,在绘制时映射到图层边界。也就是说x值为1表示点在图层右边缘,y值为1表示点在图层下边缘。CAGradientLayer包含type属性,虽说该属性只有kCAGradientLayerAxial一个选择,由数组中的各颜色产生线性过渡渐变。具体含义是渐变过渡沿startPoint到endPoint的向量A方向产生,设B与A垂直,则各条B平行线上的所有点颜色相同。此外,locations属性可以使用一个数组(元素取值范围0到1),指定渐变图层参照colors顺序取用下一个过渡点颜色的位置。未设定时默认会平均分配过渡点。一旦设定就必须与colors的数量保持一致,否则会出错。 :下面是创建渐变图层的例子:letgradientLayer=CAGradientLayer()gradientLayer.frame=someView.boundsgradientLayer.colors=cgColorForRed(209.0,green:0.0,blue:0.0),cgColorForRed(255.0,green:102.0,blue:34.0),cgColorForRed(255.0,green:218.0,blue:33.0),cgColorForRed(51.0,green:221.0,blue:0.0),cgColorForRed(17.0,green:51.0,blue:204.0),cgColorForRed(34.0,green:0.0,blue:102.0),cgColorForRed(51.0,green:0.0,blue:68.0)gradientLayer.startPoint=CGPoint(x:0,y:0)gradientLayer.endPoint=CGPoint(x:0,y:1)someView.layer.addSublayer(gradientLayer)funccgColorForRed(red:CGFloat,green:CGFloat,blue:CGFloat)-AnyObjectreturnUIColor(red:red/255.0,green:green/255.0,blue:blue/255.0,alpha:1.0).CGColorasAnyObject上述代码创建一个渐变图层,框架设为someView边界,指定颜色数组,设置起止点,添加图层到视图结构树。效果如下:五彩缤纷,姹紫嫣红!图层演示应用中,你可以随意修改起止点、颜色和过渡点:示例 #6:CAReplicatorLayerCAReplicatorLayer能够以特定次数复制图层,可以用来创建一些很棒的效果。每个图层复件的颜色和位置都可以改动,而且可以在总复制图层之后延迟绘制,营造一种动画效果。还可以利用深度,创造三维效果。举个例子/1letreplicatorLayer=CAReplicatorLayer()replicatorLayer.frame=someView.bounds/2replicatorLayer.instanceCount=30replicatorLayer.instanceDelay=CFTimeInterval(1/30.0)replicatorLayer.preservesDepth=falsereplicatorLayer.instanceColor=UIColor.whiteColor().CGColor/3replicatorLayer.instanceRedOffset=0.0replicatorLayer.instanceGreenOffset=-0.5replicatorLayer.instanceBlueOffset=-0.5replicatorLayer.instanceAlphaOffset=0.0/4letangle=Float(M_PI*2.0)/30replicatorLayer.instanceTransform=CATransform3DMakeRotation(CGFloat(angle),0.0,0.0,1.0)someView.layer.addSublayer(replicatorLayer)/5letinstanceLayer=CALayer()letlayerWidth:CGFloat=10.0letmidX=CGRectGetMidX(someView.bounds)-layerWidth/2.0instanceLayer.frame=CGRect(x:midX,y:0.0,width:layerWidth,height:layerWidth*3.0)instanceLayer.backgroundColor=UIColor.whiteColor().CGColorreplicatorLayer.addSublayer(instanceLayer)/6letfadeAnimation=CABasicAnimation(keyPath:”opacity”)fadeAnimation.fromValue=1.0fadeAnimation.toValue=0.0fadeAnimation.duration=1fadeAnimation.repeatCount=Float(Int.max)/7instanceLayer.opacity=0.0instanceLayer.addAnimation(fadeAnimation,forKey:”FadeAnimation”)以上代码:创建一个CAReplicatorLayer实例,设框架为someView边界。设复制图层数instanceCount和绘制延迟,设图层为2D(preservesDepth = false),实例颜色为白色。为陆续的实例复件设置RGB颜色偏差值(默认为0,即所有复件保持颜色不变),不过这里实例初始颜色为白色,即RGB都为1.0,所以偏差值设红色为0,绿色和蓝色为相同负数会使其逐渐现出红色,alpha透明度偏差值的变化也与此类似,针对陆续的实例复件。创建旋转变换,使得实例复件按一个圆排列。创建供复制图层使用的实例图层,设置框架,使第一个实例在someView边界顶端水平中心处绘制,另外设置实例颜色,把实例图层添加到复制图层。创建一个透明度由1(不透明)过渡为0(透明)的淡出动画。设实例图层透明度为0,使得每个实例在绘制和改变颜色与alpha前保持透明。这段代码会实现这样的东西:图层演示应用中,你可以改动这些属性:示例 #7:CATiledLayerCATiledLayer以图块(tile)为单位异步绘制图层内容,对超大尺寸图片或者只能在视图中显示一小部分的内容效果拔群,因为不用把内容完全载入内存就可以看到内容。处理绘制有几种方法,一种是重写UIView,使用CATiledLayer绘制图块填充视图背景,如下:/InViewController.swiftimportUIKitclassViewController:UIViewController/1IBOutletweakvartiledBackgroundView:TiledBackgroundView!/InTiledBackgroundView.swiftimportUIKitclassTiledBackgroundView:UIViewletsideLength=CGFloat(50.0)/2overrideclassfunclayerClass()-AnyClassreturnCATiledLayer.self/3requiredinit(coderaDecoder:NSCoder)super.init(coder:aDecoder)srand48(Int(NSDate().timeIntervalSince1970)letlayer=self.layerasCATiledLayerletscale=UIScreen.mainScreen().scalelayer.contentsScale=scalelayer.tileSize=CGSize(width:sideLength*scale,height:sideLength*scale)/4overridefuncdrawRect(rect:CGRect)letcontext=UIGraphicsGetCurrentContext()varred=CGFloat(drand48()vargreen=CGFloat(drand48()varblue=CGFloat(drand48()CGContextSetRGBFillColor(context,red,green,blue,1.0)CGContextFillRect(context,rect)代码解释:tiledBackgroundView位于 (150, 150) ,宽高均为300。重写layerClass(),令该视图创建的图层实例为CATiledLayer。设置rand48()的随机数种子,用于在drawRect()中生成随机颜色。CATiledLayer类型转换,缩放图层内容,设置图块尺寸,适应屏幕。重写drawRect(),以随机色块填充视图。代码绘制66随机色块方格,最终效果如下:图层演示应用中除此之外还可以在图层背景上绘制轨迹:在视图中放大时,上述截图中的星星图案会变得模糊:产生模糊的根源是图层的细节层次(level of detail,简称LOD),CATiledLayer有两个相关属性:levelsOfDetail和levelsOfDetailBias。levelsOfDetail顾名思义,指图层维护的LOD数目,默认值为1,每进一级会对前一级分辨率的一半进行缓存,图层的levelsOfDetail最大值,也就是最底层细节,对应至少一个像素点。而levelsOfDetailBias指的是该图层缓存的放大LOD数目,默认为0,即不会额外缓存放大层次,每进一级会对前一级两倍分辨率进行缓存。例如,设上述分块图层的levelsOfDetailBias为5会缓存2x、4x、8x、16x和32x的放大层次,放大的图层效果如下:不错吧?别着急,还没讲完呢。CATiledLayer裁刀,买不了吃亏,买不了上当,只要998(译注:此处内容稍作本地化处理,原文玩的是1978年美国Ginsu刀具的梗,堪称询价型电视购物广告的万恶之源。) :开个玩笑。CATiledLayer还有一个更实用的功能:异步绘制图块,比如在滚动视图中显示一张超大图片。在用户滚动画面时,要让分块图层知道哪些图块需要绘制,写代码在所难免,不过换来性能提升也值了。图层演示应用的UIImage+TileCutter.swift中包含一个UIImage扩展,教程编纂组成员Nick Lockwood在著作iOS Core Animation: Advanced Techniques的一个终端应用程序中利用了这段代码。代码的职责是把原图片拆分成指定尺寸的方块,按行列位置命名图块,比如第三行第七列的图块windingRoad62.png(索引从零开始)。有了这些图块,我们可以自定义一个UIView子类,绘制分块图层:importUIKitclassTilingViewForImage:UIView/1letsideLength=CGFloat(640.0)letfileName=“windingRoad”letcachesPath=NSSearchPathForDirectoriesInDomains(.CachesDirectory,.UserDomainMask,true)0asString/2overrideclassfunclayerClass()-AnyClassreturnCATiledLayer.self/3requiredinit(coderaDecoder:NSCoder)super.init(coder:aDecoder)letlayer=self.layerasCATiledLayerlayer.tileSize=CGSize(width:sideLength,height:sideLength)/4overridefuncdrawRect(rect:CGRect)letfirstColumn=Int(CGRectGetMinX(rect)/sideLength)letlastColumn=Int(CGRectGetMaxX(rect)/sideLength)letfirstRow=Int(CGRectGetMinY(rect)/sideLength)letlastRow=Int(CGRectGetMaxY(rect)/sideLength)forrowinfirstRow.lastRowforcolumninfirstColumn.lastColumniflettile=imageForTileAtColumn(column,row:row)letx=sideLength*CGFloat(column)lety=sideLength*CGFloat(row)letpoint=CGPoint(x:x,y:y)letsize=CGSize(width:sideLength,height:sideLength)vartileRect=CGRect(origin:point,size:size)tileRect=CGRectIntersection(bounds,tileRect)tile.drawInRect(tileRect)funcimageForTileAtColumn(column:Int,row:Int)-UIImage?letfilePath=“(cachesPath)/(fileName)_(column)_(row)”returnUIImage(contentsOfFile:filePath)以上代码:创建属性,分别是图块边长、原图文件名、供TileCutter扩展保存图块的缓存文件夹路径。重写layerClass()返回CATiledLayer。实现init(_:),把视图的图层转换为分块图层,设置图块大小。注意此处不必设置contentsScale适配屏幕,因为是直接修改视图自身的图层,而不是手动创建子图层。重写drawRect(),按行列绘制各个图块。像这样,原图大小的自定义视图就可以塞进一个滚动视图:多亏CATiledLayer,滚动5120 x 3200的大图也会这般顺滑:如你所见,快速滚动时绘制图块的过程还是很明显,你可以利用更小的分块(上述例子中分块为640 x 640),或者自己创建一个CATiledLayer子类,重写fadeDuration()返回0:classTiledLayer:CATiledLayeroverrideclassfuncfadeDuration()-CFTimeIntervalreturn0.0示例 #8:CAShapeLayerCAShapeLayer利用可缩放的矢量路径进行绘制,绘制速度比使用图片快很多,还有个好处是不用分别提供常规、2x和3x版本的图片,好用。另外还有各种属性,让你可以自定线粗、颜色、虚实、线条接合方式、闭合线条是否形成闭合区域,还有闭合区域要填充何种颜色等。举例如下:importUIKitclassViewController:UIViewControllerIBOutletweakvarsomeView:UIView!/1letrwColor=UIColor(red:11/255.0,green:86/255.0,blue:14/255.0,alpha:1.0)letrwPath=UIBezierPath()letrwLayer=CAShapeLayer()/2funcsetUpRWPath()rwPath.moveToPoint(CGPointMake(0.22,124.79)rwPath.addLineToPoint(CGPointMake(0.22,249.57)rwPath.addLineToPoint(CGPointMake(124.89,249.57)rwPath.addLineToPoint(CGPointMake(249.57,249.57)rwPath.addLineToPoint(CGPointMake(249.57,143.79)rwPath.addCurveToPoint(CGPointMake(249.37,38.25),controlPoint1:CGPointMake(249.57,85.64),controlPoint2:CGPointMake(249.47,38.15)rwPath.addCurveToPoint(CGPointMake(206.47,112.47),controlPoint1:CGPointMake(249.27,38.35),controlPoint2:CGPointMake(229.94,71.76)rwPath.addCurveToPoint(CGPointMake(163.46,186.84),controlPoint1:CGPointMake(182.99,153.19),controlPoint2:CGPointMake(163.61,186.65)rwPath.addCurveToPoint(CGPointMake(146.17,156.99),controlPoint1:CGPointMake(163.27,187.03),controlPoint2:CGPointMake(155.48,173.59)rwPath.addCurveToPoint(CGPointMake(128.79,127.08),controlPoint1:CGPointMake(136.82,140.43),controlPoint2:CGPointMake(129.03,126.94)rwPath.addCurveToPoint(CGPointMake(109.31,157.77),controlPoint1:CGPointMake(128.59,127.18),controlPoint2:CGPointMake(119.83,141.01)rwPath.addCurveToPoint(CGPointMake(89.83,187.86),controlPoint1:CGPointMake(98.79,174.52),controlPoint2:CGPointMake(90.02,188.06)rwPath.addCurveToPoint(CGPointMake(56.52,108.28),controlPoint1:CGPointMake(89.24,187.23),controlPoint2:CGPointMake(56.56,109.11)rwPath.addCurveToPoint(CGPointMake(64.02,102.25),controlPoint1:CGPointMake(56.47,107.75),controlPoint2:CGPointMake(59.24,105.56)rwPath.addCurveToPoint(CGPointMake(101.42,67.57),controlPoint1:CGPointMake(81.99,89.78),controlPoint2:CGPointMake(93.92,78.72)rwPath.addCurveToPoint(CGPointMake(108.38,30.65),controlPoint1:CGPointMake(110.28,54.47),controlPoint2:CGPointMake(113.01,39.96)rwPath.addCurveToPoint(CGPointMake(10.35,0.41),controlPoint1:CGPointMake(99.66,13.17),controlPoint2:CGPointMake(64.11,2.16)rwPath.addLineToPoint(CGPointMake(0.22,0.07)rwPath.addLineToPoint(CGPointMake(0.22,124.79)rwPath.closePath()/3funcsetUpRWLayer()rwLayer.path=rwPath.CGPathrwLayer.fillColor=rwColor.CGColorrwLayer.fillRule=kCAFillRuleNonZerorwLayer.lineCap=kCALineCapButtrwLayer.lineDashPattern=nilrwLayer.lineDashPhase=0.0rwLayer.lineJoin=kCALineJoinMiterrwLayer.lineWidth=1.0rwLayer.miterLimit=10.0rwLayer.strokeColor=rwColor.CGColoroverridefuncviewDidLoad()super.viewDidLoad()/4setUpRWPath()setUpRWLayer()someView.layer.addSublayer(rwLayer)代码解释:创建颜色、路径、图形图层对象。绘制图形图层路径。如果不喜欢编写生硬的绘图代码的话,你可以尝试PaintCode这款软件,可以利用简便的工具进行可视化绘制,支持导入现有的矢量图(SVG)和Photoshop(PSD)文件,并自动生成代码。设置图形图层。路径设为第二步中绘制的CGPath路径,填充色设为第一步中创建的CGColor颜色,填充规则设为非零(non-zero),即默认填充规则。填充规则共有两种,另一种是奇偶(even-odd)。不过示例代码中的图形没有相交路径,两种填充规则的结果并无差异。非零规则记从左到右的路径为+1,从右到左的路径为-1,累加所有路径值,若总和大于零,则填充路径围成的图形。从结果上来讲,非零规则会填充图形内部所有的点。奇偶规则计算围成图形的路径交叉数,若结果为奇数则填充。这样讲有些晦涩,还是有图有真相:右图围成中间五边形的路径交叉数为偶数,故中间没有填充,而围成每个三角的路径交叉数为奇数,故三角部分填充颜色。调用路径绘制和图层设置代码,并把图层添加到视图结构树。上述代码绘制的图标:顺便看看使用PaintCode的效果图:图层演示应用中,你可以随意修
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!