6 Specialzed layers 特殊层 第一部分 读书笔记

6?Specialzed?layers 特殊层? 第一部分 ?读书笔记

?

Specialization is a feature of every complex organization.

专注是每个复杂系统的特性

Catharine R. Stimpson

?

Up to this point, we have been working with the?CALayer?class, and we have seen that it has some useful image drawing and transformation capabilities. But Core Animation layers can be used for more than just images and colors. This chapter explores some of the other layer classes that you can use to extend Core Animation‘s drawing capabilities.

这章我们将研究能用来扩展core animation 绘制能力的的其他
的类。

CAShapeLayer

In Chapter 4, "Visual Effects," you learned how to use?CGPath?to create arbitrarily shaped shadows without using images. It would be neat if we could create arbitrarily shaped layers in the same way.

?

CAShapeLayer?is a layer subclass that draws itself using vector graphics instead of a bitmap image. You specify attributes such as color and line thickness, define the desired shape using a?CGPath, and?CAShapeLayer?renders it automatically.

你指明属性例如 color and line thickness ,用CGPath定义需要的图片,CAShapeLayer自动的把他们显示出来。?

Of course, you could use Core Graphics to draw a path directly into the contents of an ordinary?CALayer?(as in Chapter 2, "The Backing Image"), but there are several advantages to using?CAShapeLayer?instead:

你可以使用普通的CALayer,但是使用CAShaperLayer有下列好处:

?

??It‘s fast—CAShapeLayer?uses hardware-accelerated drawing and is much faster than using Core Graphics to draw an image.

更快

?

??It‘s memory efficient—A?CAShapeLayer?does not have to create a backing image like an ordinary?CALayer?does, so no matter how large it gets, it won‘t consume much memory.

内存更有效

?

??It doesn‘t ?get clipped to the layer?bounds—A?CAShapeLayer?can happily draw outside of its?bounds. Your path will not get clipped like it does when you draw into a regular?CALayer?using Core Graphics (as you saw in Chapter 2).

不会被layer bounds 剪切

?

??There‘s no pixelation ?— When you transform a?CAShapeLayer?by scaling it up or moving it closer to the camera with a 3D perspective transform, it does not become pixelated like an ordinary layer‘s backing image would.

不会像素失真

?

Creating a?CGPath

?

CAShapeLayer?can be used to draw any shape that can be represented by a?CGPath.

CAShapeLayer 能够绘制任何能用CGPath绘制的形状?

The shape doesn‘t have to be closed, and the path doesn‘t have to be unbroken, so you can actually draw several distinct shapes in a single layer. 形状不一定是闭合的,也不一定是不可分割的。

You can control the?strokeColor?and?fillColor?of the path, along with other properties such as?lineWidth?(line thickness, in points),?lineCap?(how the ends of lines look), and?lineJoin?(how the joints between lines look); but you can only set these properties once, at the layer level. If you want to draw multiple shapes with different colors or styles, you have to use a separate layer for each shape.

Listing 6.1 shows the code for a simple stick figure drawing, rendered using a single?CAShapeLayer. The?CAShapeLayer path?property is defined as a?CGPathRef, but we‘ve created the path using the?UIBezierPath?helper class, which saves us from having to worry about manually releasing the?CGPath. Figure 6.1 shows the result. It‘s not exactly a Rembrandt, but you get the idea!

Listing 6.1?Drawing a Stick Figure Using?CAShapeLayer?#import?"DrawingView.h"

?

#import?<QuartzCore/QuartzCore.h>
@interface?ViewController ()

@property?(nonatomic,?weak)?IBOutlet?UIView?*containerView;

@end

@implementation?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//create path

?

UIBezierPath?*path = [[UIBezierPath?alloc]?init];

[path?moveToPoint:CGPointMake(175,?100)];

[path?addArcWithCenter:CGPointMake(150,?100)?radius:25

startAngle:0?endAngle:2*M_PI

clockwise:YES];
[path?moveToPoint:CGPointMake(150,?125)];

?

[path?addLineToPoint:CGPointMake(150,?175)];

[path?addLineToPoint:CGPointMake(125,?225)];

[path?moveToPoint:CGPointMake(150,?175)];

[path?addLineToPoint:CGPointMake(175,?225)];

[path?moveToPoint:CGPointMake(100,?150)];

[path?addLineToPoint:CGPointMake(200,?150)];

//create shape layer

?

