美文网首页iOS进阶指南iOS DeveloperiOS 开发
iOS开发(高级特性)——Quartz2D

iOS开发(高级特性)——Quartz2D

作者: 猿哥媛姐 | 来源:发表于2016-05-05 12:34 被阅读241次

    What is Quartz2D

    UIView及其子类的应用目前比较熟悉了,下面开始学习一下Quartz2D。我们从名字上来大致猜测一下这个东西是干吗的,2D好说应该是说的2维和3D不同。那么Quartz又是个啥呢?Quartz的本意是石英石,也有石英表的意思。在Java中有个叫Quartz的开源的作业调度框架,估计是取其石英表的含义。但是在苹果开发中,这个名字到底怎么解释,还真猜不到。本来想望文知意的,结果不太靠谱,那我们直接先看一看苹果对Quartz 2D的描述

    Quartz 2D is an advanced, two-dimensional drawing engine available for iOS application development and to all Mac OS X application environments outside of the kernel. Quartz 2D provides low-level, lightweight 2D rendering with unmatched output fidelity regardless of display or printing device. Quartz 2D is resolution- and device-independent; you don’t need to think about the final destination when you use the Quartz 2D application programming interface (API) for drawing.

    The Quartz 2D API is easy to use and provides access to powerful features such as transparency layers, path-based drawing, offscreen rendering, advanced color management, anti-aliased rendering, and PDF document creation, display, and parsing.

    The Quartz 2D API is part of the Core Graphics framework, so you may see Quartz referred to as Core Graphics or, simply, CG

    这么一大段话,我们找几个关键字:drawing engine, resolution, device-independent, API。

    这几个关键词加起来就是说,我们可以调用Quartz 2D的接口来绘图。至于后面的简单易用,功能强大这一类的描述,看看就好,不必较真。

    我们已经知道了Quartz2D是什么,也知道它能干什么,接下来就是学习它是怎么做的。

    When to use Quartz2D

    讨论怎么用之前,我们先了解一下什么时候用,即应用场景。还是看苹果给的东西吧,毕竟这玩意都是他们搞出来的。

    Draw graphics

    Provide graphics editing capabilities in an application

    Create or display bitmap images

    Work with PDF documents

    对这上面这几种翻译一下:

    1 )画图

    这里说的画图,应该是指在界面上画线条,多边形,弧形等。如股票软件中的各种线条。

    2)提供图形编辑功能

    图片编辑功能复杂一点,如照片处理一类的。

    3)创建或者显示位图

    4)处理PDF文档

    How to use Quartz2D


    concept

    我们先理解一些概念,不然理解后面说的东西比较费劲。

    1)Painter's model

    图1

    看图1来理解这个所谓的粉刷模型,就是一个粉刷效果,后面的掩盖前面的。

    2)The Graphics Context

    这个可以理解为绘画环境,比如涂鸦绘画环境就是墙壁,油画的绘画环境就是画布。开发中的绘画环境有:位图,PDF,窗口,图层。

    Creating a Window Graphics Context,API本身不能获取window的Context,需要在Cocoa framework中获取一个。

    CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];//

    Creating a PDF Graphics Context

    CGPDFContextCreateWithURL

    CGPDFContextCreate

    Creating a Bitmap Graphics Context

    CGBitmapContextCreate

    UIGraphicsBeginImageContextWithOptions//iOS环境中用这个,避免坐标系统的不同

    3)Opaque Data Types

    数据类型很多,我们用到的时候在详细了解。下面列一下这些数据类型和用处:

    CGPathRef, used for vector graphics to create paths that you fill or stroke. SeePaths.

    CGImageRef, used to represent bitmap images and bitmap image masks based on sample data that you supply. SeeBitmap Images and Image Masks.

    CGLayerRef, used to represent a drawing layer that can be used for repeated drawing (such as for backgrounds or patterns) and for offscreen drawing. SeeCore Graphics Layer Drawing

    CGPatternRef, used for repeated drawing. SeePatterns.

    CGShadingRefandCGGradientRef, used to paint gradients. SeeGradients.

    CGFunctionRef, used to define callback functions that take an arbitrary number of floating-point arguments. You use this data type when you create gradients for a shading. SeeGradients.

    CGColorRefandCGColorSpaceRef, used to inform Quartz how to interpret color. SeeColor and Color Spaces.

    CGImageSourceRefandCGImageDestinationRef, which you use to move data into and out of Quartz. SeeData Management in Quartz 2DandImage I/O Programming Guide.

    CGFontRef, used to draw text. SeeText.

    CGPDFDictionaryRef,CGPDFObjectRef,CGPDFPageRef,CGPDFStream,CGPDFStringRef,andCGPDFArrayRef, which provide access to PDF metadata. SeePDF Document Creation, Viewing, and Transforming.

    CGPDFScannerRefandCGPDFContentStreamRef, which parse PDF metadata. SeePDF Document Parsing.

    CGPSConverterRef, used to convert PostScript to PDF. It is not available in iOS. SeePostScript Conversion.

    4)Coordinate Systems

    在二维中绘图,坐标系的概念必不可少。指标系统大家还是比较熟悉的,过多的解释没有必要,值得注意的是在iOS的显示中坐标原点的位置不在左下角而在左上角。

    5)Path

    我们想要画一个三角形或一个圆,在现实中我们可以根据抽象的思维,随意画出三角形和圆,但是计算机怎样能够准确的画出我们想要的图案呢。Path就是用来定义图形的。可以理解为Path表示了图形的轮廓,按照这个轮廓,通过填充,描绘就可以准确的得到我们想要的图案。

    直接在Context上画

    CGContextMoveToPoint

    CGContextAddLineToPoint

    CGContextAddLines

    CGContextAddArc

    CGContextAddArcToPoint

    CGContextAddCurveToPoint

    CGContextAddQuadCurveToPoint

    CGContextClosePath

    CGContextAddEllipseInRect

    CGContextAddRect

    创建可复用的Path

    CGPathCreateMutable, which replacesCGContextBeginPath

    CGPathMoveToPoint, which replacesCGContextMoveToPoint

    CGPathAddLineToPoint, which replacesCGContextAddLineToPoint

    CGPathAddCurveToPoint, which replacesCGContextAddCurveToPoint

    CGPathAddEllipseInRect, which replacesCGContextAddEllipseInRect

    CGPathAddArc, which replacesCGContextAddArc

    CGPathAddRect, which replacesCGContextAddRect

    CGPathCloseSubpath, which replacesCGContextClosePath

    将Path加到Context上CGContextAddPath.

    有了Path了我们就可以涂鸦啦,哦不对,是Paint.有两种方式,填充(filling)和笔画(stroking)。

    Parameters That Affect Stroking

    Parameter:Function to set parameter value

    Line width:CGContextSetLineWidth//线宽度

    Line join:CGContextSetLineJoin//连接处的风格设置

    Line cap:CGContextSetLineCap//两端的风格

    Miter limit:CGContextSetMiterLimit //

    Line dash pattern:CGContextSetLineDash

    Stroke color space:CGContextSetStrokeColorSpace

    Stroke color:CGContextSetStrokeColorCGContextSetStrokeColorWithColor

    Stroke pattern:CGContextSetStrokePattern

    Functions that fill paths

    CGContextEOFillPath

    Fills the current path using the even-odd rule.

    CGContextFillPath

    Fills the current path using the nonzero winding number rule.

    CGContextFillRect

    Fills the area that fits inside the specified rectangle.

    CGContextFillRects

    Fills the areas that fits inside the specified rectangles.

    CGContextFillEllipseInRect

    Fills an ellipse that fits inside the specified rectangle.

    CGContextDrawPath

    Fills the current path if you pass kCGPathFill(nonzero winding number rule) or kCGPathEOFill(even-odd rule). Fills and strokes the current path if you pass kCGPathFillStroke or kCGPathEOFillStroke.

    6)Color and Color Space

    颜色的相关内容。

    7) Transform

    如图,Transform说的就是这样的一些变换。缩放、移动,旋转等。有坐标系作为基础,这些变化对应相应的数学知识就很好理解了。简单的直接调用API即可,复杂的变换可能要涉及到数学内容,比如矩阵变换等,这些东西不在讨论范围。明白可能用到这些就好了

    8)Partterns

    9)Shadows

    阴影可以让2D的图形有3D的视觉效果。

    10)Gradient

    有时候一种颜色,或者简单叠加的颜色看起来很枯燥乏味,我们用渐变让图形更丰富。

    理解了这些东西了,也很无聊的了,来个例子吧,看看这些东西到底是怎么玩的。

    @implementation MyQuartzView

    - (id)initWithFrame:(NSRect)frameRect

    {

    self = [super initWithFrame:frameRect];

    return self;

    }

    - (void)drawRect:(NSRect)rect

    {

    CGContextRef myContext = [[NSGraphicsContext

    currentContext] graphicsPort]; // 1

    // ********** Your drawing code here **********// 2

    CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);// 3

    CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 ));// 4

    CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);// 5

    CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));// 6

    }

    @end

    得到的效果如图2

    1.获取Context

    2.准备绘图

    3.设置填充颜色(涉及到Color相关内容)

    4.填充矩形区域(涉及到path相关内容)

    5.再次设置颜色(透明相关)

    6.填充矩形区域(根据Painter's Model 覆盖,重叠区域的覆盖)

    图2

    Demo

    1)QuartzLines

    简单画线

    -(void)drawInContext:(CGContextRef)context

    {

    // Drawing lines with a white stroke color

    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

    // Draw them with a 2.0 stroke width so they are a bit more visible.

    CGContextSetLineWidth(context, 2.0);

    // Draw a single line from left to right

    CGContextMoveToPoint(context, 10.0, 30.0);

    CGContextAddLineToPoint(context, 310.0, 30.0);

    CGContextStrokePath(context);

    // Draw a connected sequence of line segments

    CGPoint addLines[] =

    {

    CGPointMake(10.0, 90.0),

    CGPointMake(70.0, 60.0),

    CGPointMake(130.0, 90.0),

    CGPointMake(190.0, 60.0),

    CGPointMake(250.0, 90.0),

    CGPointMake(310.0, 60.0),

    };

    // Bulk call to add lines to the current path.

    // Equivalent to MoveToPoint(points[0]); for(i=1; i < count,++i) AddLineToPoint(points[i]);

    CGContextAddLines(context, addLines, sizeof(addLines)/sizeof(addLines[0]));

    CGContextStrokePath(context);

    CGPoint strokeSegments[] =

    {

    CGPointMake(10.0, 150.0),

    CGPointMake(70.0, 120.0),

    CGPointMake(130.0, 150.0),

    CGPointMake(190.0, 120.0),

    CGPointMake(250.0, 150.0),

    CGPointMake(310.0, 120.0),

    };

    // Bulk call to stroke a sequence of line segments.

    CGContextStrokeLineSegments(context, strokeSegments, sizeof(strokeSegments)/sizeof(strokeSegments[0]));  

    cap and join

    -(void)drawInContext:(CGContextRef)context

    {

    // Drawing lines with a white stroke color

    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

    // Preserve the current drawing state

    CGContextSaveGState(context);

    // Setup the horizontal line to demostrate caps

    CGContextMoveToPoint(context, 40.0, 30.0);

    CGContextAddLineToPoint(context, 280.0, 30.0);

    // Set the line width & cap for the cap demo

    CGContextSetLineWidth(context, self.width);

    CGContextSetLineCap(context, self.cap);

    CGContextStrokePath(context);

    // Restore the previous drawing state, and save it again.

    CGContextRestoreGState(context);

    CGContextSaveGState(context);

    // Setup the angled line to demonstrate joins

    CGContextMoveToPoint(context, 40.0, 190.0);

    CGContextAddLineToPoint(context, 160.0, 70.0);

    CGContextAddLineToPoint(context, 280.0, 190.0);

    // Set the line width & join for the join demo

    CGContextSetLineWidth(context, self.width);

    CGContextSetLineJoin(context, self.join);

    CGContextStrokePath(context);

    // Restore the previous drawing state.

    CGContextRestoreGState(context);

    // If the stroke width is large enough, display the path that generated these lines

    if (self.width >= 4.0) // arbitrarily only show when the line is at least twice as wide as our target stroke

    {

    CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);

    CGContextMoveToPoint(context, 40.0, 30.0);

    CGContextAddLineToPoint(context, 280.0, 30.0);

    CGContextMoveToPoint(context, 40.0, 190.0);

    CGContextAddLineToPoint(context, 160.0, 70.0);

    CGContextAddLineToPoint(context, 280.0, 190.0);

    CGContextSetLineWidth(context, 2.0);

    CGContextStrokePath(context);

    }

    }

    -(void)setCap:(CGLineCap)c

    {

    if(c != _cap)

    {

    _cap = c;

    [self setNeedsDisplay];

    }

    }

    -(void)setJoin:(CGLineJoin)j

    {

    if(j != _join)

    {

    _join = j;

    [self setNeedsDisplay];

    }

    }

    -(void)setWidth:(CGFloat)w

    {

    if(w != _width)

    {

    _width = w;

    [self setNeedsDisplay];

    }

    }

    2)QuartzPoly

    3)QuartzGradient

    4)QuartzDash

    5)QuartzPolygons

    6)QuartzCurves

    7)QuartzImages

    8)QuartzRendering

    9) QuartzClipping

    2到9的内容就不一一贴代码和贴图了。这些内容不用记得太清楚,用的时候有个印象能快速查询到相关文档既可以了。

    相关文章

      网友评论

        本文标题:iOS开发(高级特性)——Quartz2D

        本文链接:https://www.haomeiwen.com/subject/nntrrttx.html