CAShapeLayer?*shapeLayer = [CAShapeLayer?layer];

shapeLayer.strokeColor?= [UIColor?redColor].CGColor;

shapeLayer.fillColor?= [UIColor?clearColor].CGColor;

shapeLayer.lineWidth?=?5;

?

shapeLayer.lineJoin?=?kCALineJoinRound;

shapeLayer.lineCap?=?kCALineCapRound;

shapeLayer.path?= path.CGPath;

//add it to our view

[self.containerView.layer?addSublayer:shapeLayer]; }

?

@end

Figure 6.1?A simple stick figure displayed using?CAShapeLayer

Rounded Corners, Redux

?

Chapter 2 mentioned that?CAShapeLayer?provides an alternative way to create a view with rounded corners, as opposed to using the?CALayer cornerRadius?property. Although using a?CAShapeLayer?is a bit more work, it has the advantage that it allows us to specify the radius of each corner independently.

尽管使用CAShapeLayer有点麻烦,但是可以为每个角独立的指定弧度。

We could create a rounded rectangle path manually using individual straight lines and arcs, but?UIBezierPath?actually has some convenience constructors for creating rounded rectangles automatically. The following code snippet produces a path with three rounded corners and one sharp:

//define path parameters

?

CGRect?rect =?CGRectMake(50,?50,?100,?100);

CGSize?radii =?CGSizeMake(20,?20);

UIRectCorner?corners =?UIRectCornerTopRight?|?UIRectCornerBottomRight?|?UIRectCornerBottomLeft;

//create path

?

UIBezierPath?*path = [UIBezierPath?bezierPathWithRoundedRect:rect?byRoundingCorners:corners?cornerRadii:radii];

?

?

We can use a?CAShapeLayer?with this path to create a view with mixed sharp and rounded corners.

我们可以利用CAShapeLayer 有这个path来创建一个固定的角度和圆角的view?

If we want to clip the view‘s contents to this shape, we can use our?CAShapeLayer?as the?mask?property of the view‘s backing layer instead of adding it as a sublayer. (See Chapter 4, "Visual Effects," for a full explanation of layer masks.)

CATextLayer ?

?

A user interface cannot be constructed from images alone. A well-designed icon can do a great job of conveying the purpose of a button or control, but sooner or later you‘re going to need a good old-fashioned text label.

?

?

If you want to display text in a layer, there is nothing stopping you from using the layer delegate to draw a string directly into the layer contents with Core Graphics (which is essentially how?UILabel?works).

使用layer 代理去绘制一个String 直接到layer 的content是
用Core Graphics .?

This is a cumbersome approach if you are working directly with layers, though, instead of layer-backed views.

如果你想直接与layers工作,而不是在layer-backed views时,会是笨重的方法。

You would need to create a class that can act as the layer delegate for each layer that displays text, and then write logic to determine which layer should display which string, not to mention keeping track of the different fonts, colors, and so on.

?

Fortunately, this is unnecessary. Core Animation provides a subclass of?CALayer?called?CATextLayer?that encapsulates most of the string drawing features of?UILabel?in layer form and adds a few extra features for good measure.

CATextLayer囊括了UILabel string 绘制的特性并添加了一些更好的特色。

CATextLayer?also renders much faster than?UILabel. It‘s a little-known fact that on iOS6 and earlier,?UILabel?actually uses WebKit to do its text drawing, which carries a significant performance overhead when you are drawing a lot of text.?CATextLayer?uses Core Text and is significantly faster.

Let‘s try displaying some text using a?CATextLayer. Listing 6.2 shows the code to set up and display a?CATextLayer, and Figure 6.2 shows the result.

?

Listing 6.2?Implementing a Text Label Using?CATextLayer

@interface?ViewController ()

@property?(nonatomic,?weak)?IBOutlet?UIView?*labelView;

@end

@implementation?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//create a text layer

?

CATextLayer?*textLayer = [CATextLayer?layer];

textLayer.frame?=?self.labelView.bounds;

[self.labelView.layer?addSublayer:textLayer];

//set text attributes

?

textLayer.foregroundColor?= [UIColor?blackColor].CGColor;

textLayer.alignmentMode?=?kCAAlignmentJustified;

textLayer.wrapped?=?YES;

//choose a font

UIFont?*font = [UIFont?systemFontOfSize:15];

//set layer font

?

CFStringRef?fontName = (__bridge?CFStringRef)font.fontName;

CGFontRef?fontRef =?CGFontCreateWithFontName(fontName);

textLayer.font?= fontRef;

textLayer.fontSize?= font.pointSize;

CGFontRelease(fontRef);

//choose some text

NSString?*text =?@"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc \

elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis";

//set layer text

textLayer.string?= text; }

?

@end

?

Figure 6.2?A plain text label implemented using?CATextLayer

?

If you look at this text closely, you‘ll see that something is a bit odd; the text is pixelated. That‘s because it‘s not being rendered at Retina resolution. Chapter 2 mentioned the?contentsScale?property, which is used to determine the resolution at which the layer contents are rendered. The?contentsScale?property always defaults to 1.0 instead of the screen scale factor. If we want Retina-quality text, we have to set the?contentsScale?of our?CATextLayer?to match the screen scale using the following line of code:需要设置contentsScale属性
来设为screen scale 因子。

textLayer.contentsScale?= [UIScreen?mainScreen].scale;

?

This solves the pixelation problem (see Figure 6.3).

The?CATextLayer font?property is not a?UIFont, it‘s a?CFTypeRef.

CATextLayer ?font 属性不是一个UIFont,是CFTypeRef。

This allows you to specify the font using either a?CGFontRef?or a?CTFontRef?(a Core Text font), depending on your requirements. The font size is also set independently using the?fontSize?property, because?CTFontRef?and?CGFontRef?do not encapsulate the point size like?UIFont?does. The example shows how to convert from a?UIFont?to a?CGFontRef.

?

Also, the?CATextLayer string?property is not an?NSString?as you might expect, but is typed as?id.

CATextLayer string属性不是NSString,而是id类型的。

This is to allow you the option of using an?NSAttributedString?instead of an?NSString?to specify the text (NSAttributedString?is not a subclass of?NSString). Attributed strings are the mechanism that iOS uses for rendering styled text. They specify?style runs, which are specific ranges of the string to which metadata such as font, color, bold, italic, and so forth are attached.

Rich Text

?

In iOS 6, Apple added direct support for attributed strings to?UILabel?and to other UIKit text views.

在iOS6上,苹果提供了一个attributed strings 给UILabel 和其他UIKit text views .

This is a handy feature that makes attributed strings much easier to work with, but?CATextLayer?has supported attributed strings since its introduction in iOS 3.2; so if you still need to support earlier iOS versions with your app,?CATextLayer?is a great way to add simple rich text labels to your interface without having to deal with the complexity of Core Text or the hassle of using a?UIWebView.

Let‘s modify the example to use an?NSAttributedString?(see Listing 6.3). On iOS 6 and above we could use the new?NSTextAttributeName?constants to set up our string

attributes, but because the point of the exercise is to demonstrate that this feature also works on iOS 5 and below, we‘ve used the Core Text equivalents instead. This means that you‘ll need to add the Core Text framework to your project; otherwise, the compiler won‘t recognize the attribute constants.

Figure 6.4 shows the result. (Note the red, underlined text.)

Listing 6.3?Implementing a Rich Text Label Using?NSAttributedString

?

#import?"DrawingView.h"

#import?<QuartzCore/QuartzCore.h>

#import?<CoreText/CoreText.h>

@interface?ViewController ()
@property?(nonatomic,?weak)?IBOutlet?UIView?*labelView;?@end
@implementation?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//create a text layer

?

CATextLayer?*textLayer = [CATextLayer?layer];

textLayer.frame?=?self.labelView.bounds;

textLayer.contentsScale?= [UIScreen?mainScreen].scale;

[self.labelView.layer?addSublayer:textLayer];

//set text attributes

textLayer.alignmentMode?=?kCAAlignmentJustified; textLayer.wrapped?=?YES;

//choose a font

UIFont?*font = [UIFont?systemFontOfSize:15];

//choose some text

NSString?*text =?@"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc \ elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis";

//create attributed string

NSMutableAttributedString?*string =?nil;
string = [[NSMutableAttributedString?alloc]?initWithString:text];

//convert UIFont to a CTFont

?

CFStringRef?fontName = (__bridge?CFStringRef)font.fontName;

CGFloat?fontSize = font.pointSize;

CTFontRef?fontRef =?CTFontCreateWithName(fontName, fontSize,?NULL);

//set text attributes

NSDictionary?*attribs =?@{
(__bridge id)kCTForegroundColorAttributeName:

(__bridge id)[UIColor?blackColor].CGColor, (__bridge id)kCTFontAttributeName: (__bridge id)fontRef

?

};

[string?setAttributes:attribs?range:NSMakeRange(0, [text?length])];

attribs =?@{

(__bridge id)kCTForegroundColorAttributeName: (__bridge id)[UIColor?redColor].CGColor, (__bridge id)kCTUnderlineStyleAttributeName:

@(kCTUnderlineStyleSingle),
(__bridge id)kCTFontAttributeName: (__bridge id)fontRef

};
[string?setAttributes:attribs?range:NSMakeRange(6,?5)];

//release the CTFont we created earlier

CFRelease(fontRef);

//set layer text

textLayer.string?= string; }

?

@end

?

?

Figure 6.4?A rich text label implemented using?CATextLayer

Leading and Kerning

?

It‘s worth mentioning that the?leading?(line spacing) and?kerning?(spacing between letters) for text rendered using?CATextLayer?is not completely identical to that of the string rendering used by?UILabel?due to the different drawing implementations (Core Text and WebKit, respectively).

leading 行间距
和kerning 两个字符的间距?

?

The extent of the discrepancy varies (depending on the specific font and characters used) and is generally fairly minor, but you should keep this mind if you are trying to exactly match appearance between regular labels and a?CATextLayer.

一般差距很小,但是一般情况下很少,但是如果你要注意这事在使用普通的labels和CATextLayer的时候。

A?UILabel?Replacement

We‘ve established that?CATextLayer?has performance benefits over?UILabel, as well as some additional layout options and support for rich text on iOS 5. But it‘s fairly cumbersome to use by comparison to a regular label. If we want to make a truly usable replacement for?UILabel, we should be able to create our labels in Interface Builder, and they should behave as much as possible like regular views.

?

We could subclass?UILabel?and override its methods to display the text in a?CATextLayer?that we‘ve added as a sublayer, but we‘d still have the redundant empty backing image created by the presence of?UILabel -drawRect:?method. And because?CALayer?doesn‘t support autoresizing or autolayout, a sublayer wouldn‘t track the size of the view?bounds?automatically, so we would need to manually update the sublayer bounds every time the view is resized.

我们可以创建UILabel 的子类并重写它的方法来展示我们添加到为一个sublayer的CATextLayer.

What we really want is a?UILabel?subclass that actually uses a?CATextLayer?as its backing layer, then it would automatically resize with the view and there would be no redundant backing image to worry about.

?

As we discussed in Chapter 1, "The Layer Tree," every?UIView?is backed by an instance of?CALayer. That layer is automatically created and managed by the view, so how can we substitute a different layer type? We can‘t replace the layer once it has been created, but if we subclass?UIView, we can override the +layerClass?method to return a different layer subclass at creation time.?UIView?calls the +layerClass?method during its initialization, and uses the class it returns to create its backing layer.

但是如果我们继承UIView,我们可以重载+layerClass 方法
返回一个不同的layer 子类在创建的时候。UIView调用layerClass 方法在初始化的时候,使用这个类返回创建的backing layer.

?

Listing 6.4 shows the code for a?UILabel?subclass called?LayerLabel?that draws its text using a?CATextLayer?instead of the using the slower?–drawRect:?approach that an ordinary?UILabel?uses.?LayerLabel?instances can either be created program-matically or via Interface Builder by adding an ordinary label to the view and setting its class to?LayerLabel.

?

Listing 6.4?LayerLabel, a?UILabel?Subclass That Uses?CATextLayer

#import?"LayerLabel.h"

?

#import?<QuartzCore/QuartzCore.h>

@implementation?LayerLabel

+ (Class)layerClass {

?

//this makes our label create a CATextLayer

//instead of a regular CALayer for its backing layer

return?[CATextLayer?class];

?

}

- (CATextLayer?*)textLayer {

?

return?(CATextLayer?*)self.layer;

}

- (void)setUp {

//set defaults from UILabel settings

?

self.text?=?self.text;

self.textColor?=?self.textColor;

self.font?=?self.font;

?

//we should really derive these from the UILabel settings too

//but that‘s complicated, so for now we‘ll just hard-code them

[self?textLayer].alignmentMode?=?kCAAlignmentJustified;

?

[self?textLayer].wrapped?=?YES;

[self.layer?display];

?

}

  • - (id)initWithFrame:(CGRect)frame {

    //called when creating label programmatically

    if?(self?= [super?initWithFrame:frame]) {

    [self?setUp];

  • }

    return self; }

  • - (void)awakeFromNib {

    //called when creating label using Interface Builder

    [self?setUp];

  • }
  • - (void)setText:(NSString?*)text {

    super.text?= text;

    //set layer text

    [self?textLayer].string?= text; }

  • - (void)setTextColor:(UIColor?*)textColor {

    super.textColor?= textColor;

    //set layer text color

    [self?textLayer].foregroundColor?= textColor.CGColor; }

  • - (void)setFont:(UIFont?*)font {

    super.font?= font;

    //set layer font

    CFStringRef?fontName = (__bridge?CFStringRef)font.fontName;?CGFontRef?fontRef =?CGFontCreateWithFontName(fontName); [self?textLayer].font?= fontRef;
    [self?textLayer].fontSize?= font.pointSize;

?

CGFontRelease(fontRef);

}

@end

If you run the sample code, you‘ll notice that the text isn‘t pixelated even though we aren‘t setting the?contentsScale?anywhere. Another benefit of implementing?CATextLayer?as a backing layer is that its?contentsScale?is automatically set by the view.

In this simple example, we‘ve only implemented a few of the styling and layout properties of?UILabel, but with a bit more work we could create a?LayerLabel?class that supports the full functionality of?UILabel?and more (you will find several such classes already available as open source projects online).

If you only intend to support iOS 6 and above, a?CATextLayer-based label may be of limited use. But in general, using +layerClass?to create views backed by different layer types is a clean and reusable way to utilize?CALayer?subclasses in your apps.

CATransformLayer

When constructing complex objects in 3D, it is convenient to be able to organize the individual elements hierarchically. For example, suppose you were making an arm: You would want the hand to be a child of the wrist, which would be a child of the forearm, which would be a child of the elbow, which would be a child of the upper arm, which would be a child of the shoulder, and so on.

The reason for this is that it allows you to move each section independently. Pivoting the elbow would move the lower arm and hand but not the shoulder. Core Animation layers easily allow for this kind of hierarchical arrangement in?2D,?but in 3D it‘s not possible because each layer flattens its children into a single plane (as explained in Chapter 5, "Transforms").

CATransformLayer?solves this problem. A?CATransformLayer?is unlike a regular?CALayer?in that it cannot display any content of its own; it exists only to host a transform that can be applied to its sublayers.?CATransformLayer?does not flatten its sublayers, so it can be used to construct a hierarchical 3D structure, such as our arm example.

Creating an arm programmatically would require rather a lot of code, so we‘ll demonstrate this with something a bit simpler: In the cube example in Chapter 5, we worked around the layer-flattening problem by rotating the?camera?instead of the cube by using the?sublayerTransform?of the containing layer. This is a neat trick, but only works for a single object. If our scene contained two cubes, we would not be able to rotate them independently using this technique.

So, let‘s try it using a?CATransformLayer?instead. The first problem to address is that we constructed our cube in Chapter 5 using views rather than standalone layers. We cannot place a view-backing layer inside another layer that is not itself a view-backing layer without messing up the view hierarchy. We could create a new?UIView?subclass backed by a?CATransformLayer?(using the +layerClass?method), but to keep things simple for our example, let‘s just re-create the cube using standalone layers instead of views. This means we can‘t display buttons and labels on our cube faces like we did in Chapter 5, but we don‘t need to do that right now.

Listing 6.5 contains the code. We position each cube face using the same basic logic we used in Chapter 5. But instead of adding the cube faces directly to the container view‘s backing layer as we did before, we place them inside a?CATransformLayer?to create a standalone cube object, and then place two such cubes into our container. We‘ve colored the cube faces randomly so as to make it easier to distinguish them without labels or lighting. Figure 6.5 shows the result.

?

Listing 6.5?Assembling a 3D Layer Hierarchy Using?CATransformLayer

@interface?ViewController ()

@property?(nonatomic,?weak)?IBOutlet?UIView?*containerView;?@end
@implementation?ViewController

- (CALayer?*)faceWithTransform:(CATransform3D)transform {

//create cube face layer

CALayer?*face = [CALayer?layer];
face.frame?=?CGRectMake(-50, -50,?100,?100);

//apply a random color

?

CGFloat?red = (rand() / (double)INT_MAX);

CGFloat?green = (rand() / (double)INT_MAX);

CGFloat?blue = (rand() / (double)INT_MAX);

face.backgroundColor?= [UIColor?colorWithRed:red?

green:green?blue:blue

?

alpha:1.0].CGColor;

?

//apply the transform and return

face.transform?= transform;

?

return?face;

}

?

?

- (CALayer?*)cubeWithTransform:(CATransform3D)transform {

//create cube layer

CATransformLayer?*cube = [CATransformLayer?layer];

//add cube face 1

?

CATransform3D?ct =?CATransform3DMakeTranslation(0,?0,?50);

[cube?addSublayer:[self?faceWithTransform:ct]];

//add cube face 2

?

ct =?CATransform3DMakeTranslation(50,?0,?0);

ct =?CATransform3DRotate(ct,?M_PI_2,?0,?1,?0);

[cube?addSublayer:[self?faceWithTransform:ct]];

//add cube face 3

?

ct =?CATransform3DMakeTranslation(0, -50,?0);

ct =?CATransform3DRotate(ct,?M_PI_2,?1,?0,?0);

[cube?addSublayer:[self?faceWithTransform:ct]];

//add cube face 4

?

ct =?CATransform3DMakeTranslation(0,?50,?0);

ct =?CATransform3DRotate(ct, -M_PI_2,?1,?0,?0);

[cube?addSublayer:[self?faceWithTransform:ct]];

//add cube face 5

?

ct =?CATransform3DMakeTranslation(-50,?0,?0);

ct =?CATransform3DRotate(ct, -M_PI_2,?0,?1,?0);

[cube?addSublayer:[self?faceWithTransform:ct]];

//add cube face 6

?

ct =?CATransform3DMakeTranslation(0,?0, -50);

ct =?CATransform3DRotate(ct,?M_PI,?0,?1,?0);

[cube?addSublayer:[self?faceWithTransform:ct]];

//center the cube layer within the container

?

CGSize?containerSize =?self.containerView.bounds.size;

cube.position?=?CGPointMake(containerSize.width?/?2.0,

containerSize.height?/?2.0);

//apply the transform and return

cube.transform?= transform;

return?cube; }

  • - &nbsp;&nbsp;(void)viewDidLoad {

[super?viewDidLoad];

//set up the perspective transform

CATransform3D?pt =?CATransform3DIdentity; pt.m34?= -1.0?/?500.0;?self.containerView.layer.sublayerTransform?= pt;

//set up the transform for cube 1 and add it

?

CATransform3D?c1t =?CATransform3DIdentity;

c1t =?CATransform3DTranslate(c1t, -100,?0,?0);

CALayer?*cube1 = [self?cubeWithTransform:c1t];

[self.containerView.layer?addSublayer:cube1];

//set up the transform for cube 2 and add it

?

CATransform3D?c2t =?CATransform3DIdentity;

c2t =?CATransform3DTranslate(c2t,?100,?0,?0);

c2t =?CATransform3DRotate(c2t, -M_PI_4,?1,?0,?0);

c2t =?CATransform3DRotate(c2t, -M_PI_4,?0,?1,?0);

CALayer?*cube2 = [self?cubeWithTransform:c2t];

[self.containerView.layer?addSublayer:cube2];

}

?

@end

?

Figure 6.5?Two cubes with shared perspective but different transforms applied

时间: 2024-11-06 21:54:20

6 Specialzed layers 特殊层 第一部分 读书笔记的相关文章

6 Specialzed layers 特殊层 第二部分 读书笔记

CAGradientLayer ? CAGradientLayer?is used to generate a smooth gradient between two or more colors. 是用来产生渐变色的. It's possible to replicate the appearance of a?CAGradientLayer?using Core Graphics to draw into an ordinary layer's backing image, but the

《内核设计与实现》第一章读书笔记

<内核设计与实现>第一章读书笔记 第一章:Linux内核简介 1.1 Unix的历史 Unix强大的特点 A.简洁,几百个系统调用,明确的设计目的 B.文件对待所有东西 C.移植性强(C语言) D.进程创建快,使用fork()系统调用. E.进程间通信元语,进程间通信机制 1.2 linux的简介 Linux系统的基础是内核.C库.工具库和系统的基本工具. 1.3 操作系统和内核简介 内核:管理者,操作系统的核心 通常一个内核由负责响应中断的中断服务程序和网络.进程间通信等系统服务共同组成.

第一周读书笔记《构建之法》

构建之法读书笔记 #wmd-preview h1 { color: #0077bb } 构建之法读书笔记 沈三景 PB15061249 软件工程 读书笔记 前言 开学前两周,杂事颇多,没有充足的时间阅读<构建之法>,只能每天在睡前阅读约半小时,故只看了前三章.虽如此,但仍收获很多,下面就是我对前四章内容的一些看法和理解,如有理解偏颇之处,望见谅. 第一章 概论 本章主要介绍了软件工程是什么?软件工程的目标是什么?为了解决前一个问题,作者首先提出了两个等式: 程序 = 数据结构 + 算法 软件

Android深度探索(卷一):HAL与驱动开发第一章节读书笔记

在课下我学习了Android深度探索(卷一)这本书.该课本的第一章节,详细介绍了如何搭建和使用Ubuntn Linux12.04 LTS.Android模拟器和S3C6410开发板. 首先,我知道了Android是一个非常优秀的嵌入式操作系统.Android的系统架构分为四层:Linux内核.c/c++代码库.Android SDK API和应用程序. 其次,是Android系统的移植.Android移植分为两部分:应用移植和系统移植.应用移植是指将应用程序层的应用程序移植到某一个特定的硬件平台

《构建之法》第一章读书笔记

工程有了一个初步的了解.介绍了软件工程里的一些基本概念,软件开发的几个阶段.软件工程的特殊性.目标以及软件工程与计算机科学之间的联系与区别.    软件工程作为一门新兴的学科,是连接计算机硬件和传统机械工程的一个桥梁.起先,我所认为的软件工程单纯的只是编程,通过算法实现正确的输出而已.但在构建之法的第一章中,我认识到会写程序只是一个合格的软件工程师最基本的素质.一个完整的项目,应该在需求分析,软件构架设计.代码实现.程序测试.软件发布运营及维护每个阶段都尽职尽责,并结合用户体验去完善软件的每一个

《CLR.via.C#第三版》第一部分读书笔记(一)

最近开始仔细研读<CLR.via.C#第三版>这本书.读pdf文档确实很累.建议有条件的朋友还是买书看吧. 我的笔记用来记录我对这本书的理解,简化下逻辑,对每个部分我觉得是要点的进行归纳总结.特别基础的东西不会做过多的阐述. 第一部分讲的是CLR基础. 首先还是重新说下CLR的概念:“CLR 是一个可由多种编程语言使用的“运行时”.可用任何编程语言来开发代码,只要编译器是面向CLR的就可以了”.这里要重新解释下“只要编译器是面向CLR的就可以了”这句话.初学者一般不认同.net平台跨语言,或者

《深入理解计算机系统》 第一章读书笔记

最近开始啃CSAPP,买了英文版,看得比较慢.只有先理解系统才能在更多方面学的更明其实质 Chapter1: * 一份hello.c代码的编译分为四个阶段:1.Pre-processor:编译预处理,就是把#include后面的库代码加入到程序中,生成hello.i的文件. 2.Complier:用编译器把hello.i的C代码翻译成汇编语言,并生成:hello.s文件.(汇编语言是高级语言转为机器码的一个中间过程) 3.Assembler:汇编机把汇编语言翻译成机器二进制代码,生成hello.

&lt;java编程思想&gt;第一章读书笔记二

7.伴随多态的可互换对象 前面说了继承,我们知道继承中存在基类(父类)以及导出类(子类),不知道大家有没有遇到过这种情况?就是在向一个方法中传递一个对象作为参数时,我们往往会选择传递一个基类而不是一个子类,为什么要这么做呢?其实原因也很简单,说的高大上一点就是这样做有利于代码的健壮性和可扩展性,说的详细还是有利于代码的健壮性和可扩展性,更重要的也就是可扩展性. 还拿喝可乐的例子来说,如果你传递的参数对象是可乐,那么不管你是给我百事可乐还是可口可乐我都可以接受啊,但是如果你传递的参数仅仅是百事可乐

第一章读书笔记--关于View

Chapter1 Views Chapter1 Views The Window Experimenting With Views Subview and SuperView 可见性和透明度Visibility and Opacity Frame Bounds and Center 窗口坐标和屏幕坐标 Transform Trait Collection and Size Classes Layout 1 Autoresizing 2 AutoLayout 21 Constraints 22 A